Cocoa フレームワークでの作業


Objective-C との相互運用性の一環として、Swift は Cocoa フレームワークを扱う便利で効率的な方法を提供します。


Swift は、自動的にいくつかの Objective-C の型を Swift の型に変換し、いくつかの Swift の型を Objective-C の型にに変換します。Objective-C と Swift の間で変換できる型は、ブリッジ 型と呼ばれます。たとえば、Swift コードでは、NSString パラメータをとるように宣言された Objective-C メソッドに String 値を渡すことができます。さらに、Foundation、AppKit、UIKit などの Cocoa フレームワークの多くは、Swift で、より自然な API に改良しています。たとえば、NSCoderdecodeObjectOfClass(_:forKey :) メソッドは Swift の汎用を使用してより強力な型シグニチャを提供します。


Foundation


Foundation フレームワークは、データ保管、テキスト処理、日付と時刻、並べ替えとフィルタリング、永続性、及びネットワークを含む、アプリやフレームワークの基本機能を提供します。


ブリッジ型


Swift の Foundation オーバーレイは、以下のObjective-C 参照型に対して、以下のブリッジ値の型を提供します。


Objective-C 参照型Swift 値型
NSAffineTransformAffineTransform
NSArrayArray
NSCalendarCalendar
NSCharacterSetCharacterSet
NSDataData
NSDateComponentsDateComponents
NSDateIntervalDateInterval
NSDateDate
NSDecimalNumberDecimal
NSDictionaryDictionary
NSIndexPathIndexPath
NSIndexSetIndexSet
NSLocaleLocale
NSMeasurementMeasurement
NSNotificationNotification
NSNumberSwift numeric types (Int, Float, など)
NSPersonNameComponentsPersonNameComponents
NSSetSet
NSStringString
NSTimeZoneTimeZone
NSURLComponentsURLComponents
NSURLQueryItemURLQueryItem
NSURLURL
NSURLComponentsURLComponents
NSURLQueryItemURLQueryItem
NSURLRequestURLRequest
NSUUIDUUID


これらの値型は、対応する参照型と同じ機能を持ちます。不変および可変サブクラスを含むクラスクラスタは、単一の値型にブリッジされます。Swift コードは varlet を使用して可変性を制御するので、両方のクラスは必要ありません。対応する参照型は、元ののクラス名に NS 接頭辞をしてアクセスできます。


ブリッジされた Objective-C 参照型を使用できる場所であればどこでも、代わりに Swift の値型を使用できます。これにより、参照型の実装で利用可能な機能を Swift コードに自然な形で利用できるようになります。このため、自分のコードで直接ブリッジされた参照型を使用する必要はほとんどありません。実際、Swift コードが Objective-C API を import するとき、importer は Objective-C の参照型を、対応する値型に置き換えます。同様に、Objective-C コードが Swift API を import する場合、importer はまた Swift 値型を、対応する Objective-C の参照型に置き換えます。


参照型よりも値型が上回る主な利点の1つは、コードを推論しやすくなることです。値型の詳細については、Swift プログラミング言語(Swift 4.0.3)クラスと構造体、および WWDC 2015 セッション 414 Swift での値型によるより優れたアプリのビルド を参照してください。


ブリッジされた Foundation オブジェクトを使用する必要がある場合は、as 型キャスト演算子を使用してブリッジされた型間でキャストできます。


名前の変更された型


Swift Foundation のオーバーレイは、クラスとプロトコル、および関連する列挙型と定数の名前を変更します。


import された Foundation クラスおよびプロトコルは、以下の例外を除いて NS 接頭辞を削除します。


Foundation クラスは、しばしば列挙型または定数型を宣言します。これらの型を import する場合、Swift はそれらを関連型の入れ子にされた型に移動します。たとえば、NSJSONReadingOptions のオプションセットは JSONSerialization.ReadingOptions として import されます。


文字列


Swift は、String 型と NSString クラスの間をブリッジします。NSString オブジェクトを作成するには、as 演算子を使用して String 値をキャストします。また、型注釈を明示的に提供して、文字列リテラルを使用する事により NSString オブジェクトを作成することもできます。


    << SWIFT >>

  1. import Foundation
  2. let string: String = "abc"
  3. let bridgedString: NSString = string as NSString
  4. let stringLiteral: NSString = "123"
  5. if let integerValue = Int(stringLiteral as String) {
  6.         print("\(stringLiteral) is the integer \(integerValue)")
  7. }
  8. // Prints "123 is the integer 123"


