How to return value from a Closure in Swift?

后端 未结 2 558
逝去的感伤
逝去的感伤 2021-02-07 12:09

So I am using fabric plugin/Twitter-kit to use twitter api in my application. I want to get the image URL of profile picture of a celebrity. here is my code below.



        
2条回答
  •  自闭症患者
    2021-02-07 12:43

    You need to return from an @escaping closure. Change the function

    func getImageURL(celebrity: String) -> String {
    
    }
    

    to

    func getImageURL(celebrity: String, completion: @escaping(String)->()) {
    
          // your code
          completion(imgURL)
    }
    

    You can use it as given below

    getImageURL(celebrity: String) { (imgURL) in
    
          self.imgURL = imgURL // Using self as the closure is running in background
    }
    

    Here is an example how I write multiple methods with closures for completion.

    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")
            }
        }
      }
    }
    

    Below is the example how I use it to pass values.

    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()
          }
    }
    

    I hope this helps anybody looking for the same solution.

提交回复
热议问题