Upload
goichi-hirakawa
View
817
Download
4
Embed Size (px)
Citation preview
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
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 } }
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?)
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
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
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);
• リファレンスには理由等は特に記述されていない