ObjCがサクっと書けるコーディングTips

2013年4月21日日曜日 | Published in | 1 コメント

このエントリーをはてなブックマークに追加

最近よく使っている省略記法を紹介する。これらを使うとなんとなく気分がいい。

クラスメソッドの . (ドット)アクセス


実はクラスメソッドも .(ドット)表記が可能になった。
[SomeClass sharedInstance]
     ↓
SomeClass.sharedInstance
当然ながらさらにメソッドも重ねられる。

SomeClass.sharedInstance.localName
Xcodeではクラスメソッドの.表記は補完が効かないのが難点。ただしそれ以降のメソッドは補完してくれる。
例えば SomeClass.share... ここまでは補完しないが、SomeClass.sharedInstance.local.. ここまで来ると補完できる。


インスタンス作成 (1)new

お馴染みの alloc/init の代わりに new が使える。
SomeClass* obj = [[SomeClass] alloc] init];
     ↓
SomeClass* obj = [SomeClass new];
. を使えばさらに短くサクっと書ける
SomeClass* obj = SompeClass.new;
+new は NSObjectで定義されている(new = alloc+initとの説明がある)
This method is a combination of alloc and init.
NSObject Class Reference

昔からObj-Cにあったメソッドだが、ARCになってから autoreleaseが不要になったので使いやすくなった。

(参考)
objective c - What is difference between new and [[alloc]init] in iOS? - Stack Overflow


インスタンス作成 (2)self


クラスメソッド内でselfはクラス自身を指す。なのでインスタンスの作成に使える。
+ (instancetype)sharedInstance
{
 SomeClass* obj = [[self alloc] init];
  :
  :
}
さらに . と new を使えばこう書ける。
SomeClass* obj = self.new;

instancetype については下記を参照
Objective-Cにおけるinstancetype型について - Takebayashi.Asia


配列・ディクショナリ作成

githubでソースコードを読んでて知った。mutableな配列・ディクショナリもサクっと書ける。
NSDictionary* dict = @{}
NSMutableDictionary* dict = @{}.mutableCopy;
NSArray* array = @[]
NSMutableArray* array = @[].mutableCopy;


- - - -
多くはgithubで他の人のコードを読んでて知ったもの。コードを読むことはアルゴリズムを読み解くだけでなくコーディングのトレンドもわかるなー。

NSSecureCoding - セキュアなプロセス間通信への小さな布石

2013年4月20日土曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

NSSecureCoding という聞きなれないプロトコルが iOS6/OSX10.8から導入された。ここでいうCodingとはオブジェクトの永続化のプロコトル NSCodingのそれを指している。つまり NSSecureCoding はセキュアな NSCodingのこと。


NSSecureCodingの定義はクラスメソッドが1つあるだけ。
+ (BOOL)supportsSecureCoding;

使い方の前に何故この新しいプロコトルが導入されたかというと、現状のNSCodingだと不正なオブジェクトのロードを防げないから。
例えば -initWithCoder: の標準的な実装はこうなる。
id obj = [decoder decodeObjectForKey:@"myKey"];
if (![obj isKindOfClass:[MyClass class]]) {...fail...}
2行目でクラスチェックを行っているが実際には1行目でインスタンス化されていて既にその時点でクラスおよびインスタンスのイニシャライザは起動している。つまり現状では仮に不正なクラスが読み込み対象のファイルに紛れ込んでもその初動を防ぐことができない。

そこでNSCoderクラスに新しく -[NScoder decodeObjectOfClass:forKey:] が導入された。
NSCoder Class Reference

先程の2行の代わりに1行でチェックとデコードを同時に行う。
id obj = [decoder decodeObjectOfClass:[MyClass class]
            forKey:@"myKey"];
もし
(a)指定クラスがNSSecureCodingを実装している
(b)指定クラスとロードするクラスが一致する
のどちらかを満たさない場合は例外がスローされ、インスタンスの作成は行われない。これにより不正な振る舞いを防ぐことができる。なおこのチェックを有効にするには -[NScoder requiresSecureCoding]でYESを返すようにしておく必要がある(NOだとチェックは働かず実質 decodeObjectforKey:と変らない)。

この外部からのインスタンスロードのチェックに NSSecureCodingが使われる。このNSSecureCodingを実装するには次のどちらか2つの条件を満たす必要がある。
[a] initWithCoder: をオーバーライドしない
[b] initWithCoder: をオーバーライドする場合、decodeObjectOfClass:forKey: を使う
さらに + supportsSecureCodingをオーバーライドして、YESを返す必要がある。
この辺り、NScoderの条件と合わせると若干複雑な感じはする。

NSSecureCodingが導入されたのはXPC導入に伴うもので、iOSに関して言えばiOS6からXPCが導入された。このXPC導入に伴い、従来はアプリ内(1プロセス内)で完結していた動作がプロセス間での協調動作できるようになった。この為、従来の信頼できる自アプリ内の永続化データだけでなく、外部プロセスとの通信時に送られてくるデータの復元(decode)が必要になってきた。この時、攻撃者が何らかの方法で不正なクラス・インスタンスのデータを紛れ込ますことに成功した場合、従来の initWithCoder: ではチェックする手段が無い(※こういう攻撃方法を object substitution attacks と呼ぶらしい)。この対策としてNSSecureCodingを始めとする一連のAPIが導入された。

なお XPC Serviceを作ったり、直接アクセスできるのは今のところApple提供のライブラリだけ。一般開発者には公開されていない。このあたり次期iOS7でどうなるのかが非常に興味深い。


- - - -
今のところ一般開発者が使う理由があまり思いつかないが、XPCが公開された時には必須スタイルになるのかもしれない。



(参考)iOS6でのXPC利用


(参考)NSSecureCodingについて


(参考)XPCの概要




人気の投稿(過去 30日間)