Using Swift with Cocoa and Objective-Cのメモ(その1)
はじめに
これは、『Using Swift with Cocoa and Objective-C』を読んだ時の個人的なメモです。なので、引用はすべて『Using Swift with Cocoa and Objective-C』から。
iTunes - ブック - Apple Inc.「Using Swift with Cocoa and Objective-C」
https://itunes.apple.com/jp/book/using-swift-cocoa-objective/id888894773?mt=11
Getting Started
Basic Setup
- SwiftはCocoaやObjective-Cと互換性があるよ
Understanding the Swift Import Process
Objective-CやCのモジュールをSwiftで直接取り込むことが出来るよ
メモ: 逆に言うと、モジュールになってないものは取り込めない? 要確認具体的にはこんな感じになるよ
import Foundation
この作業で型はこんな感じになるよ
- Objective-Cの型はSwiftで該当するものに置き換えられるよ。例えば、idだとAnyObjectになるよ
- Objective-Cのコアになる型はSwiftで似たようなものに置き換えられるよ。例えば、NSStringはStringになるよ
- Objective-Cのコンセプトも置き換えられるよ。例えばポインターはオプション変数になるよ
NOTE: C++のコードを直接取り込むことは出来ないよ
Interoperability
Interacting with Objective-C APIs
- SwiftとObjective-Cには相互運用性があるよ
- つまり、片方の言語で書いたコードを、もう一つの言語から使うことが出来るよ
Initialization
Objective-Cのinit関係のメソッドは、Swiftだとイニシャライザーになるよ
最初の『init』は省略されて、残りがイニシャライザーの引数になるよ
- 『initWith』ではじまってる場合は、そこまで省略されるよ
- 残ったキーワードの最初の文字は小文字になるよ
- 残りのセレクターは、そのまま引数になるよ
メモ: 説明を読むよりコードを見たほうがわかりやすい
- Objective-Cだとこう
UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
- Swiftだとこう
let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)
Objective-Cのファクトリーメソッドは、Swiftの便利イニシャライザーになるよ
Objective-Cだとこう
UIColor *color = [UIColor colorWithRed:0.5 green:0.0 blue:0.5 alpha:1.0];
- Swiftだとこう
let color = UIColor(red: 0.5, green: 0.0, blue: 0.5, alpha: 1.0)
Accessing Properties
- Objective-Cだと引数なしで戻り値が1つのメソッドをプロパティの取得と同じように使えたけど、Swiftだとこれは出来ないよ
- SwiftからObjective-Cのクラスを使う場合、@propertyのついたプロパティだけがプロパティとして使えるよ
Working with Methods
- Objective-CのメソッドをSwiftから使う場合、セレクターがメソッドの名前と引数名になるよ
- Objective-Cのセレクターの最初の部分がメソッドの名前になるよ
- セレクターの最初の引数は、Swiftのメソッドの最初の引数になって、これは名前無しだよ
- セレクターの残りの引数は、メソッドの名前付き引数になるよ
メモ: これも、説明を読むよりコードを見たほうがわかりやすい
- Objective-Cだとこう
[myTableView insertSubview:mySubview atIndex:2];
- Swiftだとこう
myTableView.insertSubview(mySubview, atIndex: 2)
id Compatibility
Objective-CのidはSwiftだとAnyObjectプロトコルになるよ
AnyObjectを使う場合、@objc属性の付いたメソッドやプロパティなら、キャスト無しで呼び出すことが出来るよ
- もちろん、存在しないメソッドやプロパティを使うとランタイムエラーになるよ
- オプション変数やオプション連鎖を使えば、メソッドやプロパティを使うのが安全になるよ
Working with nil
- Objective-Cのオブジェクトはnilになる可能性があるから、Swiftに取り込むとオプション変数になるよ
- Objective-Cのメソッドやプロパティで得られる値が、絶対にnilにならないってわかってる場合、implicitly unwrapped optionalsを使うことも出来るよ
Extensions
- エクステンションはObjective-Cから取り込んだものにも使えるよ
- エクステンションで、既存のメソッドやプロパティをオーバーライドすることは出来ないよ
Closures
Objective-Cのブロックは、Swiftだとクロージャになるよ
Objective-Cだとこう
void (^completionBlock)(NSData *, NSError *) = ^(NSData *data, NSError *error) {/* ... */}
- Swiftだとこう
let completionBlock: (NSData, NSError) -> Void = {data, error in /* ... */}
- SwiftのクロージャとObjective-Cのブロックは互換性があるよ
- だから、ブロックを必要とするObjective-Cのメソッドに、Swiftのクロージャを渡すことが出来るよ
- Swiftの関数はクロージャと同じものだから、関数を渡すことも出来るよ
- クロージャはブロックと同じように周りの変数をキャプチャするけど、変数が変更可能だよ
- つまり、Objective-Cで『__block』を指定してたのと同じ動きがデフォルトになってるよ
Object Comparison
Swiftでは、NSObjectから派生したクラスを『==』で比較できるよ
これは、標準の実装では『isEqual:』を呼び出すだけだよ。自作クラスを比較できるようにする場合、ハッシュ関係の機能も実装するべきだよ
Swift Type Compatibility
- SwiftでNSObjectから派生したクラスを作った場合、そのままで、Objective-Cでも使えるよ
- そうじゃない場合、@objc属性を付ける必要があるよ
@IBOutletや@IBActionや@NSManaged属性を付けると、自動的に@objc属性も付くよ
Swiftで作ったAPIはObjective-Cでもそのまま使えるよ
ただし、イニシャライザーは名前が変わってくるから注意が必要だよ
『@objc(name)』の形で、Objective-Cで使う時の名前を指定することも出来るよ
これは、Objective-Cのアーカイブ可能なクラスをSwiftに移行するときに便利だったりするよ。
Objective-C Selectors
- Objective-Cのセレクターは、Objective-Cのメソッドを参照するためのものだよ
- これは、SwiftだとSelector構造体になるよ
- Selector構造体は文字列から生成できるよ
let mySelector: Selector = "tappedButton:"
セレクターを受け取るメソッドに文字列を渡すと、自動的にSelector構造体に変換されるよ
メモ: 暗黙の型変換が起きる? 要確認Swiftには『performSelector:』は無いよ
Writing Swift Classes with Objective-C Behavior
Adopting Protocols
プロトコルの使い方はこんな感じになるよ
Objective-Cだとこう
id<UITableViewDelegate> delegate;
- Swiftだとこう
UITableViewDelegate delegate
Working with Outlets and Actions
- Swiftだと、アウトレットやアクションは『@IBOutlet』や『@IBAction』で指定するよ
- アウトレットコレクションも『@IBOutlet』だよ
- アウトレットは、自動でweakになってnilで初期化されるよ
Live Rendering
『@IBDesignable』と『@IBInspectable』は、Interface Builderでカスタムビューをデザインするときに使えるよ
UIViewかNSViewから派生したクラスでクラス名に@IBDesignable属性を付けると、カスタムビューをInterface Builderに追加できるよ
- 同じように@IBInspectable属性をプロパティに付けると、Interface Builderからプロパティを編集できるようになるよ
Copy Semantics
- Objective-Cのプロパティでcopyを指定したものは、Swiftだと@NSCopying属性になるよ
Implementing Core Data Managed Object Subclasses
- NSManagedObjectを派生したクラスでCore Dataと連携するプロパティには、@NSManaged属性を付けるよ
Working with Cocoa Data Types
- Swiftは自動的に、SwiftとObjective-Cの型を変換するよ
メモ: 要確認
Strings
- 文字列はStringとNSStringで橋渡しできるよ
- Stringが必要な時はNSStringをキャストすれば変換できるよ
Localization
- Objective-Cだと、ローカライズにNSLocalizedString関係のマクロを使ってたよ
- Swiftだと、『NSLocalizedString(key:tableName:bundle:value:comment:)』を使うよ
この関数は、デフォルト値をいろいろ持ってるから、マクロの置き換えに使えるよ。
メモ: 要確認
Numbers
- Swiftは自動的にIntやFloatとかをNSNumberに橋渡しするよ
このおかげで、NSNumberを引数に取る所にIntやFloatを直接書けるよ
NSNumberに自動で橋渡し出来るのは以下の型だよ
- Int
- UInt
- Float
- Double
- Bool
Foundation Data Types
- SwiftはNSUIntegerもNSIntegerもIntにするよ
Foundation Functions
- Objective-CだとNSLogをロギングに使うよ
- Swiftだとprintやprintlnを使うよ
- NSAssertはassertになるよ
メモ: いろいろ、要確認
Core Foundation
- Core Foundationの型はSwiftだとクラスになるよ
- メモリ管理の註釈がちゃんとしてれば、自動的にオブジェクトの管理もやってくれるよ
Remapped Types
- SwiftだとCore Foundationの名前が置き換えられるよ
名前の後ろの『Ref』が切り落とされるよ。
メモ: 要確認
Memory Managed Objects
注釈付きのAPIから取得したCore Foundationのオブジェクトは、自動的に管理されるよ
つまり、CFRetainやCFReleaseやCFAutoreleaseを自分で呼ぶ必要はないよ。自分で作ったCの関数やObjective-CのメソッドからCore Foundationのオブジェクトを返す時は、『CF_RETURNS_RETAINED』か『CF_RETURNS_NOT_RETAINED』の註釈を使うよ
Unmanaged Objects
- 註釈のついてないAPIからCore Foundationのオブジェクトを返されると、自動で管理できないよ
この場合、SwiftはCore Foundationのオブジェクトを『
Unmanaged<T>
』構造体で管理するよObjective-Cだとこう
CFStringRef StringByAddingTwoStrings(CFStringRef string1, CFStringRef string2)
- Swiftだとこうなる
func StringByAddingTwoStrings(CFString!, CFString!) -> Unmanaged<CFString>!
- Unmanagedで受け取ったオブジェクトは、使う前にManagedオブジェクトに変換しないと駄目だよ
このために、Unmanaged構造体は2つのメソッドが用意してあるよ
『takeUnretainedValue()』と『takeRetainedValue()』だよ。例えば、オブジェクトを管理しない関数を呼ぶ場合、こんな感じになるよ
let memoryManagedResult = StringByAddingTwoStrings(str1, str2).takeUnretainedValue() // memoryManagedResult is a memory managed CFString
- いちおう、retain()やrelease()やautorelease()を呼ぶこともできるけど、このやり方はおすすめできないよ
とりあえず、ここまで。 (2014/06/18)