如何在函数中返回 CLLocationManager didUpdateLocations 的值?

Posted

技术标签:

【中文标题】如何在函数中返回 CLLocationManager didUpdateLocations 的值?【英文标题】:How to return the value of CLLocationManager didUpdateLocations in function? 【发布时间】:2019-07-25 10:10:58 【问题描述】:

我遇到的问题是,当我在其他类中调用 getCityName() 函数时,它返回 nil,因为 didUpdateLocations 需要更多时间来运行,如何解决这个异步问题?以及

import Foundation
import CoreLocation

class userCurrentLocation: NSObject, CLLocationManagerDelegate 

    var locationManager:CLLocationManager!
    var cityName:String!

     init(cityName:String) 
        super.init()
        setUp()
    

    func getCityName() -> String?
        return cityName
    

    func setUp() 
        if (CLLocationManager.locationServicesEnabled())
        
            locationManager = CLLocationManager()
            locationManager.delegate = self
            locationManager.desiredAccuracy = kCLLocationAccuracyBest
            locationManager.requestWhenInUseAuthorization()
            locationManager.startUpdatingLocation()
        
    

     func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 
        locations.last!.geocode  placemark, error in
            if let error = error as? CLError 
                print("CLError:", error)
                return
             else if let placemark = placemark?.first 
                    self.cityName = placemark.locality ?? ""
                    manager.stopUpdatingLocation()
            
        
    

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) 
        print(error)
    


extension CLLocation 
    func geocode(completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  
        CLGeocoder().reverseGeocodeLocation(self, completionHandler: completion)
    

【问题讨论】:

【参考方案1】:
class userCurrentLocation: NSObject, CLLocationManagerDelegate 

    var locationManager:CLLocationManager!
    var cityName:String!


    //1. Add a closure callback
    var didGetCity: ((String) -> Void)?


    //2. Send City Name when received
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 
        locations.last!.geocode  placemark, error in
            if let error = error as? CLError 
                print("CLError:", error)
                return
             else if let placemark = placemark?.first 
                    self.cityName = placemark.locality ?? ""

                    // Check for null 
                    // Send city name in the completion block
                    if (self.didGetCity != nil)
                    self.didGetCity?(self.cityName)
                    
                    manager.stopUpdatingLocation()
            
        
    


    //3. Add code to your class where you need the city Name

    var City : String?


    let locationManager = userCurrentLocation (cityName: "")
        locationManager.didGetCity = 
            [weak self] city in
            self!.City = city
        

【讨论】:

如果你只是想强制解开它,那么使用[weak self] 没有多大意义。我建议您要么保留强大的self,要么使用有条件的展开。 @Paulw11 你是对的。这是我的错误 另外,City 属性应该是 city【参考方案2】:

您可以使用 Delegate 告诉主类一切准备就绪并使用该值

import Foundation
import CoreLocation


protocol userCurrentLocationDelegate: class 
  func userCurrentLocationDidGetLocation(_ userLocation: userCurrentLocation)


class userCurrentLocation: NSObject, CLLocationManagerDelegate 

    var locationManager:CLLocationManager!
    var cityName:String!
    weak var delegate: userCurrentLocationDelegate?

 init(cityName:String) 
    super.init()
    setUp()


func getCityName() -> String?
    return cityName


func setUp() 
    if (CLLocationManager.locationServicesEnabled())
    
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
    


 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 
    locations.last!.geocode  placemark, error in
        if let error = error as? CLError 
            print("CLError:", error)
            return
         else if let placemark = placemark?.first 
                self.cityName = placemark.locality ?? ""
                manager.stopUpdatingLocation()
                delegate?.userCurrentLocationDidGetLocation(self)
        
    


func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) 
    print(error)

extension CLLocation 
    func geocode(completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  
        CLGeocoder().reverseGeocodeLocation(self, completionHandler: completion)
    

在调用这个的主类中,使用这个回调中的委托来开始调用城市名称

【讨论】:

以上是关于如何在函数中返回 CLLocationManager didUpdateLocations 的值?的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript:如何在异步内部函数中返回外部函数?

如何在 AsyncTask 中调用一个返回值函数

我如何最终在 Lambda 函数中返回 promise 的值?

如何在恐慌的 Go 函数中返回一个值?

如何在过程中显示函数返回的值

如何在函数中返回 CLLocationManager didUpdateLocations 的值?