我有这样的功能。
class func getAccountBalances(completionHandler:@escaping ((_ balances:Any) -> Void)){
//Alamofire request and we get the result. But sometimes the result fails.
switch response.result {
case .success(let value):
completionHandler(value)
case .failure(let error):
print ("error is: \(error)")
}
如果失败,我不会把代码放到处理结果中。那是一件坏事?在调用失败的情况下,我是否需要有一个完成处理程序,以便此函数不会留在内存中等待调用完成处理程序?什么是最佳做法?
答案 0 :(得分:0)
您的标题:完成处理程序从未调用
您的代码:如果出现错误,则不会向完成处理程序返回任何值。
如果出现故障,您希望如何看到竞争处理程序的结果?你想破解应用程序吗?这种方式更好,因为它处理两种情况:
class func getAccountBalances(completionHandler:@escaping ((_ balances:Any?) -> Void)){ //make Any an optional
//Alamofire request and we get the result. But sometimes the result fails.
switch response.result {
case .success(let value):
completionHandler(value)
case .failure(let error):
print ("error is: \(error)")
completionHandler(nil)
}
您对此功能的新调用:
getAccountBalances() { value in
guard let _value = value else { // anticipate on the error return }
// use _value, the balances are inside.
}
另一种方法不是将其设为零,而是将其内部的价值向下转。这看起来像这样:
class func getAccountBalances(completionHandler:@escaping ((_ balances:Any) -> Void)){
//Alamofire request and we get the result. But sometimes the result fails.
switch response.result {
case .success(let value):
completionHandler(value)
case .failure(let error):
print ("error is: \(error)")
completionHandler(error) //notice this change
}
然后你的功能看起来像这样:
getAccountBalances() { value in
if let error = value as? Error { //or whatever type your error is in the function
//there is an error
}
}
答案 1 :(得分:0)
一般来说,最好在每个案例中都要求完成。这样做的原因是您通常希望让上方杠杆(业务逻辑层)决定是否应将某些余额(例如)标记为已保存,或者可能在发生错误时显示对话框。认为一切都应该是一个模块,这是一个很好的做法。话虽这么说,如果另一个模块想要在某个时刻调用相同的函数,那么让该模块结果发生了什么可能是个好主意。这可以用几种方式实现,我不会进入这里,这是你的决定。
但是,这不是必须的。如果一个块不会被调用,应该被释放,然后一切都是好记忆的。所以在你的例子中,如果你没有在其他地方保留块(例如将它保存在使getAccountBalances
调用的类中的变量中),你应该没问题。
另一个重要的部分是当你调用函数时要注意不要在块中保留self
而不创建内存泄漏:
getAccountBalances() { _ in
self.updateUI()
}
此块将创建一个自我保留,如果一切正常,但用户离开了屏幕,您可能最终使用已解除分配的变量并使应用程序崩溃。这里的一个好习惯是不在回调中保留自我,但在此之前使其变弱:
getAccountBalances() { [weak self] _ in
// This is not necessarily needed, and you could use self?.updateUI() instead.
// However, this is usually another thing i like to do and consider it a good practice
guard let `self` = self else { return }
self.updateUI()
}