注意: Swift の String 型は、コード化に依存しない Unicode 文字で構成され、さまざまな Unicode 表現でそれらの文字にアクセスするためのサポートを提供します。NSString クラスは、UTF-16 コード単位のシーケンスとして表される、Unicode 準拠のテキスト文字列をコード化します。長さ、文字のインデックス、または 16 ビットのプラットフォームエンディアン値の範囲を表す NSString メソッドは、 Int および NSRange 値ではなく String.Index および Range<String.Index> 値を使用する、対応する Swift の String メソッドを持っています。



Swift は、NSNumber クラスと Int、Double、 および Bool などの Swift の数値型の間のブリッジを行います。


NSNumber オブジェクトを作成するには、as 演算子を使用して Swift の数値をキャストします。NSNumber はさまざまな種類の型を含んでいるので、Swift の数値型にキャストするときには as? 演算子を使用しなければなりません。例えば、数値の 500 を表す NSNumber 値を Swift の Int8 型にキャストするのは失敗し、nil が返ります。と言うのも、Int8 値の最大値は 127 を表すからです。


また、型注釈を明示的に提供し、浮動小数点、整数、またはブール値リテラルを使用して NSNumber オブジェクトを作成することもできます。


    << SWIFT >>

  1. import Foundation
  2. let number = 42
  3. let bridgedNumber: NSNumber = number as NSNumber
  4. let integerLiteral: NSNumber = 5
  5. let floatLiteral: NSNumber = 3.14159
  6. let booleanLiteral: NSNumber = true


注意: NSUIntegerNSInteger などの Objective-C プラットフォーム対応の整数型は、Int にブリッジされます。


配列


Swift は、Array 型と NSArray クラスとの間をブリッジします。パラメータ化された型を持つ NSArray オブジェクトから Swift 配列にブリッジすると、結果の配列の要素型もブリッジされます。NSArray オブジェクトがパラメータ化された型を指定しない場合、型 [Any] の Swift 配列にブリッジされます。


たとえば、以下の Objective-C 宣言を考えてみましょう。


    <<OBJECTIVE-C>>

  1. @property NSArray *objects;
  2. @property NSArray<NSDate *> *dates;
  3. - (NSArray<NSDate *> *)datesBeforeDate:(NSDate *)date;
  4. - (void)addDatesParsedFromTimestamps:(NSArray<NSString *> *)timestamps;


Swift はこれを以下のように import します:


    << SWIFT >>

  1. var objects: [Any]
  2. var dates: [Date]
  3. func datesBeforeDate(date: Date) -> [Date]
  4. func addDatesParsedFromTimestamps(timestamps: [String])


上で概説した同じブリッジの規則に従って、Swift の配列リテラルから直接 NSArray オブジェクトを作成することもできます。NSArray オブジェクトとして明示的に定数または変数型を入力し、それを配列リテラルに割り当てると、Swift は Swift の配列の代わりに NSArray オブジェクトを作成します。


    << SWIFT >>

  1. let schoolSupplies: NSArray = ["Pencil", "Eraser", "Notebook"]
  2. // schoolSupplies is an NSArray object containing three values


セット


配列に加えて、Swift は Set 型と NSSet クラスの間をブリッジします。パラメータ化された型を持つ NSSet オブジェクトから Swift のセットにブリッジすると、結果のセットは Set<ObjectType> 型になります。NSSet オブジェクトがパラメータ化された型を指定していない場合、Set<AnyHashable> 型の Swift のセットにブリッジされます。


たとえば、以下の Objective-C 宣言を考えてみましょう。


    <<OBJECTIVE-C>>

  1. @property NSSet *objects;
  2. @property NSSet<NSString *> *words;
  3. - (NSSet<NSString *> *)wordsMatchingPredicate:(NSPredicate *)predicate;
  4. - (void)removeWords:(NSSet<NSString *> *)words;


Swift は、以下のようにこれを import します:


    << SWIFT >>

  1. var objects: Set<AnyHashable>
  2. var words: Set<String>
  3. func wordsMatchingPredicate(predicate: NSPredicate) -> Set<String>
  4. func removeWords(words: Set<String>)


上で概説したのと同じブリッジの規則に従って、Swift の配列リテラルから直接 NSSet オブジェクトを作成することもできます。NSSet オブジェクトとして明示的に定数または変数型を入力し、それに配列リテラルを割り当てると、Swift は Swift のセットの代わりに NSSet オブジェクトを作成します。


    << SWIFT >>

  1. let amenities: NSSet = ["Sauna", "Steam Room", "Jacuzzi"]
  2. // amenities is an NSSet object containing three values


Dictionary


Swift はまた Dictionary 型と NSDictionary クラスとの間でもブリッジします。パラメーター化された型を持つ NSDictionary オブジェクトから Swift の dictionary にブリッジすると、結果の dictionary は [Key:Value] 型になります。NSDictionary オブジェクトがパラメータ化された型を指定していない場合、[AnyHashable:Any] 型の Swift dictionary にブリッジされます。


たとえば、以下の Objective-C の宣言を考えてみましょう:


    <<OBJECTIVE-C>>

  1. @property NSDictionary *keyedObjects;
  2. @property NSDictionary<NSURL *, NSData *> *cachedData;
  3. - (NSDictionary<NSURL *, NSNumber *> *)fileSizesForURLsWithSuffix:(NSString
    *)suffix;
  4. - (void)setCacheExpirations:(NSDictionary<NSURL *, NSDate *> *)expirations;


Swift は、以下のようにこれを import します:


    << SWIFT >>

  1. var keyedObjects: [AnyHashable: Any]
  2. var cachedData: [URL: Data]
  3. func fileSizesForURLsWithSuffix(suffix: String) -> [URL: NSNumber]
  4. func setCacheExpirations(expirations: [URL: NSDate])


上で概説したのと同じブリッジの規則に従って、Swift dictionary リテラルから直接 NSDictionary オブジェクトを作成することもできます。NSDictionary オブジェクトとして明示的に定数または変数型を入力し、それに dictionary リテラルを割り当てると、Swift は Swift dictionary の代わりに NSDictionary オブジェクトを作成します。


    << SWIFT >>

  1. let medalRankings: NSDictionary = ["Gold": "1st Place", "Silver": "2nd Place",
    "Bronze": "3rd Place"]
  2. // medalRankings is an NSDictionary object containing three key-value pairs


Core Foundation


Core Foundation 型は Swift クラスとして import されます。メモリ管理の注釈が提供されている限り、Swift は、あなた自身をインスタンス化する、Core Foundation オブジェクトを含む Core Foundation オブジェクトのメモリを自動的に管理します。Swift では、自由通話でブリッジされた Foundation と Core Foundation 型の各ペアを互換性を持って使用できます。また、最初にブリッジする Foundation 型にキャストする場合、Swift 標準ライブラリに、いくつかの自由通話でブリッジされた Core Foundation 型もブリッジすることができます。


再マッピングされた型


Swift が、Core Foundation 型を import すると、コンパイラはこれらの型の名前を再マッピングします。Swift クラスは全て参照型で接尾語が冗長であるため、コンパイラは各型の名の末尾から Ref を削除します。


Core Foundation の CFTypeRef 型は完全に AnyObject 型に再マッピングします。CFTypeRef を使用するどこででも、今や、コード内では AnyObject を使用する必要があります。


メモリ管理オブジェクト


注釈付きの API から返された Core Foundation オブジェクトは、Swift で自動的にメモリ管理されており、CFRetain、CFRelease または CFAutorelease 関数をあなた自身で起動する必要はありません。


あなた独自の C 関数と Objective-C のメソッドから Core Foundation のオブジェクトを返すと、自動的にメモリ管理の呼び出しを挿入するため、CF_RETURNS_RETAINED または CF_RETURNS_NOT_RETAINED マクロのどちらかで注釈を付けられます。また、CF_IMPLICIT_BRIDGING_ENABLED マクロと CF_IMPLICIT_BRIDGING_DISABLED マクロを使用して、Core Foundation の所有権ポリシーの命名規則に従う C 関数宣言を囲んで、命名からメモリ管理を推測することもできます。


Core Foundation オブジェクトを間接的に返さない注釈付きの API のみを使用する場合は、この節の残りの部分をスキップできます。それ以外の場合は、管理されない Core Foundation オブジェクトでの操作を読み続けてください。


管理されないオブジェクト


