Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.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
如何等待函数在iOS/Swift上结束,然后再启动第二个函数_Ios_Swift - Fatal编程技术网

如何等待函数在iOS/Swift上结束,然后再启动第二个函数

如何等待函数在iOS/Swift上结束,然后再启动第二个函数,ios,swift,Ios,Swift,我基本上必须创建方法,这些方法在我的viewDidLoad中被调用。第一个获取用户的搜索首选项,并将首选项保存到顶部的变量中。之后,我想在第二个函数中访问并使用这些变量。但是现在当我想在第二个函数中访问变量时,变量总是为零 我需要如何调整viewDidLoad,以便第二个函数只执行一次,并且我的数据请求已成功执行 var searchLocation = String() var searchLocationCoordinates = [String:Double]() var searchRa

我基本上必须创建方法,这些方法在我的viewDidLoad中被调用。第一个获取用户的搜索首选项,并将首选项保存到顶部的变量中。之后,我想在第二个函数中访问并使用这些变量。但是现在当我想在第二个函数中访问变量时,变量总是为零

我需要如何调整viewDidLoad,以便第二个函数只执行一次,并且我的数据请求已成功执行

var searchLocation = String()
var searchLocationCoordinates = [String:Double]()
var searchRange = Int()


override func viewDidLoad() {
    super.viewDidLoad()

    // Gets the user's search preference
    getTheSearchLocationAndRange()

    // Loads the data from the database
    loadDataFromDatabase()
}

到目前为止,我已经阅读了dispatch_asynch或completion handler的内容。也许有人可以发布一些代码,我可以在我的viewDidLoad中使用这些代码并使其工作?

您可以使用Swift闭包!他们就是为这个而生的

请参阅苹果指南:

这是您在特定情况下需要的代码

最终卸载是关闭。调用
getTheSearchLocationAndRange()
时,其代码将一直执行到
completed()
行,该行等待函数的所有进程完成。一旦进程完成(例如下载),
completed()
调用闭包,该闭包激活
getTheSearchLocationAndRange{()->()中定义的代码。因此,
loadDataFromDatabase()
只调用一次
getTheSearchLocationAndRange()
已完全执行完毕,数据已存在(不是零)

我希望这解决了您的问题并回答了您的问题:)


顺便说一句,关于“让你的GUI挂起来”Alamofire会自动为您解决这一问题。如果您不使用Alamofire,那么您必须手动将异步请求分配给后台线程,这样您的GUI就不会没有响应。

我编写了一个演示项目,并将其发布在GitHub上,模拟处理异步网络下载。请看

具体看一看asyncFetchImage()方法,它几乎和这个线程所说的完全一样:在内部使用一个异步方法,并在异步加载完成后调用一个完成块

这是您应该使用的一般模式。编写一个接受完成块/闭包的方法。在内部,让该方法调用它需要的任何异步函数,然后从异步方法调用的完成闭包内部调用完成闭包

函数
asyncFetchImage
如下所示:

func asyncFetchImage(imageName imageName: String,
  completion: (
    image: UIImage?,
    status: String) -> ())
{
  print("Entering \(#function)")

  //Simulate a network operation by waiting a few seconds before loading an image
  let nSecDispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(3.0 * Double(NSEC_PER_SEC)))
  let queue = dispatch_get_main_queue()
  dispatch_after(nSecDispatchTime, queue)
    {
      () -> Void in
      let result = UIImage(named: imageName)
      print("Loading image in background")
      let status = result != nil ? "image loaded" : "Error loading image"
      print("About to call completion handler")
      completion(image: result, status: status)
  }
  print("Leaving \(#function)")
}

好的,我找到了一个解决方案。我基本上在第一个函数的末尾调用了这个函数

所以基本上:

    var searchLocation = String()
    var searchLocationCoordinates = [String:Double]()
    var searchRange = Int()


    override func viewDidLoad() {
        super.viewDidLoad()

        // Gets the user's search preference
        getTheSearchLocationAndRange()
    }

    func getTheSearchLocationAndRange() {
    // Code for getTheSearchLocationAndRange()

    loadDataFromDatabase()
    }

    func loadDataFromDatabase(){
    // Code for loadDataFromDatabase()
    }

你没有这么说,但是getThSearchLocationAndRange必须是异步的?在这种情况下,你不应该等待,这会使你的GUI挂起。相反,你可以让第一个函数以完成块作为参数,然后把第二个函数作为块体,因为块体是实现它的一种方法,还有其他方法。好的,知道了!你有一些示例代码吗这让我明白了吗?但这也是我在其他帖子中看到的一个关于完成处理程序的想法!getTheSearchLocationAndRange中有调度函数吗?嗨,FredericP,还没有。@Mattk90你试过我在回答中发布的代码吗?问题是它使
getTheSearchLocationAndRange()成为
函数不太有用,除非它总是调用
loadDataFromDatabase
。如果你想让这个方法更灵活,就使用补全块方法。好的,我同意这一点。在我的情况下,我永远不需要两个函数都独立使用。因此我想我可以这样解决它。但我相信你,你解决了这个问题n可能是编程上更好的一个!如果其中一个进程在获取searchLocationAndRange()时花费更长的时间,则此进程可能会失败这根本不是一个解决方案。除了您的特定情况之外,这不是一个解决方案。它可能对您有效,但出于错误的原因。如果您在父函数中具有异步功能,则子函数仍将在不等待其他代码完成的情况下被排队调用。如果我在父函数中有参数呢我需要的GetTheSearchLocation和Range已返回
    var searchLocation = String()
    var searchLocationCoordinates = [String:Double]()
    var searchRange = Int()


    override func viewDidLoad() {
        super.viewDidLoad()

        // Gets the user's search preference
        getTheSearchLocationAndRange()
    }

    func getTheSearchLocationAndRange() {
    // Code for getTheSearchLocationAndRange()

    loadDataFromDatabase()
    }

    func loadDataFromDatabase(){
    // Code for loadDataFromDatabase()
    }