30
New Objective-C Features for Swift 2.0 Goichi Hirakawa

New Objective-C Features for Swift 2.0

Embed Size (px)

Citation preview

New Objective-C Features for Swift 2.0

Goichi Hirakawa

About Me• 平川 剛一 (Goichi Hirakawa)

• @gooichi

• OS X / iOSソフトウェアエンジニア(フリー)

• GyazSquare / GitHub

• Mailer、デバイス制御、MDM系など

• Objective-C歴XX年

New Objective-C FeaturesObjective-CとSwiftをより簡単で効率的に連携させるためのXcode 7からのObjective-Cの新機能:

• Generics

• Nullability (Xcode 6.3~)

• KindOf Types

• New Macros

Agenda

• Generics

• Nullability (Updated)

• KindOf Types

• New Macros

Agenda

• Generics

• Nullability (Updated)

• KindOf Types

• New Macros

What’s Generics?• 型に依存しない共通の処理やアルゴリズムを型パラメータ(Type Parameter)を用いて定義し、汎用化する機能

• ジェネリックプログラミングの仕組み

• 言語により呼び名、機能は若干異なる

• テンプレート(C++)、ジェネリクス(Java、Swiftなど)、ジェネリック(MS系言語)、パラメータ化された型(Scala)等々

Objective-C Generics• 他言語と比べ、Lightweight(軽量、簡易)

• APIの表現力を向上させる

• コレクションをより使いやすくする

• Swiftにより型情報がインポート

• より良い静的型チェックを可能にする

• Xcode 7(LLVM 7.0.0)以降

Before Using Generics

Objective-C @interface UIView @property (nonatomic, copy ,readonly) NSArray *subviews; @end

Swift class UIView { var subviews: [AnyObject] { get } }

After Using Generics

Objective-C @interface UIView @property (nonatomic,readonly,copy) NSArray<UIView *>*subviews; @end

Swift class UIView { var subviews: [UIView] { get } }

Static Type Checking• 型に関する警告が表示される

• ただし、以下は警告は出ない→正しい(後方互換性参照)

Backward Compatibility• 型消去(Type Erasure)モデルでバイナリ互換

• Objective-Cランタイムに変更なし

• コード生成に影響なし 

• 暗黙の変換によるソース互換性 NSArray<NSString *> *strings = ...;   NSArray *array = ...;   array = strings; // OK, 型引数が削除   strings = array; // OK, 型引数が追加  

Generic Classes (iOS 9)• NSArray、NSSetとNSDictionary

• これらの型情報はSwiftによりインポートされる

• それ以外のジェネリクス対応クラス

• NSCache、NSEnumerator、NSHashTable、NSMapTable、NSOrderedSet、PHFetchResult、および、これらのMutableクラスもジェネリクス対応

• これらの型情報はSwiftによりインポートされない

Variances• 共変性(covariant)

• A←Bのとき、X<A>変数にX<B>実体を割り当て可能

• 反変性(contravariant)

• A←Bのとき、X<B>変数にX<A>実体を割り当て可能

• 不変性(invariant)

• X<A>変数にはX<A>以外の実体は割り当て不可

Objective-C Generics Variances• 新しいキーワードの追加

• 共変性:X<__covariant ObjectType>

• NSArray、NSDictionary、NSOrderedSet、NSSet

• 反変性:X<__contravariant ObjectType>

• 現状該当クラスなし

• 不変性:何もつけない(デフォルト)

• 上記クラス以外すべて

Type Safety for Typed Collections

• NSArrayはcovariant(共変) NSArray<UIView *> *views; NSArray<UIResponder *> *responders = views; // OK

• NSMutableArrayはinvariant(不変) UIViewController *viewController; NSMutableArray<UIView *> *views; NSMutableArray<UIResponder *> *responders = views; // NG [responders addObject:viewController];

warning: Incompatible pointer types initializing 'NSMutableArray<UIResponder *> *' with an expression of type 'NSMutableArray<UIView *> *'

Generics Notes• Swift 2.1のリファレンスにはジェネリクスの変性に関する記述はないが、

• コレクションは値型なので共変性

• 2.1より関数型はパラメータ型に関して反変性

• 近い将来(いい加減な推測と希望)、

• 変性に関するキーワードが追加されるのでは?(Swift 3.0?)

• OrderedSet型が追加され、NSOrderedSetの型情報がSwiftによりインポートされるのでは?(Swift 2.5?)

Agenda

• Generics

• Nullability (Updated)

• KindOf Types

• New Macros

What’s Nullability?• NULL (nil / Nil) 値の許容を明確にする→ Swiftで不要なアンラップ処理を減らす

• 対象

• 関数/メソッドのパラメータや戻り値

• プロパティ

• 変数

New Type Annotations型修飾子 Objective-C

プロパティ/メソッド Swiftでの扱い NULL許容

