2014年12月19日金曜日

SwiftからCやObjective-Cのライブラリを扱うときのテクニック数点

Objective-C Bridging Headerを利用することで、Swiftは既存のいかなるC/Objective-Cコードのシンボルでも呼び出すことが可能になっています。しかしながら場合によってはSwift単体では素直に書きづらいハマりどころがあります。C/Objective-Cのラッパーを作り、Objective-C Bridging Header経由でSwiftから呼び出せば全ての問題は解決できるのですが、面倒くさいですしやはりSwift単体で何とかしたいですよね。そこでここでは素直に書きづらいハマりどころと、それを何とかしてSwift単体で解決する方法をご紹介します。

※以下の情報は2014/12/19現在のものです。Swiftは言語仕様の変化が激しいので予期せず変更されている場合があります、ご了承ください。

1. ARCに管理されていないObjective-Cオブジェクトを扱う

例えばKeychainを扱うAPIなどで、ARCに管理されていないObjective-Cオブジェクトを扱うことがあります。このような場合にはUnmanaged型を使用します。

Unmanaged型はメソッド経由でretain, release, autoreleaseを行うことができるほか、takeUnretainedValue()またはtakeRetainedValue()メソッド経由でT型のSwiftオブジェクトを取り出すことができます。

2. C言語のポインタを扱う

生のC言語のポインタを扱う場合、たいていのケースではUnsafePointer型を使うようにCのAPIがSwiftのAPIに変換されます。このとき、Swift上ではUnsafePointer型を要求するのに、C言語のAPI的にはNULLを渡したい場合には、nilを渡すことができないので、代わりにUnsafePointer.null()を渡すことができます。

UnsafePointer以外にもCOpaquePointer型やCFunctionPointer型に変換されるAPIもありますが、この場合も同様にCOpaquePointer.null()やCFunctionPointer.null()をAPIに渡してやればうまくいきます。

3. cStringUsingEncoding()メソッドの罠に注意する

SwiftにはSwiftネイティブのString型とCocoaのNSString型が存在します。基本的にはこの2つは自動的にうまい具合にブリッジされるためプログラマは違いを意識する必要がありませんが、実はcStringUsingEncoding()メソッドを使う場合にはこれが重大な問題になってきます。String.cStringUsingEncoding()は[CChar]?を、NSString.cStringUsingEncoding()はUnsafePointerを返すのです。さらにコンパイラは文字列をStringとして解釈するのを優先するため、先ほど述べたC言語のAPIに渡す際に型が合わないという理由でエラーになりがちです。

対策として上記の通り明示的にNSStringにキャストすることをおすすめします。

4. enum値のOR結合を何とかする

すみません、なんともなりませんでした(´・_・`)
例えば以下のようなコードを書くこと自体は可能なのですが、適切なenum値を得ることができません。optionsはnilになってしまいます。

どうしてもOR結合が必要なenum値が存在する場合は、現状C/Objective-Cでラッパーを作りObjective-C Bridging Header経由でSwiftから呼び出すしかないようです。


2014年9月30日火曜日

GitHub:Enterprise 環境下では CocoaPods を 0.34.0 以上にアップデートしてはいけません

タイトルの地点で結構出落ちですが、本日少々厄介な問題にぶち当たってしまったので共有いたします。

発生条件

CocoaPods 0.34.0以上を使用し、GitHub:EnterpriseのgitリポジトリをPodSpecないしSourceリポジトリとして使用している場合に発生します。

発生する問題

CocoaPodsのgitを利用するアクションが全く成功しなくなります。具体的にはpod install, pod updateなどが全く通りません。

問題の原因

公式ブログにあるとおり、0.34.0以上からCocoaPodsは高速にgitリポジトリをcloneするため--depth 1 (shallow clone) オプションを採用するようになっています。しかしながらGitHub:Enterprise側の技術的問題なのか、GitHub:Enterprise内のgitリポジトリに対するhttpないしhttps経由でのshallow cloneが成功しないため永遠にpod installやpod updateが終わりません。

対処方法

根本的にはCocoaPodsかGitHub:Enterpriseかいずれかが修正されるのを待つしかありませんが、CocoaPods側としてはあまり積極的に対応する気がないようなので、GitHub:Enterprise側に対応を期待するしかないでしょうか。もちろん全てのGitHub:Enterprise環境下で発生するとは限りませんが、いずれにせよ注意する必要があります。

2014/10/01追記

GitHub:Enterpriseに問い合わせてみたところ、こちらは既知の問題であり現在修正中で、次のリリース時に修正されるそうです。次のリリースが社内環境にデプロイされるまでの辛抱ですね。

こちらからは以上です。

2014年9月8日月曜日

Swift から Core Data を操作するときはこの2点だけ気をつけよう (Xcode 6 beta 7編)

将来的にXcode側の対応が変わる可能性が極めて高いので暫定ですが、Xcode 6 beta 7でSwiftからCore Dataを触った時に注意するポイント2点まとめです。この2点にだけ気をつければSwiftでもCore Dataは案外あっさり動きますのでご安心ください!

1. プロパティの設定の仕方


  • @NSManagedを使うこと
  • Int, BoolではなくNSNumberを使うこと。StringはStringでOK
  • Many関連にはNSSetを指定すること



2. entityNameの与え方


  • コード上ではクラス名だけを与える
  • Model Editor上ではモジュール名.クラス名(完全修飾名)を与える



Model Editorではこのようにモジュール名.クラス名の形で設定する必要があります


あとは普段Objective-Cで使っている時と同じように使えばOKです。一応、簡単なSwiftからCore Dataを操作するラッパライブラリを書いてみたので、もし宜しければ見てみてください。
https://github.com/akisute/Dove