2016-07-10 9 views
1

私はアプリケーションでtwitter apiを使用するためにfabricプラグイン/ Twitter-kitを使用しています。私は有名人のプロフィール画像の画像URLを取得したいです。ここに私のコードは以下のとおりです。SwiftのClosureから値を返す方法は?

func getImageURL(celebrity :String) -> String{ 

    var imageURL = "" 
    let client = TWTRAPIClient() 
    let statusesShowEndpoint = userSearch 
    let params = ["q": celebrity, 
        "page" : "1", 
        "count" : "1" 
        ] 
    var clientError : NSError? 

    let request = client.URLRequestWithMethod("GET", URL: statusesShowEndpoint, parameters: params, error: &clientError) 

    client.sendTwitterRequest(request) { (response, data, connectionError) -> Void in 
     if connectionError != nil { 
      print("Error: \(connectionError)") 
     } 

     do { 
      let json = try NSJSONSerialization.JSONObjectWithData(data!, options: []) 
      print("json: \(json)") 

      let profileImageURL: String? = json[0].valueForKey("profile_image_url_https") as? String 

      imageURL = self.cropTheUrlOfImage(profileImageURL!) 
      print(imageURL) 

      //how do i return the value back. confused ????? 
      return imageURL 

     } catch let jsonError as NSError { 
      print("json error: \(jsonError.localizedDescription)") 
     } 
    } 

    return imageURL 

} 

クロージャが完全に実行される前にメソッドが終了するため、値を返す方法がわかりません。私は迅速にすべての助けを感謝しています。

imageURlから画像を取り除くには、このメソッドをtableviewのcellForRowIndexPathに使用します。

+0

[Swiftのボイドクロージャから値を返す方法については、こちらを参照してください](http://stackoverflow.com/questions/37798352/how-to-return-a-value-from-a-void-closure-in -迅速)。 – OOPer

+0

http://stackoverflow.com/questions/38160959/void-inside-of-return-function/38161092#38161092 – penatheboss

答えて

4

あなたは正しいですが、sendTwitterRequestはあなたの関数がすでに返った後に戻るので、外部関数がimageURLを返す方法はありません。

代わりに、クロージャでは、セル内の任意の戻り値をメンバー変数のどこかに格納し、tableView自体を更新します(例:tableView.reloadData())。

これにより、セルが再び取得されます(cellForRow ...)。呼び出しから値を格納したメンバ変数を使用するように実装を変更します。

0

@エスケープクロージャから戻る必要があります。

func getImageURL(celebrity: String, completion:(String)->()) { 

     // your code 
     completion(imgURL) 
} 

に機能

func getImageURL(celebrity: String) -> String { 

} 

を変更 ここ

getImageURL(celebrity: String) { (imgURL) in 

     self.imgURL = imgURL // Using self as the closure is running in background 
} 

の下に与えられたとしてあなたはそれを使用することができ、私は完成のためのクロージャを持つ複数のメソッドを書く方法の例です。

class ServiceManager: NSObject { 

// Static Instance variable for Singleton 
static var sharedSessionManager = ServiceManager() 

// Function to execute GET request and pass data from escaping closure 
func executeGetRequest(with urlString: String, completion: @escaping (Data?) ->()) { 

    let url = URL.init(string: urlString) 
    let urlRequest = URLRequest(url: url!) 

    URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in 
     // Log errors (if any) 
     if error != nil { 
      print(error.debugDescription) 
     } else { 
      // Passing the data from closure to the calling method 
      completion(data) 
     } 
    }.resume() // Starting the dataTask 
} 

// Function to perform a task - Calls executeGetRequest(with urlString:) and receives data from the closure. 
func downloadMovies(from urlString: String, completion: @escaping ([Movie]) ->()) { 
    // Calling executeGetRequest(with:) 
    executeGetRequest(with: urlString) { (data) in // Data received from closure 
     do { 
      // JSON parsing 
      let responseDict = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] 
      if let results = responseDict!["results"] as? [[String:Any]] { 
       var movies = [Movie]() 
       for obj in results { 
        let movie = Movie(movieDict: obj) 
        movies.append(movie) 
       } 
       // Passing parsed JSON data from closure to the calling method. 
       completion(movies) 
      } 
     } catch { 
      print("ERROR: could not retrieve response") 
     } 
    } 
    } 
} 

以下は、値を渡すために使用する例です。

ServiceManager.sharedSessionManager.downloadMovies(from: urlBase) { (movies : [Movie]) in // Object received from closure 
     self.movies = movies 
     DispatchQueue.main.async { 
      // Updating UI on main queue 
      self.movieCollectionView.reloadData() 
     } 
} 

私はこれが同じ解決策を探している人に役立つことを願っています。

関連する問題