15. 書き方もありますが
func linkList(paginator:Paginator?, sortingType:ListingSortType, subreddit:Subreddit?, completion:(links:[Link], paginator:Paginator?, error:NSError?)->Void)
-> NSURLSessionDataTask {
var parameter:[String:String] = [:]
if let paginator = paginator {
if paginator.sortingType == sortingType {
parameter = paginator.parameters()
}
}
var path = sortingType.path()
if let subreddit = subreddit {
path = "/r/(subreddit.display_name)(path)"
}
var URLRequest = NSMutableURLRequest.mutableOAuthRequestWithBaseURL(baseURL, path:path, parameter:parameter, method:"GET", token:token)
let task = URLSession.dataTaskWithRequest(URLRequest, completionHandler: { (data:NSData!, response:NSURLResponse!, error:NSError!) -> Void in
self.updateRateLimitWithURLResponse(response)
if error != nil {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
completion(links:[], paginator: nil, error: error)
})
}
else {
if let json:[String:AnyObject] = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.allZeros, error: nil) as?
[String:AnyObject] {
let (links, paginator) = self.parseLinkListJSON(json)
if links.count > 0 && paginator != nil {
paginator?.sortingType = sortingType;
dispatch_async(dispatch_get_main_queue(), { () -> Void in
completion(links:links, paginator:paginator, error:nil)
})
}
else {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
completion(links:links, paginator:paginator, error:NSError.errorWithCode(0, userinfo: ["error":"Can not get any contents
expectedly."]))
})
}
}
else {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
completion(links:[], paginator: nil, error:NSError.errorWithCode(0, userinfo: ["error":"Can not parse response object."]))
})
}
}
})
task.resume()
return task
}
エラーと戻り値がぐちゃぐちゃに
16. 戻り値をResult<T>にする
public enum Result<A> {
case Success(Box<A>)
case Failure(NSError)
public init(value:A) {
self = .Success(Box(value))
}
public init(error: NSError) {
self = .Failure(error)
}
........
}
public final class Box<A> {
public let value: A
public init(_ value: A) {
self.value = value
}
}
正しい戻り値か,
Errorオブジェクトのどちらかになる
enum
swiftがenumに自由なオブジェクトを
放り込めないのでGenericsで逃げる
17. 戻り値へのアクセスのイメージ
(a : Result<Hoge>) -> Void {
switch(a) {
case let .Success(x):
println(x.value)
case let .Failuare(x):
println(x.error)
}
}
戻り値がenumのSuccessに当たれば,
xが宣言されて,x.valueを使う
戻り値がenumのFailurareに当たれば,
xが宣言されて,x.valueを使う
これでswitchで中身がどんな結果でも統一して,エラーと戻り値の
ハンドリングをResult<T>できるようになる
18. さらにコードを綺麗にすると
infix operator >>> { associativity left precedence 150 }
public func >>><A, B>(a: Result<A>, f: A -> Result<B>) -> Result<B>
{
switch a {
case let .Success(x):
return f(x.value)
case let .Failure(error):
return .Failure(error)
}
}
Resultから値を取る演算子を定義すると,メソッドチェーンぽくもかける
19. コードはさらにすっきり
var request =
NSMutableURLRequest.mutableOAuthRequestWithBaseURL(Session.baseURL, path:"/api/
v1/me", method:"GET", token:token)
let task = URLSession.dataTaskWithRequest(request, completionHandler:
{ (data:NSData!, response:NSURLResponse!, error:NSError!) -> Void in
let responseResult = resultFromOptionalError(Response(data: data,
urlResponse: response), error)
let result = responseResult >>> parseResponse >>> decodeJSON >>>
parseThing_t2_JSON
completion(result)
})
task.resume()
return task
これが果たしていいコードなのか