2016-12-24 12 views
-2
public func fetchAllRooms(completion: ([RemoteRoom]?) -> Void) { 
    let url = NSURL(string: "http://localhost:5984/rooms/_all_docs?include_docs=true")! 

    let urlRequest = NSMutableURLRequest(
    URL: url, 
    cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData, 
    timeoutInterval: 10.0 * 1000) 
    urlRequest.HTTPMethod = "GET" 
    urlRequest.addValue("application/json", forHTTPHeaderField: "Accept") 

    let task = urlSession.dataTaskWithRequest(urlRequest) 
    { (data, response, error) -> Void in 
    guard error == nil else { 
     print("Error while fetching remote rooms: \(error)") 
     completion(nil) 
     return 
    } 

    guard let json = try? NSJSONSerialization.JSONObjectWithData(data!, 
     options: []) as? [String: AnyObject] else { 
     print("Nil data received from fetchAllRooms service") 
     completion(nil) 
     return 
    } 

    guard let rows = json["rows"] as? [[String: AnyObject]] { 
     print("Malformed data received from fetchAllRooms service") 
     completion(nil) 
     return 
    } 

    var rooms = [RemoteRoom]() 
    for roomDict in rows { 
     rooms.append(RemoteRoom(jsonData: roomDict)) 
    } 

    completion(rooms) 
    } 

    task.resume() 
} 

私はSwiftでかなり新しいです。このコードスニペットを理解するのを助けてください

fetchAllRooms関数は、パラメータアレイRemoteRoomを取り、voidを返す名完了と別の機能を取ります。

は今終わり、完了ブロックは(構文はObjective Cの中のブロックのコールバックのように思える)パラメータRemoteRoomと呼ばなっています。 RemoteRoomは&完了ブロックが初期化され、completion(rooms)と呼ばれています。しかし、完成ブロックの本体はどこにありますか?行:completion(rooms)が実行されたときに実行される行は何ですか?あなたはその関数を呼び出すときcompletion

答えて

3

完了ブロックのボディは、渡された関数またはクロージャのボディです。次の例はすべて同じことを実行します。

func fetch(completion: (Int) -> Int) { 
    print("executing fetch") 

    let result = completion(5) 
    print("completion(5) returns \(result)") 
} 

// calling it passing a function with the right signature 
func addOne(i: Int) -> Int { 
    return i + 1 
} 

fetch(completion: addOne) 

// passing a closure 
fetch(completion: { i in return i + 1 }) 

// same with trailing closure syntax 
fetch() { i in 
    return i + 1 
} 

//() isn't needed if completion is the only parameter 
fetch { i in 
    return i + 1 
} 

// simplified closure removing parameter name and return 
fetch { $0 + 1 } 
+0

すごくおかげで総合的な答えを@vacawwama。私が持っている質問のカップル。 "//クロージャを渡す"& "//同じクロージャのシンタックスと比較する"クロージャを使用する場合と後続のクロージャを使用する場合どんな特定の事件?なぜこれがキーワードの中で使われていますか?入力パラメータ?なぜこの$ 0が使われたのですか?入力パラメータを表すために使用されている場合は、 "{(data、response、error) - > Void in"という行に何が表示されますか? – user804417

+1

@ user804417のように、最後のパラメータがクロージャを受け取る場合は、通常、後続のクロージャ構文を使用します。 'in'キーワードは、引数をクロージャ本体から分離します。 '$ 0'は最初のパラメータを表します。 3つのパラメータがある場合は、 '$ 0'、' $ 1'、 '$ 2'を使います。 – vacawama

+0

ありがとうございますサー!今は明瞭です! – user804417

1

ブロックの一部は、(実行)と呼ばれています。 completion(rooms)の呼び出しは、この関数を呼び出した完了ブロックを実行しますfetchAllRooms

self.fetchAllRooms() { rooms in 
    //When you call completion(rooms) this block will be executed and you get [RemoteRoom] 
    in rooms instance 

    //do something with rooms instance here 
} 
+0

あなたの答えはNiravです。ブロックが呼び出されると、私は理解することができますが、ブロックの本体はどこにありますか? (closureがブロックと同じように動作するかどうかは確かではありませんが) – user804417

+1

@ user804417 'fetchAllRooms'関数を呼び出すと、' completion(rooms) 'の本体は' {rooms in} 'になります。 –

+0

それを得ましたNirav、ありがとう。私が持っているもう1つの質問 – user804417

1

Objective-Cのブロックとスウィフトクロージャを異なる名前とわずかに異なる構文を使用して、同じものですが、彼らは交換可能です。 Objective-Cで

、システムは、UIViewのアニメーションクラスメソッドanimateWithDuration:animations:を有しています。その実装を想像してみてください:

@interface UIView 

+(void) animateWithDuration: (int) duration, animations: (void (^)(void)) animations { 
    //set up animation 
    animations(); 
    //finish animations 
} 

アニメーションブロックの本体はどこですか?

これは発信者によって提供されたものです。行animations()は、メソッドに渡されたブロックを呼び出します。

同じことがfetch()の機能も同様です。これはブロック/クロージャーをとり、名前はcompletionです。 fetch関数は、async URLSession(Objective-CのNSURLSession)dataTaskを使用してデータをダウンロードし、完了ハンドラをデータタスクに提供します。

データタスクが完了すると、データタスクの完了ハンドラコードが実行されます。その完了ハンドラ内で、fetch()関数は、渡された完了ハンドラ関数を呼び出します。 Objective-CとSwiftの両方で、aysncライブラリを使用するための非常に一般的なパターンです。これは、2つのレベルの補完ハンドラがあります。

スウィフトはちょうどのObjective-Cのような「後閉鎖」構文を持っています。両方の言語で、関数の最後のパラメータがブロック/クロージャである場合、ブロッククロージャをカッコの外に引っ張り、パラメータラベルをスキップしてブロック/クロージャに中カッコを指定するだけです。 Objective-Cでは、コンパイラを幸せにするためにブロックに接頭語^を付ける必要がありますが、それ以外の場合はかなり似ています。

関連する問題