简体   繁体   English

Alamofire的Swift完成处理程序似乎未执行

[英]Swift completion handler for Alamofire seemingly not executing

I have the following function in a class in my program: 我的程序中的类中具有以下功能:

    func getXMLForTrips(atStop: String, forRoute: Int, completionHandler: @escaping (String) -> Void) {
        let params = [api key, forRoute, atStop]

        Alamofire.request(apiURL, parameters: params).responseString { response in
            if let xmlData = response.result.value {
                completionHandler(xmlData)
            } else {
                completionHandler("Error")
            }
        }
    }

In the init() for the class, I attempt to call it like this: 在该类的init()中,我尝试这样调用它:

getXMLForTrips(atStop: stop, forRoute: route) { xmlData in
                    self.XMLString = xmlData
                }

This compiles without errors, but after init() is executed, my class's self.XMLString is still nil (shown both by the Xcode debugger and by my program crashing due to the nil value later on). 编译时没有错误,但是在执行init()之后,类的self.XMLString仍然为nil(由Xcode调试器显示,并且由于稍后的nil值导致程序崩溃)。 I see no reason why this shouldn't work. 我没有理由不这样做。 Can anyone see what I am missing? 谁能看到我所缺少的吗?

You shouldn't be making internet calls in the initializer of a class. 您不应在类的初始化程序中进行Internet调用。 You will reach the return of the init method before you go into the completion of your internet call, which means it is possible that the class will be initialized with a nil value for the variable you are trying to set. 在完成Internet调用之前,您将到达init方法的返回值,这意味着可能会使用要设置的变量的nil值来初始化该类。

Preferably, you would have another class such as an API Client or Data Source or View Controller with those methods in it. 最好是,您将拥有另一个类,例如其中包含那些方法的API客户端或数据源或视图控制器。 I am not sure what your class with the init() method is called, but lets say it is called Trips . 我不确定使用init()方法调用的类是什么,但是可以说它称为Trips

class Trips: NSObject {

  var xmlString: String

  init(withString xml: String) {
    xmlString = xml
  }

}

Then one option is to put the other code in whatever class you are referencing this object in. 然后一种选择是将其他代码放在您要引用该对象的任何类中。

I'm gonna use a view controller as an example because I don't really know what you are working with since you only showed two methods. 我将以视图控制器为例,因为我真的不知道您在使用什么,因为您只展示了两种方法。

class ViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad() 
    //setting some fake variables as an example
    let stop = "Stop"
    let route = 3

    //just going to put that method call here for now
    getXMLForTrips(atStop: stop, forRoute: route) { xmlData in
      //initialize Trip object with our response string
      let trip = Trip(withString: xmlData)
    }
  }

  func getXMLForTrips(atStop: String, forRoute: Int, completionHandler: @escaping (String) -> Void) {
    let params = [api key, forRoute, atStop]
    Alamofire.request(apiURL, parameters: params).responseString { response in
      if let xmlData = response.result.value {
        completionHandler(xmlData)
      } else {
        completionHandler("Error")
      }
    }
  }

}

If you want to be able to initialize the class without requiring setting the xmlString variable, you can still do the same thing. 如果您希望能够初始化该类而不需要设置xmlString变量,则仍然可以执行相同的操作。

Change the Trips class init() method to whatever you need it to be and set var xmlString = "" or make it optional: var xmlString: String? 将Trips类的init()方法更改为所需的值,并设置var xmlString = ""或使其可选: var xmlString: String? .

Initialize the class wherever you need it initialized, then in the completion of getXMLForTrips , do trip.xmlString = xmlData . 在需要初始化的位置初始化该类,然后在完成getXMLForTrips ,执行trip.xmlString = xmlData

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM