ios - Swift:使用异步方法获取值

标签 ios swift asynchronous reverse-geocoding clgeocoder

我正在为这种情况寻找一两个好的成语:

我想通过异步反向地理定位调用将 CLLocationCoordinate2D 转换为 CLPlacemark,作为一系列其他操作的一部分。

转换步骤是一个非常“实用”的步骤,因此在处理程序中放置大量代码来执行“其他操作”感觉结构不佳。

我可以将结果存储在类变量中,但随后我需要知道异步步骤何时完成,这意味着某种事件触发或主线程排队超时或其他事情,这看起来也很尴尬。

有没有标准的方法来解决这个问题?将代码放在处理程序中是否很常见?

谢谢!

这是我的上下文的具体代码,FWIW。

func getPlaceFromCoordinate(coordinate: CLLocationCoordinate2D) -> CLPlacemark? {

    var loc = CLLocation(
        latitude: coordinate.latitude,
        longitude: coordinate.longitude
    )

    var mightBeAPlace: CLPlacemark? = nil

    CLGeocoder().reverseGeocodeLocation(loc, completionHandler: {(placemarks, error) -> Void in
        if(error != nil) {
            println("Reverse geocoding error.")
        }
        else if (placemarks.count == 0) {
            println("no placemarks")
        }
        else { // if (placemarks.count > 0)
            println("we have placemarks")
            mightBeAPlace = CLPlacemark(placemark: placemarks[0] as! CLPlacemark)
            println("Inside closure place: \(mightBeAPlace?.locality)")
            lastUserSelectedPlace = mightBeAPlace // This stores it in a class variable.
        }
    })
    println("Outside closure place: \(mightBeAPlace?.locality)")
    return mightBeAPlace // This of course fails because the async task is running separately.
}

最佳答案

典型的方法是自己采用completionHandler方法,例如:

lazy var geocoder = CLGeocoder()

func getPlaceFromCoordinate(coordinate: CLLocationCoordinate2D, completionHandler: (CLPlacemark!, NSError?) -> ()) {
    let location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)

    geocoder.reverseGeocodeLocation(location) { placemarks, error in
        if error != nil {
            println("Reverse geocoding error: \(error)")
        } else if placemarks.count == 0 {
            println("no placemarks")
        }

        completionHandler(placemarks.first as? CLPlacemark, error)
    }
}

你可以这样调用它:

getPlaceFromCoordinate(coordinate) { placemark, error in 
    if placemark != nil {
        // use placemark here
    }
}

// but do not use it here, because the above runs asynchronously (i.e. later)

就您在此 completionHandler 闭包中放入了多少代码以及在 getPlaceFromCoordinate 中放入了多少代码而言,这完全取决于该代码所包含的内容。但是在 getPlaceFromCoordinate 中重复了很多例行代码(例如记录错误,你有什么),希望闭包将仅限于获取 CLPlacemark 和更新模型对象和/或 UI。

但是,是的,约定是在完成处理程序中放置任何取决于异步方法完成的内容。虽然有一些技术可以使这种异步方法同步运行,但这通常是一个非常糟糕的主意。

如果您发现闭包内的代码变得笨拙,那么进行功能分解并将这段代码移到它自己的函数中,让完成处理程序简单地调用它。或者也有其他异步模式(例如异步 NSOperation 子类,它们之间具有依赖关系,promises/futures 等)。但是使用异步模式。

关于ios - Swift:使用异步方法获取值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30003280/

相关文章:

ios - 如何在 IOS 中获得类似于 IMEI 的标识字符串

ios - 在 Swift 中将专辑插图添加为 subview

java - EJB @Asynchronous - 事务在执行几分钟后不活动

node.js - Nodejs异步函数原型(prototype)链错误

ios - Base64 解码 NSString 的异常结果

ios - 即时更改 UIPopoverController

ios - Swift 不能使用 ObjectiveC 类

arrays - 将 PFObject append 到数组,导致所有元素被替换(Swift、Parse)

ios - 检查 AppDelegate 中 session 中的用户,如果没有则触发 UIViewController

javascript - Node.js 中的嵌套异步操作