Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 完成处理程序从未调用_Swift_Swift4 - Fatal编程技术网

Swift 完成处理程序从未调用

Swift 完成处理程序从未调用,swift,swift4,Swift,Swift4,我有一个这样的函数 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): completi

我有一个这样的函数

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

如果结果失败,我不会使用代码来处理它。这是件坏事吗?在调用失败的情况下,我是否需要有一个完成处理程序,以便该函数不会停留在内存中等待调用该完成处理程序?最佳做法是什么?

您的标题:完成处理程序从未调用过

如果出现错误,代码:不会向完成处理程序返回任何值

如果比赛失败了,你怎么能期望看到比赛的结果呢?是否要使应用程序崩溃?这种方法更好,因为它可以处理两种情况:

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
}
}
那么您的函数将如下所示:

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

一般来说,对每一个案例都要求完成是一种良好的做法。这样做的原因是,您通常希望让上层(业务逻辑层)决定是将某些余额(例如)标记为已保存,还是在发生错误时显示对话框。这是一个很好的实践,认为一切都应该是一个模块。也就是说,如果另一个模块希望在某个时候调用同一个函数,那么最好让该模块知道结果如何。这可以通过几种方式实现,我不在此赘述,这是你的决定

然而,这不是必须的。如果一个块不被调用,它应该被释放,然后一切都是良好的内存明智的。因此,在您的示例中,如果您没有将块保留在其他地方(例如,将其保存在类中的一个变量中,该类调用
getAccountBalances
),您应该就可以了

另一个重要的部分是调用函数时,小心不要在块内保留
self
时产生内存泄漏:

getAccountBalances() { _ in 
   self.updateUI()
}
此块将创建一个retain to self,如果调用一切正常,但用户离开了屏幕,则您可能最终使用已解除分配的变量并使应用程序崩溃。这里的一个好做法是不要在回调中保留自我,而是在回调之前使其变弱:

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

您的response.result是什么类型的对象?它在测试中是否为.success(response.result)返回true?JSON,通常返回true,但有时失败。我正在使用codable来解析它。@NevinJethmalani将第二个参数(
错误?
)添加到您的完成处理程序中。有一天你真的需要返回
任何
?如果是这样,请将其更改为
(Any?,Error?
,否则最好返回正确的对象类型
Balance?
。有两个注意事项:如果存在强引用循环的风险(您将此闭包存储为参数,并且从不释放它),则绝对使用
[弱自我]
。但这对Alamofire来说不是问题,因为他们在完成闭包后会释放闭包。(查看Alamofire页面,他们很少/从不使用
[弱自我]
模式,因为这根本不需要。)另一个问题更为琐碎:如果您发出请求并碰巧在请求完成之前关闭视图控制器,您是否关心它是否会一直挂在视图控制器上直到请求完成?。。。一般来说,你不在乎,所以你不必为
[弱自我]
操心。但是如果您这样做(例如,如果视图控制器占用大量内存,或者请求可能非常慢),那么您可以尽一切可能使用
[弱自我]
让视图控制器在其关闭后立即释放。所以Radu是正确的,您可以使用
[弱自我]
模式,但在Alamofire的情况下,这通常不是问题。我当然不想让你担心在这种特殊情况下使用
[弱自我]
来防止泄漏。但是如果需要,您可以使用该模式。如果我不包括
completionHandler(error)
,会发生什么?该功能是否保留在应用程序的内存中,并在以后导致问题,或者这样做是否可以?如果出现错误,我不需要在主VC中执行任何操作。我只是忽略了这个错误。@NevinJethmalani你为什么要这么做?您的函数将等待返回,但该返回永远不会出现。我想它会留在记忆中,但我真的不知道。但是我没有理由不在转义完成处理程序中返回值。是的,这就是我想知道的全部。没有理由。偶尔我会忘记处理错误,所以我想知道这是一件大事,还是应该回去添加那行代码来处理错误。你是说
错误
。您不能将其强制转换为自己的实例<代码>如果let error=值为?错误{
总是会失败这太棒了!谢谢!你能详细说明内存泄漏部分吗?我想我的代码中可能有这个问题。这里的最佳做法是什么?我应该做些什么来避免泄漏?@NevinJethmalani让我知道我是否应该提供更多细节。如果你在某些情况下需要更多帮助,我建议你对整个场景进行ost只是为了澄清:Radu,我想你知道这一点,但是为了@NevinJethmalani的利益,如果你不将
[弱自我]
模式与Alamofire结合使用,它就不会“泄漏”就其本身而言,但可能只是在视图控制器被解除后等待几秒钟来解除分配,而只是等待请求完成。有时您需要
[弱自我]
模式(如果您只是更新UI),但在其他情况下,您可能正在更新模型或类似的内容,在这种情况下,您不想使用
[弱自我]
模式。这取决于您在此闭包中所做的操作。