从另一个文件中快速调用完成处理程序失败

Posted

技术标签:

【中文标题】从另一个文件中快速调用完成处理程序失败【英文标题】:Swift calling completion handler in from another file fails 【发布时间】:2018-12-29 06:08:33 【问题描述】:

我正在用 completio=n 处理程序从一个类调用一个函数到另一个类

调用类:

class PVClass


var avgMonthlyAcKw:Double = 0.0

var jsonString:String!

func estimateMonthlyACkW (areaSqFt:Float, completion: @escaping(Double) -> () )

    var capacityStr:String = ""

    let estimatedCapacity = Float(areaSqFt/66.0)
    capacityStr = String(format: "%.2f", estimatedCapacity)

    // Build some Url string
    var urlString:String = "https://developer.nrel.gov/"
    urlString.append("&system_capacity=")
    urlString.append(capacityStr)

    let pvURL = URL(string: urlString)
    let dataTask = URLSession.shared.dataTask(with: pvURL!)  data, response, error in
        do 

            let _ = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers)
            self.jsonString = String(data: data!, encoding: .utf8)!
            print("JSON String:\(String(describing: self.jsonString))")

            if self.jsonString != nil 
                let decoder = JSONDecoder()
                let jsonData = try decoder.decode(PVClass.Top.self, from: data!)

                // do some parsing here
                var totalAcKw: Double = 0.0
                let cnt2: Int = (jsonData.Outputs?.ACMonthly.count)!
                for i in 0..<(cnt2-1) 
                    totalAcKw = totalAcKw + (jsonData.Outputs?.ACMonthly[i])!
                
                self.avgMonthlyAcKw = Double(totalAcKw)/Double(cnt2)

                // prints value
                print("updated estimate: ", self.avgMonthlyAcKw)
            

         catch 
            print("error: \(error.localizedDescription)")

        
    
    dataTask.resume()
    completion(self.avgMonthlyAcKw)

调用类:

 func estimate() 
  var estimatedSolarkWh:Double = 0.0
 let aPVClass = PVClass()
aPVClass.estimateMonthlyACkW(areaSqFt: 100.0,  completion:  (monthlyAckW) -> Void in

           estimatedSolarkWh = monthlyAckW
            self.view.setNeedsDisplay()
       )
return 


当我调用函数estimate() 时,另一个PVClass 中的estimateMonthlyACkW 函数被执行,但它在调用estimate() 函数执行后返回。因此,即使在被调用的函数中,URLsession 被执行,json 被解析,并且值被正确打印——值永远不会被传输到完成处理程序,并且值永远不会返回到调用类。我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

您需要在打印语句之后移动completion(self.avgMonthlyAcKw),如下所示:

   // prints value
   print("updated estimate: ", self.avgMonthlyAcKw)
   completion(self.avgMonthlyAcKw)

希望对你有帮助:)

【讨论】:

更新评论:我确实调用了完成处理程序,我在 varestimateSolarkWh 中捕获了返回值。我从 varestimatedSolarkWh 对 UI 进行了分配,但 UI 没有得到更新。如何根据捕获的值强制刷新 UI? 在 DispatchQueue.main.async 中添加 UI 内容 修改后的代码仍然失败。 DispatchQueue.main.async [weak self] in guard case self = self else return print("monthlyAckW: ",monthlyAckW) self?.estimatedSolarkWh = Int(monthlyAckW * Double((12)/365 * (self?. numDays)!)) print("estimatedSolarkWh: ", self?.estimatedSolarkWh ?? 0) guard let val = self?.estimatedSolarkWh else return print("val: ", val) self?.estimatedSolarkWhLabel.text = String( val) self?.view.setNeedsDisplay() ) monthlyAckW 具有正确的值。将值分配给 self?.estimatedSolarkWh 但 self?.estimatedSolarkWh 为 '0',值永远不会转移到当前类 @vrao 你能接受这个答案和其他关于 UI 问题的问题吗?随着完成问题的解决。

以上是关于从另一个文件中快速调用完成处理程序失败的主要内容,如果未能解决你的问题,请参考以下文章

发出调用快速完成处理程序关闭的问题

需要故意让 JMS 失败来调用错误处理程序

如何从另一个线程的 cpp 代码同步调用 qml 信号处理程序?

如何从另一个类调用viewmodel方法

快速从另一个 ViewController 调用函数

使用完成处理程序进行异步调用的多个 URLSession dataTask 导致内存上升