Learn Swift / サンプルプログラム Memo Pad 2
Model クラスのコード説明に注釈を追加しました。追加した注釈は緑字で記述しています。Feb. 19, 2016
Model クラスのコード説明と、エンコーダーとデコーダーの説明に間違いがあり訂正をしました。訂正箇所は赤字で記述しています。Feb. 14 2016掲載開始日:2016年02月10日
最終更新日:2015年02月19日
home 目次 前へ 次へ mail
Model クラスの作成
ナビゲータエリアで「Memo Pad」フォルダを選択して、「File」メニュー →「New」→「File...」を選んでください。
次のパネルで「OS X」の「Source」を選び、「Cocoa Class」を選んでください。そして「Next」をクリックします。
次のパネルでは、Class: に「Model」と入力してください。Subclass of: は「NSObject」を選び、Language では「Swift」を選びます。設定が終わりましたら「Next」をクリックしてください。
次のパネルでは、デフォルトのままで「Create」をクリックします。
ナビゲータエリアに Model.swift が追加され、エディタエリアに Model.swift のコードが表示されます。
Model クラスのコーディング
Model.swift に次のコードを記述してください。太字部分が追加するコードです。冒頭のコメント部分は省略しています。
import Cocoa @objc(Model) class Model: NSObject { var note:AnyObject = String() }
- @objc(Model)
- Cocoa バインディングが、このクラスを見つけるためのコンパイラディレクティブです。自ら作成したクラスには、このコードを記述する必要があります。このコードを記述しないと、Cocoa バインディングが このクラスを見つけられなくなります。
- class Model: NSObject {
- Cocoa バイディングで使うクラスは、NSObject を継承している必要があります。
- var note:AnyObject = String()
- このコードは苦労しました。この一行を記述するために三日ほどかかりました。Swift を使った Cocoa バインディングでは、すべてデータは AnyObject 型でやり取りされます。したがって note プロパティの型は、AnyObject 型になります。そして、Swift のプロパティは必ず初期化されなければなりません。初期化するためには何らかのインスタンスが必要です。しかし AnyObject は単なる型であって、インスタンスを作成できるわけではありません。本来、この note プロパティに代入したいデータは、Text View が保持する NSTextStorage クラスのインスタンスです。ところが、Swift は、この NSTextStorage インスタンスを受け取ることが (理解することが )できません。代わりに Swift の String クラスを使ってみたところ、うまくいきました。Swift の String クラスは、Objcect-C の NSString の単なる互換クラスではなく、大きくパワーアップされているみたいです。
少し難しい話しになりますので、この注釈は読み飛ばしてもらっても構いません。var note:AnyObject = String() を、Objective-C で記述した場合は、次のようになります。@property (readwrite, copy) NSTextStorage *note;Objective-C の詳しいコード説明は割愛しますが、このコードには、copy というオプションが付いています。これは、Objective-C の配列の要素が参照型であるためです。一方、Swift の配列の要素は値型です。したがって、複製を作らなくても、各要素の値は違うものになります。
エンコーダーとデコーダー
以上で、現段階で必要となるコーディングは完了しています。しかしながら、Model クラスの note プロパティのデータを、シリアライズ (serialize、バイト列化) したり、あるいは、シリアライズされたデータを元の形に復元するためには、エンコーダーとデコーダーと呼ばれるメソッドを記述しなければいけません。次のリストで太字部分がエンコーダーとデコーダーです。なお、このコードを今、記述する必要はありません。後ほど、ファイル入出力を説明する際に、再度説明いたします。今は眺めるだけで結構です。
import Cocoa @objc(Model) class Model: NSObject, NSCoding { var note:AnyObject = String() override init() { super.init() } required init?(coder aDecoder: NSCoder) { note = aDecoder.decodeObjectForKey("note")! } func encodeWithCoder(aCoder: NSCoder) { aCoder.encodeObject(note, forKey: "note") } }
- class Model: NSObject, NSCoding
- Model クラスに、NSCoding プロトコルを採用しています。これにより、このクラスのプロパティを、シリアライズ (serialize、バイト列化) することができるようになります。なお、データをシリアライズ (バイト列化) することをエンコード (encode) といい、バイト列を元のデータに復元することをデコード (decode) と言います。 この Memo Pad では、note プロパティのデータをシリアライズしてからハードディスクに保存します。そのためにエンコーダーメソッドが必要が必要になります。またハードディスクからシリアライズされたデータを読み込みます。そのために、デコーダーメソッドが必要になります。
- override init() { super.init() }
- 通常、すべてのプロパティに初期値がある場合は、init() メソッドを省略することができます。しかしここでは、NSCording で指定された init?() メソッドも記述しなければいけません。したがって、この init() メソッドを省略することはできません。
- required init?(coder aDecoder: NSCoder) {
- デコーダーメソッドです。2014年の Swift 登場以来、さまざまなデコーダーが使われてきたと思います。しかし、2016年2月現在、Xcode 7.2.1 でコンパイラを通るのは、このデコーダーメソッドだけではないかと思います。このメソッドは、Apple のクラスリファレンスに掲載されています。
- note = aDecoder.decodeObjectForKey("note")!
- デコーダーの実装です。行末に「!」をつけて、アンラップ (非オプショナル化) している以外は、変わったところはありません。
- func encodeWithCoder(aCoder: NSCoder) {
- エンコーダーです。特に変わったところはないと思います。
- aCoder.encodeObject(note, forKey: "note")
- エンコーダーの実装です。特に変わったところはないと思います。
お疲れ様でした。
次のページでは、Memo Pad のコントローラを作成します。
無断転載禁止、リンクフリー Copyright 2016. vivacocoa.jp All right reserved.