AlamoFireの使用方法を習得しようとしていますが、問題があります。
これまでの私の方法は次のとおりです:
func siteInfo()->String?{
var info:NSDictionary!
var str:String!
Alamofire.request(.GET, MY_API_END_POINT).responseJSON {(request, response, JSON, error) in
info = JSON as NSDictionary
str = info["access_key"] as String
//return str
}
return str
}
これは問題であるnilを返します。私が読んだもの here から、これはリクエストがしばらくかかることがあり、そのためクロージャーが戻るまで実行されないためです。戻り値をクロージャに移動するという提案された解決策は私にとっては機能せず、コンパイラは叫ぶだけです(->String
の後に(request,response,JSON,error)
を追加すると、「「String」はvoidのサブタイプではありません」。提供される他のソリューションについても同様です。
何か案は?この問題に関係なく、AlamoFireを使用するいくつかのソースコードも役立ちます。
ありがとう!
これを処理する1つの方法は、クロージャー(通常はcompletionHandler
と呼びます)をsiteInfo
関数に渡し、それを_Alamofire.request
_のクロージャー内で呼び出すことです。
_func siteInfo(completionHandler: (String?, NSError?) -> ()) -> () {
Alamofire.request(.GET, MY_API_END_POINT).responseJSON {
(request, response, JSON, error) in
let info = JSON as? NSDictionary // info will be nil if it's not an NSDictionary
let str = info?["access_key"] as? String // str will be nil if info is nil or the value for "access_key" is not a String
completionHandler(str, error)
}
}
_
次に、次のように呼び出します(エラー処理を忘れないでください):
_siteInfo { (str, error) in
if str != nil {
// Use str value
} else {
// Handle error / nil value
}
}
_
では、クロージャーの内部でのみ行うことができ、クロージャーの外部のオブジェクトには影響を与えられない場合、取得リクエストから収集した情報をどのように保存しますか?また、リクエストが完了したことを追跡する方法は?
Getリクエストの結果は、クロージャーの内側からクラスのインスタンス変数に保存できます。クロージャがそれを妨げることは何もありません。そこから何をするかは、そのデータをどのように処理するかによって異なります。
リクエストを取得するアクセスキーフォームを取得しているように見えるため、他の関数で行われる将来のリクエストには、それが必要になる場合があります。
その場合、次のようなことができます。
注:非同期プログラミングは大きなトピックです。ここではカバーしきれません。これは、非同期リクエストから取得したデータを処理する方法の一例にすぎません。
_public class Site {
private var _accessKey: String?
private func getAccessKey(completionHandler: (String?, NSError?) -> ()) -> () {
// If we already have an access key, call the completion handler with it immediately
if let accessKey = self._accessKey {
completionHandler(accessKey, nil)
} else { // Otherwise request one
Alamofire.request(.GET, MY_API_END_POINT).responseJSON {
(request, response, JSON, error) in
let info = JSON as? NSDictionary // info will be nil if it's not an NSDictionary
let accessKey = info?["access_key"] as? String // accessKey will be nil if info is nil or the value for "access_key" is not a String
self._accessKey = accessKey
completionHandler(accessKey, error)
}
}
}
public func somethingNeedingAccessKey() {
getAccessKey { (accessKey, error) in
if accessKey != nil {
// Use accessKey however you'd like here
println(accessKey)
} else {
// Handle error / nil accessKey here
}
}
}
}
_
この設定では、最初にsomethingNeedingAccessKey()
を呼び出すと、アクセスキーを取得するリクエストがトリガーされます。その後のsomethingNeedingAccessKey()
の呼び出しでは、_self._accessKey
_にすでに格納されている値が使用されます。 somethingNeedingAccessKey
に渡されるクロージャー内でgetAccessKey
の残りの作業を行う場合、accessKey
が常に有効であることを確認できます。 accessKey
を必要とする別の関数が必要な場合は、somethingNeedingAccessKey
と同じ方法で記述してください。
_public func somethingElse() {
getAccessKey { (accessKey, error) in
if accessKey != nil {
// Do something else with accessKey
} else {
// Handle nil accessKey / error here
}
}
}
_