NSURLSession を使って通信を走らせる場合、コールバックやデリゲートなどで後処理を指定する非同期通信となります。基本的に通信処理を非同期で扱うのは正しいと思います。しかし、コールバックやデリゲート、Future や Observable などに縛られず処理を書きたいとなると、同期通信でないと困ります。
そこで強制的に同期通信にしてしまうコードを書いてみました。これで晴れてコールバックを渡す必要も無く、デリゲートを指定する必要もない。そして Future や Observable に包む必要のない状態になりました。
public class HttpClientImpl {
private let session: NSURLSession
public init(config: NSURLSessionConfiguration? = nil) {
self.session = config.map { NSURLSession(configuration: $0) } ?? NSURLSession.sharedSession()
}
public func execute(request: NSURLRequest) -> (NSData?, NSURLResponse?, NSError?) {
var d: NSData? = nil
var r: NSURLResponse? = nil
var e: NSError? = nil
let semaphore = dispatch_semaphore_create(0)
session
.dataTaskWithRequest(request) { (data, response, error) -> Void in
d = data
r = response
e = error
dispatch_semaphore_signal(semaphore)
}
.resume()
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
return (d, r, e)
}
}
実際に UI 層から呼び出す前に、適当なタイミングで Future なり Observable なりに lift すればよいので、同期である方が柔軟な設計が可能になるのではないかなと思います。execute の戻り型が、 Either<NSError, HttpResponse> とかになっているとさらに良さそうですね。
純粋な HttpClient が Future や Observable に依存する必然性がないので、このコードが安定したものであれば、使っていきたいと考えています。iOS 開発に詳しい方、このコード実際どうなんですかね?(丸投げ)
Pinned Articles
About
ウェブ界隈でエンジニアとして労働活動に励んでいる @gomi_ningen 個人のブログです
Tags
JavaScript
PowerShell
kibana
elasticsearch
fluentd
nginx
イベント
五十嵐裕美
村川梨衣
logrotate
IoT
Scala
Java
C言語
iputils
ICMP
WUG
mastodon
Swift
AWS
Clock
Windows
アーキテクチャ
PoEAA
iOS
DeviceFarm
プログラミング言語
OS
StepFunctions
Lambda
Serverless
terraform
ポエム
RHEL
ネットワーク
GraphQL
CloudWatch
Linux
Coreutils
network
nc
telnet
LinuxKernel
fpinscala
ELB
IAM
AppSync
EFS
Gradle
english