Swift が、注釈されていない API を import する時は、コンパイラは返された Core Foundation オブジェクトのメモリを自動的に管理することはできません。Swift は、Unmanaged<Instance> 構造体にこれらの、返された Core Foundation のオブジェクトを包み込みます。すべての間接的に返された Core Foundation のオブジェクトも同様に管理されていません。例えば、ここで注釈なしの C 関数を取り上げましょう:



    <<OBJECTIVE-C>>

    CFStringRef StringByAddingTwoStrings(CFStringRef s1, CFStringRef s2)



そして、Swift は以下のようにこれを import します:



    << SWIFT >>

  1. func StringByAddingTwoStrings(_: CFString!, _: CFString!) -> Unmanaged<CFString>! {
  2.         // ...
  3. }


注釈なしの API から管理されないオブジェクトを受信した場合、それを使用して作業する前に、メモリ管理オブジェクトにすぐに変換する必要があります。そうすれば、Swift は、メモリ管理を出来るようになります。 Unmanaged<Instance> 構造体は、管理されていないオブジェクトを、takeUnretainedValue()takeRetainedValue() のメモリ管理オブジェクトに変換するために2つのメソッドを提供します。これらのメソッドはどちらも、オリジナルで、オブジェクトの開封された型を返します。呼びだそうとする API が、オブジェクトを保持するのか保持しないのかに基づいて、どちらのメソッドを使用するかを選択して下さい。


例えば、上記に挙げた C の関数は、返す前に CFString オブジェクトを保持していないと仮定します。オブジェクトの使用を開始するには、takeUnretainedValue() 関数を使用して下さい。


    << SWIFT >>

  1. let memoryManagedResult = StringByAddingTwoStrings(str1, str2).takeUnretainedValue()
  2. // memoryManagedResult is a memory managed CFString


また、管理されないオブジェクトに対して retain()、release()、 および autorelease() メソッドを呼び出すこともできますが、この方法はお勧めしません。


詳細については、Core Foundation のためのメモリ管理プログラミングガイド所有権ポリシー を参照してください。


統合ログオン


統合されたログオンシステムは、システムのすべてのレベルを通じてメッセージするのをキャプチャするための API を提供し、Foundation フレームワークの NSLog 関数を置き換えるものです。統合ログオンは、iOS 10.0 以降、macOS 10.12 以降、tvOS 10.0 以降、および watchOS 3.0 以降で利用できます。


Swift では、os モジュールのサブモジュール log にある最上位レベルの os_log(_:dso:log:type:_:) 関数を使用して、統合ログオンシステムと対話できます。


    << SWIFT >>

  1. import os.log
  2. os_log("This is a log message.")


NSString または printf 形式の文字列と1つ以上の後続の引数を使用して、ログメッセージをフォーマットできます。


    << SWIFT >>

  1. let fileSize = 1234567890
  2. os_log("Finished downloading file. Size: %{iec-bytes}d", fileSize)


また、ログオン・イベントの重要度に応じてログ・メッセージを処理する方法を制御するために、Info、Debug、または Error のようなログオン・システムによって定義されたログ・レベルを指定することもできます。たとえば、役に立つかもしれないが、トラブルシューティングのエラーには不可欠ではない情報は、情報レベルに記録されます。


    << SWIFT >>

    os_log("This is additional info that may be helpful for troubleshooting.", type:
    .info)



特定のサブシステムにメッセージをログとして記録するには、サブシステムとカテゴリを指定して、新しい OSLog オブジェクトを作成し、それをパラメータとして os_log 関数に渡すことができます。


    << SWIFT >>

  1. let customLog = OSLog("com.your_company.your_subsystem_name.plist",
    "your_category_name")
  2. os_log("This is info that may be helpful during development or debugging.", log:
    customLog, type: .debug)


統合ログオンシステムの詳細については、ログオン を参照してください。


Cocoa 構造体


Swift のコードから Objective-C のコードにブリッジするとき、Cocoa と Foundation からの組み込み構造体は NSValue インスタンスとしてブリッジされます。その結果、参照型のインスタンスのみを受け付ける Cocoa API 内の Swift から Objective-C 構造体を使用できます。これは、インスタンスの定義型が構造体型として Swift にブリッジされていても当てはまります。


以下の構造体は NSValue にブリッジされます:





前:Swift のクラスとプロトコルの書き方及び Objective-C の動作 次:Cocoa デザインパターンの採用
目次
Xcode 10 の新機能

