Swift: 访问存储为变量的闭包参数

Swift: Accessing argument of closure stored as variable

我 运行 进入位置管理器的一些代码 class 并且我注意到有一个变量包含一个闭包。

var locationInfoCallBack: ((_ info: LocationInformation) -> ())!

我似乎无法访问变量的基础参数,这是首选。是否可以从上述变量中​​检索 LocationInformation

我的理解是,通过像这样传入 info 参数 self.locationInfoCallBack(info),'start' 函数将重新 运行:

根据我的经验,没有必要回忆 locationManager.requestAlwaysAuthorization()locationManager.startUpdatingLocation()

代码如下:

class Location: NSObject, CLLocationManagerDelegate {
    static let shared = Location()
    
    let locationManager : CLLocationManager
    var locationInfoCallBack: ((_ info: LocationInformation) -> ())!
       
    override private init() {
        locationManager = CLLocationManager()
        locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        locationManager.distanceFilter = kCLLocationAccuracyNearestTenMeters
        super.init()
        locationManager.delegate = self
    }
    
    func start(completion: @escaping(_ info: LocationInformation) -> Void) {
        self.locationInfoCallBack = completion
        locationManager.requestAlwaysAuthorization()
        locationManager.startUpdatingLocation()
    }

    func stop() {
        locationManager.stopUpdatingLocation()
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let mostRecentLocation = locations.last else {
            return
        }
       
        let info = LocationInformation()
        info.latitude = mostRecentLocation.coordinate.latitude
        info.longitude = mostRecentLocation.coordinate.longitude


        let geocoder = CLGeocoder()
        geocoder.reverseGeocodeLocation(mostRecentLocation) { (placemarks, error) in
            guard let placemarks = placemarks, let placemark = placemarks.first else { return }
            if let city = placemark.locality,
                let state = placemark.administrativeArea,
                let zip = placemark.postalCode,
                let locationName = placemark.name,
                let thoroughfare = placemark.thoroughfare,
                let country = placemark.country {
                info.city = city
                info.state = state
                info.zip = zip
                info.address = locationName + ", " + (thoroughfare as String)
                info.country = country
            }
            self.locationInfoCallBack(info)
        }
    }
    
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        locationManager.stopUpdatingLocation()
    }
}

class LocationInformation {
    var city: String?
    var address: String?
    var latitude: CLLocationDegrees?
    var longitude: CLLocationDegrees?
    var zip: String?
    var state: String?
    var country: String?
    
    init(city: String? = "", address: String? = "", latitude: CLLocationDegrees? = Double(0.0), longitude: CLLocationDegrees? = Double(0.0), zip: String? = "", state: String? = "", country: String? = "") {
        self.city = city
        self.address = address
        self.latitude = latitude
        self.longitude = longitude
        self.zip = zip
        self.state = state
        self.country = country
    }
}


如果底层参数不可访问,我当前的假设是变量 'locationInfoCallBack' 可用于检查 'start' 函数是否已完成。如果是这种情况,为什么不对相同的结果使用简单的布尔值呢?

当闭包为 运行 时,您可以从闭包代码访问参数,其值将是调用者传递的任何值。它与函数相同。除非函数(或闭包)是 运行,否则参数不存在。

I want it to be available app wide

那么,更合适的设计应该是不使用闭包。将闭包替换为:

var currentLocationInfo: LocationInformation?

可以删除 start 的参数:

func start() {
    locationManager.requestAlwaysAuthorization()
    locationManager.startUpdatingLocation()
}

并且在 didUpdateLocation 中,将调用 self.locationInfoCallBack(info) 替换为对 currentLocationInfo 的简单赋值:

self.currentLocationInfo = info

现在您可以从任何地方访问:

Location.shared.currentLocationInfo

这会给你你得到的位置,最后一次 didUpdateLocation 被调用,你成功 reverse-geocoded 那。

请注意,这可能是 nil,因为您可能在第一次成功之前访问它。 reverse-geocoded 一个位置。