iOS
iOSDay 21

NSURLRequestにいろんな情報を付加しとくと色々と捗るぞ

More than 3 years have passed since last update.

ネットワーク通信をした後様々なことをすると思います。

例えばダウンロードした情報をディスクに保存したり、アップロードした一時ファイルを削除したりなどです。

この時、そのネットワークリクエストにどのファイルが紐付いているのかなど、その辺の情報を管理する必要があります。

NSURLSessionではblockベースの処理が追加され、かなり楽になりましたが、backgroundSessionなど一部の処理では許可されておらず、delegateベースの処理が必要になってきます。その時のこれらの処理はとってもめんどくさかったりします。

そこでNSURLProtocolのpropertyForKey, setPropertyクラスメソッドが役に立ちます。

使い方としては黒魔術のAssociated Objectに似ています。これはNSURLRequest限定のAssociated Objectのようなものです。

例えばNSURLRequestにnameプロパティを追加してみます。extensionを使うと次のようになります。

private let nameKey = "name"

extension NSURLRequest {
var name: String? {
return NSURLProtocol.propertyForKey(nameKey, inRequest: self) as? String
}
}

extension NSMutableURLRequest {
override var name: String? {
get {
return super.name
}
set {
if let newValue = newValue {
NSURLProtocol.setProperty(newValue, forKey: nameKey, inRequest: self)
}
else {
NSURLProtocol.removePropertyForKey(nameKey, inRequest: self)
}
}
}
}

値の取得にはNSURLProtocol.propertyForKeyクラスメソッドを使います。取得はNSURLRequestに対して行います。

値の付与・削除はNSURLProtocol.setProerty, removePropertyForKeyクラスメソッドを用います。名前がバラついてしまっているのはObjCの名残ですね。

これらはRequestの変更なのでNSMutableURLRequestに対してのみ行えます。

これでRequestからnameを設定・取得ができるようになりました。

設定できるものはAnyObjectなので、なんでも付与できるようです。

ViewControllerのインスタンスもセットすることができました。

このsetPropertyが特にすごいところはプロセスを超えて値を保持できることです。

NSURLSessionのbackgroundSessionでのタスクが完了した時や、Share Extensionからの送信失敗がフォールバックされた時も、付与されたStringやNSDataなどの値は復元されます。おそらくNSDictionaryでシリアライズできるものは復元されると思います。

したがって、Share Extensionで送信が完了した後、送信した一時ファイルを削除したいなどといった時に、RequestにfileURLなどを付与してあげれば、送信失敗後不要になったファイルを削除するといったことができます。

このようにNSURLRequestにNSURLProtocol.setPropertyで値を付与すると、ネットワーク周りの処理が捗ると思うので、使ってみてもいいですね。