Swift:はじめに
Swift Programming Language
Swift Blog より

  • はじめに(Part I)
  • 基本設定
  • Swift 環境の設定
    Swift のインポートプロセスの理解
  • 相互運用性(Part II)
  • Objective-C API との相互作用
  • 初期化
  • クラスファクトリメソッドとコンビニエンスイニシャライザ
    失敗可能な初期化
    プロパティへのアクセス
    メソッドでの作業
  • id の互換性
  • Any のダウンキャスト
    動的なメソッドの参照
    認識されないセレクタと optional の連鎖
  • ヌル可能性 (Nullabity) と optionals
  • ヌル可能性のない (nonnullable) オブジェクトに Optional をブリッジする
    プロトコルで修飾されたクラス
    軽量級の汎用
    拡張機能
  • クロージャ
  • self をキャプチャする時の強い循環参照を回避する
  • オブジェクトの比較
  • Hash する
  • Swift の型の互換性
  • Objective-C で Swift インターフェースの構成
    動的な送出を要求
  • セレクタ
  • Objective-C メソッドの安全でない呼び出し
    キーとキーパス
  • Swift のクラスとプロトコルの書き方及び Objective-C の動作
  • Objective-C のクラスからの継承
  • NSCoding
    プロトコルの採用
    イニシャライザとデイニシャライザを書く
    Objective-C API で Swift クラス名を使用する
  • Interface Builder との統合
  • アウトレットとアクションを使った作業
    ライブレンダリング
  • プロパティ属性の指定
  • Strong と Weak
    読み/書き可能と読み取り専用
    コピーの意味
    コアデータ管理オブジェクトサブクラスの実装
    プロトコルの宣言
  • Cocoa フレームワークでの作業
  • Foundation
  • ブリッジ型
  • 名前の変更された型
  • 文字列

    配列
    セット
    Dictionary
  • Core Foundation
  • 再マッピングされた型
    メモリ管理オブジェクト
    管理されないオブジェクト
    統合ログオン
    Cocoa 構造体
  • Cocoa デザインパターンの採用
  • デリゲート化
    遅延した初期化
  • エラー処理
  • エラーの catch と処理
    エラーを Optional の値に変換する
    エラーを throw する
    カスタムエラーの Catch と処理
    キー値の監視
    ターゲット・アクション
    シングルトン
    Introspection(内省)
  • 連載
  • ローカライズ
    自動解放プール
    API の利用
    コマンドライン引数の処理
  • C の API との相互作用
  • 原始的な型
  • グローバル定数
  • import された定数の列挙体と構造体
  • 関数
  • 可変個引数の関数
  • 構造体
  • 型メンバとして関数を import
    列挙型
    Option のセット
    ユニオン
    ビットフィールド
    名前のない構造体と union のフィールド
  • ポインタ
  • 定数ポインタ
    可変ポインタ
    自動解放ポインタ
    関数ポインタ
    バッファポインタ
    ヌルポインタ
    ポインタの計算
    データ型サイズの計算
    1回限りの初期化
  • プリプロセッサの指令
  • 簡単なマクロ
    複雑なマクロ
    条件付きコンパイルブロック
  • うまく組み合わせる(part III)
  • 同じプロジェクトでの Swift と Objective-C
  • 「うまく組み合わせる」概観
  • 同じアプリターゲット内からコードを import
  • Objective-C から Swift への import
    Swift から Objective-C への import
  • 同じフレームワークターゲット内からコードを import
  • Objective-C から Swift への import
    Swift から Objective-C への import
    外部フレームワークの import
  • Objective-C からの Swift の使い方
  • Objective-C ヘッダでの Swift クラスまたはプロトコルの参照
    Objective-C クラスで採用可能な Swift プロトコルを宣言
    Objective-C の実装での Swift プロトコルの採用
    Objective-C から使用できる Swift のエラー型の宣言
  • Objective-C インターフェイス用に Swift 名をオーバーライド
  • クラスファクトリメソッド
    列挙型
    Objective-C 宣言を洗練する
    Swift で Objective-C インターフェイスを使用できないようにする
    Objective-C API へ利用可能性情報の追加
    プロダクトモジュールの命名
    トラブルシューティングのヒントと注意
  • 移行(Part IV)
  • Objective-C から Swift への移行
  • 移行のための Objective-C コードの準備
  • 移行プロセス
  • はじめる前に
    作業中に
    見終わったら
    トラブルシューティングのヒントと注意
  • 更新履歴
  • マニュアルの更新履歴












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)












    トップへ(Swift を Cocoa と Objective-C と使う)