【问题标题】:delegate return nil after calling it in a class委托在类中调用后返回 nil
【发布时间】:2019-03-24 16:00:04
【问题描述】:

我正在使用此类获取位置并将其与委托一起发送到另一个视图控制器,但委托在调用时返回 nil。 我的班级:

protocol LocationUpdateProtocol {
    func locationDidUpdateToLocation(location : CLLocation)
}
/// Notification on update of location. UserInfo contains CLLocation for key "location"
let kLocationDidChangeNotification = "LocationDidChangeNotification"
class LocationServiceHelper:NSObject,CLLocationManagerDelegate {

    static let sharedManager = LocationServiceHelper()
    private let locationManager = CLLocationManager()
    var currentLocation:CLLocation?
    weak var delegate :LocationUpdateProtocol?
    private override init() {
        super.init()
        self.locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.distanceFilter = kCLLocationAccuracyHundredMeters
        locationManager.requestAlwaysAuthorization()
        locationManager.startUpdatingLocation()
    }

    // MARK: CLLocationManagerDelegate

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let delegate = self.delegate else {
            return
        }
        currentLocation = locations.first
        let userInfo:NSDictionary = ["location":currentLocation!]
        delegate.locationDidUpdateToLocation(location: currentLocation!)
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: kLocationDidChangeNotification), object: self, userInfo: userInfo as? [AnyHashable : Any])
    }
}

我在下面的另一个类中调用了委托:

var locationServiceReference = LocationServiceHelper.sharedManager
    override func viewDidLoad() {
        super.viewDidLoad()
        fillFields()
      locationServiceReference.delegate = self
        self.mapView.showsUserLocation = true
    }

func locationDidUpdateToLocation(location: CLLocation) {
       // print(location)
        // let myLocation = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
        let myLocationForTesting = CLLocationCoordinate2D(latitude: 33.410165, longitude: 35.480060)
        myLocation = location
            let region = MKCoordinateRegion(center: myLocationForTesting, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
        self.mapView.setRegion(region, animated: true)

    }

在更新位置中,委托返回 nil,知道发生了什么吗?该函数未被调用,因为委托返回 nil。

【问题讨论】:

  • 你在哪里添加了LocationUpdateProtocol?也添加该代码。
  • 它在这个类中,在顶部
  • 我的意思是你想在哪里LocationUpdateProtocol delegate必须被调用?比如你初始化LocationServiceHelper的地方?
  • 完成,问题更新
  • 在下面查看我的答案。

标签: swift delegates location-services


【解决方案1】:
  1. 确保您的控制器仍在内存中
  2. 您不需要使用防护。可选链在这种情况下效果更好:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    currentLocation = locations.first
    let userInfo:NSDictionary = ["location":currentLocation!]
    delegate?.locationDidUpdateToLocation(location: currentLocation!)
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: kLocationDidChangeNotification), object: self, userInfo: userInfo as? [AnyHashable : Any])
}
  1. 确保在委托设置后调用func locationManager(_:didUpdateLocations)
  2. 对于将来,您希望在委托更改为时传递最后一个位置:
weak var delegate :LocationUpdateProtocol? {
    didSet { 
        guard let last = currentLocation else { return }
        delegate?.locationDidUpdateToLocation(location: last)
    }
}
  1. 由于它是只有 1 个委托的单例,因此请确保您没有将委托设置为 nil 或其他地方的其他短期对象

【讨论】:

  • 没用,delegate 仍然返回 nil,它没有崩溃,但是由于 delegate 仍然是 nil,所以没有调用函数
  • 我收到一个错误:weak must not apply to non-class-bound LocationUpdateProtocol ,考虑添加具有类绑定的协议一致性
  • @MrJ 将协议声明更改为protocol LocationUpdateProtocol: AnyObject {
  • 那就这样吧。 protocol LocationUpdateProtocol : class
  • @matt class 将被AnyObject 弃用。所以最好现在开始使用它:) forums.swift.org/t/class-only-protocols-class-vs-anyobject/…
【解决方案2】:

这段代码 -

var locationServiceReference = LocationServiceHelper.sharedManager

在您的delegate 设置之前执行,这就是为什么delegate 总是返回nil

替换

var locationServiceReference = LocationServiceHelper.sharedManager

var locationServiceReference : LocationServiceHelper!

并在viewDidLoad() 被调用后初始化。

override func viewDidLoad() {
    super.viewDidLoad()

    locationServiceReference = LocationServiceHelper.sharedManager
    locationServiceReference.delegate = self

}

希望它能帮助你。如果您仍有任何问题,请告诉我。

【讨论】:

  • 问题出在第一类,协议存在的地方,由于委托保持为零,所以函数不会被调用,我试过你的解决方案,但没有用
  • locationServiceReference.delegate = self 行将在类中设置delegate。否则delegate 始终保持nil
  • 您是否按照我的建议进行了更改
猜你喜欢
  • 1970-01-01
  • 2018-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-10
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
相关资源
最近更新 更多