繁体   English   中英

如何等待 function 在 iOS/Swift 上结束,然后再开始第二个

[英]How to wait for a function to end on iOS/Swift, before starting the second one

我基本上必须使用在我的 viewDidLoad 中调用的方法。 第一个获取用户的搜索偏好并将偏好保存到顶部的变量。 之后我想在第二个 function 中访问和使用这些变量。但是现在当我想在第二个 function 中访问它们时,变量总是 nil。

怎么调整我的viewDidLoad,让第二个function只执行一次,我的数据请求就执行成功了?

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 或完成处理程序的内容。 也许有人可以发布一些我可以在我的 viewDidLoad 中使用并使其工作的代码?

你可以使用Swift闭包! 它们是为此而制造的。

请参阅Apple指南: 闭包

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

FinishedDownload是关闭。 getTheSearchLocationAndRange() ,执行其代码直到completed()行等待函数的所有进程完成。 一旦进程完成(例如下载), completed()将调用闭包,该闭包激活getTheSearchLocationAndRange { () -> () in定义的代码。 因此,只有在getTheSearchLocationAndRange()完全执行并且数据存在(不是nil)时才调用loadDataFromDatabase() )。

    var searchLocation = String()
    var searchLocationCoordinates = [String:Double]()
    var searchRange = Int()
    typealias FinishedDownload = () -> ()

    override func viewDidLoad() {
        super.viewDidLoad()

        getTheSearchLocationAndRange()
    }

    func getTheSearchLocationAndRange(completed: FinishedDownload) {

           // Code for searching Location Range HERE

           completed()
    }

    getTheSearchLocationAndRange { () -> () in
        loadDataFromDatabase()
    }

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

顺便说一句,关于“离开你的GUI挂”部分,Alamofire会自动为您解决这个问题。 如果您不使用Alamofire,则必须手动将异步请求分配给后台线程,以便您的GUI不会无响应。

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

具体看一下方法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()
    }

尝试这个

typealias FinishedMethod = ()

override func viewDidLoad() {
    super.viewDidLoad()
    SecondMethod(completed: FirstMethod())
}

func FirstMethod() {
       // FirstMethod Code HERE
}

func SecondMethod(completed: FinishedMethod ) {
       // SecondMethod Code HERE
}

暂无
暂无

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

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