繁体   English   中英

Swift:使用异步方法获取价值

[英]Swift: get value using async method

我正在为这种情况寻找一两个好的习惯用法:

我想通过异步反向地理位置调用将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 ,这完全是该代码所需功能的函数。 但是,在getPlaceFromCoordinate内重复执行的许多常规代码(例如,记录错误,您所拥有的内容)以及希望关闭将限于使用CLPlacemark并更新模型对象和/或UI。

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

如果发现闭包中的代码变得笨拙,请进行函数分解,然后将此代码移至其自己的函数中,并让完成处理程序简单地调用它。 或也有其他异步模式(例如,异步NSOperation子类之间具有依赖关系,承诺/未来等)。 但是使用异步模式。

我决定采用的方法是编写getPlaceFromCoordinate函数以接受可选的闭包,因此调用方法可以控制查找结果的处理方式。

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

        :
    // Reverse geocode.
        :

    //  If we get a good placemark:
    if (placeAction != nil) {
        placeAction!(placemark)
    }

    }

对于上下文来说,这似乎很合适,很灵活,并且将调用代码放回“驾驶员座位”中。 不知道还有什么其他利弊。

暂无
暂无

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

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