8

我想在长期操作完成后返回一些值。但此外,我想将逻辑和 gui 分开。

例如; 我有两节课

  1. SomeServices.swift 有一个名为“getDataFromService ...”的方法
  2. MyTableViewController.swift 将显示“getDataFromService”的结果

因此,之前在 Objective-C 中,我只是在 SomeServices 中添加了一个方法,如下所示:

(void)getDataFromService:(void (^)(NSArray *, NSError *))completionBlock{ ...... }

在这个方法中,我刚刚调用completionBlock(myData, myError)了将我的值返回给 tableviewcontroller。

我必须在 SomeServices.swift 中定义的等效闭包是什么?如何在 MyTableViewController 中调用它?

我知道如何调用像这样的简单闭包:

   ....({
            responseData, error  in
            if(!error){
                //Do something
            }
        })

但我不知道如何定义一个与completionBlock 等效的闭包。

任何帮助,将不胜感激

4

3 回答 3

14

闭包的好处是,你可以传递你想要的一切。方法或函数 - 没关系。

您可以在参数中传递一个函数,然后调用它。

func someFunctionThatTakesAClosure(completionClosure: () -> ()) {
    // function body goes here
    if(error = false) {
       completionClosure()
    }

}

//Call it
someFunctionThatTakesAClosure({
    //Completions Stuff
    println("someFunctionThatTakesAClosure")
});

摘自:Apple Inc.“Swift 编程语言”。电子书。https://itun.es/ch/jEUH0.l

于 2014-06-04T07:20:55.610 回答
3

答案在语言指南中:

假设您要返回一个字符串。这是语法

({(responseData: DataClass, error: ErrorClass) -> String in
//do stuff - calculations etc..
return calculatedString
})

这是一个使用两个字符串并将它们连接起来并返回结果的示例:

let sumStrings = ({(first: String, second: String) -> String in
    return first + " " + second
})

那么您可以执行以下操作:

sumStrings("Hello","Swift")             // "Hello Swift"
于 2014-06-04T07:22:24.607 回答
1

下面是我如何使用单例 ServiceManager 来实现这一点。

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

我希望这可以帮助任何寻找相同解决方案的人。

于 2017-08-09T14:23:43.333 回答