« ◇WI-1000XとQC30 | トップページ | ◇AndroidStudio3.0.1対応 »

◇Swift4対処

 swift3からswift4

iOSのappの開発環境がXcode8->Xcode9に言語がswift3->swift4に変わってしまいました。

swift2->swift3の時ほどの破壊的な酷さはないのですが、なんだかんだで時間がかかってしまいました。

 変更が必要だった記述

変更を要したのは文字列と#selector関連です。

文字列

文字列では

  • count,indexなどcharacter系
  • substring
が変わりました。


swift3では文字長を得るのに、次のようなオバカで冗長な記述が必要でした。

   let str:String = "abcdefg"
   let len:Int    = str.characters.count
これがまともになりました。
   let str:String = "abcdefg"
   let len:Int    = str.count
indexメソッドもオバカで冗長なcharactersは不要となりました。

substringは[]オペレータに変わりました。
ただし、引数はやはりオバカで冗長な記述が必要です。

   let str:String = "abcdefg"
   let sta:Int    = 2
   let end:Int    = 4
   let sub:String = str[str.index(str.startIndex,offsetBy:sta)
                        ..<
                        str.index(str.startIndex,offsetBy:end)]
当初Stringのsubstringが[]になったと聞いたときてっきり次のようなまともな記述が可能になったのだと思いました。
   let str:String = "abcdefg"
   let sta:Int    = 2
   let end:Int    = 4
   let sub:String = str[sta ..< end] // NGです。念のため
違うんですねえ、これが。
なぜstrインスタンスのインデックスを示すのに再びstrインスタンスを指定しないといけないのか全く理解できません。 このとんでもない冗長さを馬鹿げていると思わない言語センスはとても受け入れられるものではありません。

#selector

関数を#selectorで参照する次のような記述がある場合

   static let playActions:[Selector] = [
       #selector(MainEngine.play(sender_:count_:))
      ,#selector(MainEngine.stop(sender_:count_:))
      ];
参照される側の関数が"@objc"で修飾されていないと次のワーニングが出ます。
Dependency Analysis Warning
 The use of Swift 3 @objc inference in Swift 4 mode is deprecated. Please address deprecated @objc inference warnings, test your code with “Use of deprecated Swift 3 @objc inference” logging enabled, and then disable inference by changing the "Swift 3 @objc Inference" build setting to "Default" for the "XXXX" target. 
対処として@objcで修飾しても別のワーニングが出ます。
ネットに記述されている全ての作業を行ってもワーニングは消えず、最終的にはxcode9が異常を起こします。

 行った対処:メモ

行った対処を述べます。これは必ずしも一般的とは言えません。

文字列

swift3の文字列はオバカ過ぎてとても使えるものではなかったので直接は使用せず、extensionを使っていました。

応用プログラムではStringのネイティブな記述は避けていたため被害は最少で済みました。

public extension String {
   static public func length(of_:String)
                      -> Int {
      //return of_.characters.count;
      return of_.count;
      }
   public func length()
               -> Int {
      //return self.characters.count;
      return self.count;
      }
   static public func substring(start_:Int, end_:Int,of_:String)
                      -> String{
      let _start:Int = start_ < 0 ? 0 :start_;
      let _last:Int  = of_.count;
      let _end:Int   = end_   > _last ? _last :end_;
      //return of_.substring(
      //   with: of_.characters.index(of_.startIndex, offsetBy: _start)
      //       ..<
      //       of_.characters.index(of_.startIndex, offsetBy: _end)
      //       );
      return String(of_[
         of_.index(of_.startIndex, offsetBy:_start)
          ..<
         of_.index(of_.startIndex, offsetBy:_end)
         ]);
      }
   public func substring(start_:Int,end_:Int)
        -> String {
      return String.substring(start_:start_,end_:end_,of_:self);
      }
    ....

おそらく殆どのswift利用者はStringを裸で使っていることはないと思います。
swift4においてもStringはオバカで冗長なAPIを持ちますので、これがそのまま続くとは思われません。
extensionの使用は避けられませんが、方言だらけになってしまうことを心配しています。
だれかApple信者以外の人がまともで標準的なString-extensionを発表することを期待します。

#selector

最終的には参照される関数を持つクラス全てに@objcMembers修飾を施しました。

@objcMembers
public class MainEngine:NSObject {
   ...
   }
全クラスに施しても大丈夫そう(所詮swiftはObject-Cの表面をいじったデタラメ言語に過ぎません)ですが、 また仕様が変わる可能性が大きいので必要なクラスにのみ施しました。

 構文解析能力

swift4の構文解析能力は相変わらずShellレベルであり到底高級言語のそれではありません。

相変わらず空白がうまく取り扱えないようですが出てくるワーニングは少しだけ意味が通じるものになりました。

   var a:Int=1
   var b:Int= 2   // '=' must have consistent whitespace on both sides
   var c:Int =3   // '=' must have consistent whitespace on both sides
   var d:Int = 4
   //
   var e:Int=-1  // Use of unresolved operator '=-'
   var f:Int= -2 // '=' must have consistent whitespace on both sides
   var g:Int =-3 // Consecutive statements on a line must be separated by ';'
   var h:Int = -4
   if a==1  {print("a==1")  }
   if a== 1 {print("a== 1") }// Closure expression is unused
   if a ==1 {print("a ==1") }// Closure expression is unused
   if a == 1{print("a == 1")}
   if a!=1  {print("a!=1")  }// Cannot force unwrap value of non-optional type 'Int'
   if a!= 1 {print("a!= 1") }// Cannot force unwrap value of non-optional type 'Int'
   if a !=1 {print("a !=1") }// 'Int' is not convertible to 'Bool'
   if a != 1{print("a != 1")}
swift3でのワーニングは Swift入門?う~ん。。に載せてあります。


一つだけ、少しだけ進歩したのが、次の文の扱いです。

   let val1:Int = test3()
                 +test4() // Result of operator '+' id unused
swift3では単に動作不良を起こしますが、swift4ではワーニングが出るようになりました。
勿論、理想は文の終わりに;を必要とすることです。

|

« ◇WI-1000XとQC30 | トップページ | ◇AndroidStudio3.0.1対応 »

トラックバック


この記事へのトラックバック一覧です: ◇Swift4対処:

« ◇WI-1000XとQC30 | トップページ | ◇AndroidStudio3.0.1対応 »