【问题标题】:How to wait for closure to finish before returning in Swift [duplicate]如何在 Swift 中返回之前等待关闭完成 [重复]
【发布时间】:2020-09-14 21:23:12
【问题描述】:

我有这个功能

func getSnapshot(lat: Double, lon: Double) -> UIImage? {
        let location = CLLocationCoordinate2DMake(37.332077, -37.332077)
        let region = MKCoordinateRegion(center: location, latitudinalMeters: 1000, longitudinalMeters: 1000)
        mapSnapshotOptions.region = region
        print("a")
        mapSnapshotOptions.scale = UIScreen.main.scale
        mapSnapshotOptions.size = CGSize(width: 300, height: 300)
        mapSnapshotOptions.showsBuildings = true
        mapSnapshotOptions.showsPointsOfInterest = true

        snapShotter = MKMapSnapshotter(options: mapSnapshotOptions)
        print("b")
        var newImage: UIImage?
        self.snapShotter.start { (snapshot, error) -> Void in
            print("c")
            if error == nil {
                let image = snapshot!.image.withRenderingMode(.alwaysOriginal)
                var imageview = UIImageView(frame: CGRect(x: 30, y: 30, width: 300, height: 300))
                var label = UILabel()
                label.frame = CGRect(x: 0, y: 1, width: 30, height: 30)
                label.textAlignment = .center
                label.font = UIFont.boldSystemFont(ofSize: 12)
                label.textColor = UIColor.gray
                label.text = "my-text"
                imageview.addSubview(label)
                imageview.image = image
                newImage = image
            } else {
                print("error")
            }

        }
        print("d")
        print(newImage)
        return newImage
    }

这应该返回我在snapShotter.start 闭包中设置的 UIImage。我写了一些打印语句来检查发生了什么,它打印a b d nil c,而我正在寻找的是打印a b c d (image)。

我尝试将闭包放在DispatchQueue.main.async 中,但我一直得到相同的结果。

有什么想法吗?

【问题讨论】:

标签: swift asynchronous closures


【解决方案1】:

不是返回图像,而是使用闭包块将图像传递回您使用它的地方,如下所示:

func getSnapshot(lat: Double, lon: Double, completion: @escaping (UIImage?) -> Void) {
    let location = CLLocationCoordinate2DMake(37.332077, -37.332077)
    let region = MKCoordinateRegion(center: location, latitudinalMeters: 1000, longitudinalMeters: 1000)
    mapSnapshotOptions.region = region
    print("a")
    mapSnapshotOptions.scale = UIScreen.main.scale
    mapSnapshotOptions.size = CGSize(width: 300, height: 300)
    mapSnapshotOptions.showsBuildings = true
    mapSnapshotOptions.showsPointsOfInterest = true

    snapShotter = MKMapSnapshotter(options: mapSnapshotOptions)
    print("b")
    var newImage: UIImage?
    self.snapShotter.start { (snapshot, error) -> Void in
        print("c")
        if error == nil {
            let image = snapshot!.image.withRenderingMode(.alwaysOriginal)
            var imageview = UIImageView(frame: CGRect(x: 30, y: 30, width: 300, height: 300))
            var label = UILabel()
            label.frame = CGRect(x: 0, y: 1, width: 30, height: 30)
            label.textAlignment = .center
            label.font = UIFont.boldSystemFont(ofSize: 12)
            label.textColor = UIColor.gray
            label.text = "my-text"
            imageview.addSubview(label)
            imageview.image = image
            newImage = image
            print(newImage)
            completion(newImage)
        } else {
            print("error")
            completion(nil)
        }

    }
    print("d")
}

并且使用的地方修改成这样:

getSnapshot(lat: 0, lon: 0) { image in
    DispatchQueue.main.async {
        self.imageView.image = image
    }
}

【讨论】:

  • 我不是投票者...在 else 块中也调用完成...否则它将始终保留在内存中
  • 谢谢,我错过了那一点。当人们只是想帮助他人时,不知道为什么人们会否决正确的答案。
  • 发生在我身上,兄弟......不知道为什么......但不要担心......如果你正在学习
  • 我没有投票,但请注意,在 SO 上已被询问和回答了 100 多次。拥有 3000 个代表,您就有权“投票关闭重复”——使用它!
  • 我知道有人问过这个问题。但是,如果我认识他们,我会给出答案,而不是拒绝投票或关闭,这样他们就不会在漫长的旅程开始时感到沮丧。我知道我还是初学者时的感受。
猜你喜欢
  • 2015-09-22
  • 1970-01-01
  • 1970-01-01
  • 2020-04-17
  • 2019-03-03
  • 1970-01-01
  • 1970-01-01
  • 2020-05-13
  • 2016-05-08
相关资源
最近更新 更多