__nonnull_Nonnull nonnull 非オプショナル しない

__nullable_Nullable nullable オプショナル する

__null_unspecified _Null_unspecified null_unspecified

暗黙的アンラップオプショナル 不明

- null_resettable暗黙的アンラップオプショナル

Setter: するGetter: しない

Nullability Notes• Objective-Cランタイムに影響なし

• コンパイル時に警告は出る

• 実行時にnilチェックなし

• 基本的にはSwiftへの移行のための表記改善

• まとめてnonnull指定する場合は以下のマクロを利用するNS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END

Agenda

• Generics

• Nullability (Updated)

• KindOf Types

• New Macros

KindOf Types• 型付きコレクションを使わない場合(従来コード)

@interface UIView (UIViewHierarchy) @property(nonatomic,readonly,copy) NSArray *subviews; @end [view.subviews[0] setTitle:@YES forState:UIControlStateNormal]; // OK

• 型付きコレクションを使う場合→エラー @interface UIView (UIViewHierarchy) @property(nonatomic,readonly,copy) NSArray<UIView *> *subviews; @end [view.subviews[0] setTitle:@YES forState:UIControlStateNormal]; // NG

error: No visible @interface for 'UIView' declares the selector 'setTitle:forState:'

KindOf Types• 型付きコレクションは、型安全になり、Swiftからも利用しやすくなるが、従来のコードでエラーとなるケースが発生

• 新しいキーワードの追加

• __kindof

• __kindof MyClass: MyClassまたはMyClassの派生クラス @interface UIView (UIViewHierarchy) @property(nonatomic,readonly,copy) NSArray<__kindof UIView *> *subviews; @end [view.subviews[0] setTitle:@YES forState:UIControlStateNormal]; // OK

Agenda

• Generics

• Nullability (Updated)

• KindOf Types

• New Macros

New Macros• SwiftによるObjective-Cインポートの挙動を変更

1. NS_SWIFT_NAME(_name)

2. NS_SWIFT_UNAVAILABLE(_msg)

3. NS_REFINED_FOR_SWIFT

4. NS_SWIFT_NOTHROW

NS_SWIFT_NAME(_name)• メソッド名、列挙型のケース、オプション設定値を変更可能

+ (instancetype)recordWithRPM:(NSUInteger)RPM NS_SWIFT_NAME(init(RPM:));

+ (id)recordWithQuality:(double)quality NS_SWIFT_NAME(record(quality:));

typedef NS_ENUM(NSInteger, ABCRecordSide) { ABCRecordSideA, ABCRecordSideB NS_SWIFT_NAME("FlipSide"), };

NS_SWIFT_UNAVAILABLE(_msg)

• Swiftでは不適切/不要な宣言をインポートしない + (instancetype)collectionWithValues:(NSArray *)values forKeys:(NSArray<NSCopying> *)keys NS_SWIFT_UNAVAILABLE("Use a dictionary literal instead”);

NS_REFINED_FOR_SWIFT• 元の実装を有効にしたまま(__methodName)、洗練されたSwiftのインターフェイスを拡張で提供

• Objective-Cのインターフェイス @interface Color : NSObject - (void)getRed:(nullable CGFloat *)red green:(nullable CGFloat *)green blue:(nullable CGFloat *)blue alpha:(nullable CGFloat *)alpha NS_REFINED_FOR_SWIFT; @end

• Swiftの拡張インターフェイス extension Color { var RGBA: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { var r: CGFloat = 0.0 var g: CGFloat = 0.0 var b: CGFloat = 0.0 var a: CGFloat = 0.0 __getRed(&r, green: &g, blue: &b, alpha: &a) return (red: r, green: g, blue: b, alpha: a) } }

NS_SWIFT_NOTHROW• スローさせずにNSErrorを生成するための宣言

• 現在はNSURLの以下のメソッドのみ - (BOOL)checkResourceIsReachableAndReturnError: (NSError **)error NS_SWIFT_NOTHROW NS_AVAILABLE(10_6, 4_0);

- (BOOL)checkPromisedItemIsReachableAndReturnError: (NSError **)error NS_SWIFT_NOTHROW NS_AVAILABLE(10_10, 8_0);

• リファレンスには理由等は特に記述されていない

Conclusion既存のObjective-Cコードを流用しながら、Swiftへの移行を徐々に進める場合、以下の理由から、まずObjective-Cの新機能を導入した方がよりスムーズな移行が可能と考えられる:

• Objective-Cジェネリクスによる静的型チェックやSwiftへの型情報インポートの追加

• NullabilityによるSwiftでの不要なアンラップ処理の削減

• KindOf型はObjective-Cジェネリクスとの組み合わせだけでなく、既存コードのid型からの置き換えるによる型安全の向上(id型と比較して…)

• マクロによるSwiftらしいAPIへの変換