ヤフーのSwiftコンバーターを使ってみた感想

4月に入社しました伊東です。
Objective-CのソースコードをSwift3.0に書き換える際にobjc2swiftというコンバーターを使いました。

良かった点

  • Objective-Cの文法をあまり知らなくてもある程度読めるようになる。
  • MITライセンスで、githubにオープンソースがあるところ
  • Web版とScalaで書かれたCLI版がある

悪かった点

  • コメントが消える
     コメントが消えるため、コメントが必要な場合、後から手動追加するのが面倒だった。

  • Objective-Cのヘッダーで前方宣言(@class)になってるところが残る

  • Swift2.0の構文でコンバートされる(一部Swift3.0に書き直す必要がある)

  • Objective-Cでグローバル変数になっているところは、定数クラスを作るなどする必要がある。たとえば、Objective-CでAlertOKというグローバル変数があったとしたら、SwiftではDeviceConst().AlertOKという感じに書き直す必要があった

  • オプショナルな表記に対応していない

  • Delegateデザインパターンで定義されているところがうまく変換してくれない

コンバーターが未対応なところと対応策

  • Objective-Cに#pragmaというプリプロセッサキーワードがあるとエラーになるため、perl -pe 's/^#pragma//g'とかして消す必要がある

  • コマンドでobjc2swiftを使うとき、.mと.hを一緒に渡す必要がある。(objc2swift filename.[hm]で渡せる)

ハマったところ

overrideされないメソッドがある

ViewDidLoad()以外のView Life Cycle系のメソッドがオーバーライドされない。さらにxcodeはエラーを出してくれなかった。

[エラーにならない]

func viewWillAppear(animated: Bool) {  

[正しいコード]

override func viewWillAppear(_ animated: Bool)  

クロージャーをうまく変換してくれない  

クロージャーをうまく変換してくれないため、書き換える必要がある。

[Objective-C]

defaultAction = [UIAlertAction actionWithTitle:AlertOK  
style:UIAlertActionStyleDefault  
handler:^(UIAlertAction * action) {}];  

[Swift]

defaultAction = UIAlertAction(title: DeviceConst().AlertOK,  
style: UIAlertActionStyle.default, handler: { (action:  
UIAlertAction) in })  

ファイル入出力の処理はdo catch構文に書き換える必要がある

ライブラリ関数の引数にエラーを入れず、do catch構文にして書く。

[Objective-C]

NSString *imageFilePath = [self.documentsDir stringByAppendingPathComponent:@"/ImageFiles"];  
        if (![[NSFileManager defaultManager] fileExistsAtPath:imageFilePath]) {
            NSError *error;
            [[NSFileManager defaultManager] createDirectoryAtPath:imageFilePath withIntermediateDirectories:NO attributes:nil error:&error];
            if (error) {
                NSLog(@"ImageFileDirectory error: %@", [error localizedDescription]);
                return nil;
            }
        }

[Swift]

        let imageFilePath = self.documentsDir.stringByAppendingPathComponent(path: "/ImageFiles")
        if !FileManager.default.fileExists(atPath: imageFilePath) {
            do {
                try FileManager.default.createDirectory(atPath: imageFilePath, withIntermediateDirectories: false, attributes: nil)
            } catch let error as NSError {
                print("ImageFileDirectory error: \(error.localizedDescription)")
            }
        }

まとめ

 一番メリットとして大きかったのがC言語みたいなObjective-Cの構文を見ないで済むところでした。特にSwiftになってクロージャーの部分はとてもわかりやすかったです。 Objective-Cで書かれた既存のアプリをSwiftで一から書き直すにしろ、コンバーターを使ってObjective-CをSwift書き換えるにしろ、どちらも同じくらいの労力になると思いました。