委托回调方法返回变量slow,从另一个类访问时导致变量nil?

时间:2015-07-02 08:21:31

标签: ios swift callback delegates cllocationmanager

在我的app委托类中,我正在尝试使用委托从另一个类中检索用户当前位置。这个已转换的用户Curren位置将用于我的应用程序的许多部分。所以,我已在AppDelegate

中设置它
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var helperLocation:HelperLocationManager?
    var currentLocation:CLLocation?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        //get the current location and set it so all other screens can use it
        self.helperLocation = HelperLocationManager()
        self.helperLocation?.delegate = self 
        return true
    }
}

   extension AppDelegate: SendLocationDelegate{

     func sendCoOrdinates(loccoordinate:CLLocation, placemark:CLPlacemark){
             currentLocation = loccoordinate
      }
    }

这似乎是我的HelperLocationManager班级

protocol SendLocationDelegate{

    func sendCoOrdinates(coordinates:CLLocation,placemark:CLPlacemark)

}

class HelperLocationManager: NSObject {

    var locationManager = CLLocationManager()
    var delegate:SendLocationDelegate?

    override init() {

        super.init()

        var code = CLLocationManager.authorizationStatus()

        if code == CLAuthorizationStatus.NotDetermined {

            locationManager.requestAlwaysAuthorization()
            locationManager.requestWhenInUseAuthorization()

        }

        locationManager.delegate = self

    }


}


extension HelperLocationManager: CLLocationManagerDelegate{


    func locationManager(manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) {

        switch status {

        case CLAuthorizationStatus.Restricted:

            println( "Restricted Access to location")

        case CLAuthorizationStatus.Denied:

            println( "User denied access to location please turn on the location")
            // UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!)
            //may be open here settings page and say to turn on the setting location services


        default:

            locationManager.startUpdatingLocation()
        }

    }

    func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {

        var locValue = locations.last as! CLLocation
        locationManager.stopUpdatingLocation()

        CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: {(placemarks,error)-> Void in

            if (error != nil) {
                println("Reverse geocoder failed with error" + error.localizedDescription)
                return
            }

            if placemarks.count > 0 {

                let pm = placemarks[0] as! CLPlacemark
                self.delegate?.sendCoOrdinates(locValue,placemark: pm)

            } else {

                println("Problem with the data received from geocoder")
            }
        })


    }


    func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {

        println("Your error is ", error.localizedDescription)

    }

}

如果用户位置发生任何变化,我会调用我的回调方法...

一切都很好。 HelperLocationManager类将当前位置发送到sendCoOrdinates中实现的方法AppDelegate我已设置当前位置,现在我从presentedViewController访问这些位置

 let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
 pickUpDistanceLocation = appDelegate.currentLocation

我的问题是当我尝试在时间间隔内在另一个类中非常快地访问该值时,委托回调方法不会将我发送给我当前的位置。在这种情况下我得到零。但是如果我等待2-3秒并转到另一个班级,我从代表处获得价值。

任何人都可以解释一下我做错了什么吗?

1 个答案:

答案 0 :(得分:1)

这是一个架构问题 - 你说:

  

当我尝试在时间间隔内在另一个类中非常快地访问该值时,委托回调方法不会向我发送当前位置

你必须反过来 - 而不是检查当前位置,而不是因为尚未获得当前位置,你应该让HelperLocationManager在有位置时通知(好莱坞原则:不要打电话给我,我会打电话给你)。

这可以通过不同的方式完成:

  • 使用委托模式
  • 使用事件总线(可以使用NSNotificationCenter实现)
  • 使用回调

当然还有很多其他方法可以达到相同的效果。

当有多个观察者时,委托模式可能不是最佳解决方案。

我会使用回调方式,订阅者通过向HelperLocationManager提供闭包来注册位置更新。

HelperLocationManager可以将所有回调存储到数组中,并在位置更新可用时调用每个回调。可选地,如果位置已经可用,它可以在注册后立即调用闭包。

最后,订阅者必须能够取消订阅,因此HelperLocationManager应该公开一个从内部列表中删除回调的方法。

这只是一个想法 - 如上所述,它可以通过几种不同的方式完成,通常的规则是反转位置的传递方式。

注意:我会将HelperLocationManager设为单身,然后将其从AppDelegate中移除。如果我想使用HelperLocationManager,我应该直接与其联系,而不是通过第三方(应用代表)访问。