Swiftで踏んだ地雷集

  • 52
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

XCodeのアップデートと共にどんどん改善されているSwiftですが、まだまだ発展途上という事もあり変な罠がたくさんありそうです。

まだSwiftを書き始めてまだ1ヶ月程度ですが、ちょくちょく変なトラブルに悩まされたので小ネタ集としてまとめてみます。

謎のコンパイルエラー

以下のようなネストしたクロージャのコードを書いていた時のこと。

Model.getItems({items, error in
     if let e = error {
          println(error!)
          return

     } 

     dispatch_async(dispatch_get_main_queue()) { [unowned self] in
               self.items = items
               self.tableView.reloadData()
     }
})

syntaxエラーも無いしぱっと見問題無さそうなコードなんですが、いざコンパイルすると以下のようなエラーが。

Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1

けっこうな量のコードを修正した直後で、ヒントが無さ過ぎて原因に気づくのにも一苦労・・。結局getItemsのクロージャではなく内側のdispatch_asyncへ渡しているクロージャでunowned selfを書いていたのが原因でした。どうもコンパイラの最適化で怒られているらしいんですが、イマイチ何が悪いのか理由が分からず。

ちなみにこの問題、XCode6.1.1では再現が取れませんでした。修正されたのかな?

lldbコマンドが謎のエラーを吐く

元々Objective-CだったプロジェクトでSwiftを書いていて、あるときからデバッグ中にpoコマンドで変数を覗こうとすると以下のようなエラーが出るように。

(lldb) po self
error: Error in auto-import:
failed to get module 'TargetName' from AST context:
/Users/horimislime.../TargetName-Bridging-Header.h:23:9: ...

bridge headerだしimportしているObjective-C側に何か問題がありそうと思いつつ、検討も付かずにあれこれ調べてたところ、どうやらもう一度poコマンドを叩くと普通に変数表示させられるようです。

正直謎すぎる挙動ですが、以下でも同じことが書かれています。

unable to print object ('po') in xcode6 beta 6 osx swift project: (Error in auto-import: failed to get module '__ObjC' from AST context) - Stack Overflow

ライブラリのバグ

Objective-Cだと動くけどSwiftだと動かない、シミュレータだと動くけど実機でクラッシュする、なんてものがちょくちょく。

自分がハマったのは端末のアルバム一覧を取得するコードでした。

assetsLibrary.enumerateGroupsWithTypes(ALAssetsGroupType(ALAssetsGroupAll)) { group, stop in
    ...
}

このコードだと実機で確実にクラッシュします。原因は実機のみALAssetsGroupType(ALAssetsGroupAll)の結果がおかしかったため。

(lldb) po ALAssetsGroupType(ALAssetsGroupSavedPhotos)
16
(lldb) po ALAssetsGroupType(ALAssetsGroupAll)
4294967295
(lldb) po ALAssetsGroupType(ALAssetsGroupSavedPhotos) // これは実機でもOK
16
(lldb) po ALAssetsGroupType(ALAssetsGroupAll)
error: Execution was interrupted, reason: EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xe7ffdefe).
The process has been returned to the state before expression evaluation.

全アルバム取ってきたいのにどうすりゃいいんだよ・・と思ってGithubを漁ってたら、恐らく全く同じ問題にぶちあたってると思われるコードを発見w

ParseTesting/ImagePickingViewController.swift at dc33772d64528e6be44cea8fbd483d5509a2c726 · ericandoh/ParseTesting

ALAssetsGroupAllで定義されている定数値をそのまま渡している様子。

他にもSwiftで動きが怪しいな〜とか、Objective-CのこのコードってSwiftではどう書けばいいんだ?みたいな疑問が出たら、 ググるよりもGithubのコード検索の方が便利 かもなーと思いました。

おわり

初期からSwift弄ってる人に比べたらマシだと思いますが、この短期間でも色々罠にハマって勉強になりました。小ネタですが同じ現象でハマってる人の役に立てれば。

色々悩まされたりもするけど・・・Swift楽しい!✌ ('ω' ✌ )三 ✌ ('ω') ✌ 三( ✌ 'ω') ✌

この投稿は Swift Advent Calendar 201411日目の記事です。