用户允许位置使用后如何更新我的视图

How do I update my view after the user allows location use

我确定有一个通用的方法来解决这个问题,但我无法找出搜索词。

我有一个设置视图控制器,其中包括一个 table 视图,并且在一个单元格中有一个用于打开位置使用的开关。当用户切换那个开关时,我触发一个视图控制器方法来采取必要的行动。

如果他们关闭开关,然后我告诉我的模型将该选择存储在我的 NSUserDefaults 中并更新视图以反映这一点(包括删除一些 table 单元格)。这里没问题。

如果他们打开开关(第一次),我的方法会在用户允许在系统弹出窗口中使用位置之前触发并完成。因此视图没有被更新。这在技术上是正确的,但用户体验不佳,因为 UI 不会更新以反映他们的更改。

我正在处理模型中位置跟踪状态的更改,这是位置委托,因此如果设置视图被关闭并重新打开,一切都应该如此。

我的问题是如何异步告诉我的视图更新,假设它仍然显示。除非用户是超人,否则它似乎肯定会出现在屏幕上,尽管从逻辑上讲它不需要。

更新:添加一些代码片段以更好地说明。

这是我的模型 class 的关键部分,它既存储我自己的位置跟踪状态(useLocation 变量)又充当位置管理器委托:

public class WorldModel : NSObject, CLLocationManagerDelegate {
    var useLocation = false

    override init() {

        super.init()
        let userDefaults = NSUserDefaults.standardUserDefaults()
        useLocation = userDefaults.boolForKey("useLocation")
        let locationStatus = CLLocationManager.authorizationStatus()
        switch locationStatus {
        case .NotDetermined:
            useLocation = false
        case .AuthorizedAlways, .AuthorizedWhenInUse:
            break
        case .Denied, .Restricted:
            useLocation = false
            userDefaults.setBool(false, forKey: "useLocation")
        }
        if useLocation {
            setLocationTracking(true)
        }
    }

    // ================================================================================
    // Turn on or off location tracking for the model
    // ================================================================================
    public func setLocationAllowed(allowed: Bool) {
        useLocation = allowed
        setLocationTracking(allowed)
    }

    // ================================================================================
    // Turn on or off location tracking with the OS
    // ================================================================================
    public func setLocationTracking(state: Bool) {
        if state {
            locationManager.delegate = self
            locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
            locationManager.requestWhenInUseAuthorization()
            locationManager.pausesLocationUpdatesAutomatically = true
            locationManager.startUpdatingLocation()
        } else {
            locationManager.stopUpdatingLocation()
        }
    }

    // ================================================================================
    // Capture location permission changes from the OS
    // ================================================================================
    public func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
        let userDefaults = NSUserDefaults.standardUserDefaults()
        switch status {
        case .NotDetermined:
            useLocation = false
        case .AuthorizedAlways, .AuthorizedWhenInUse:
            useLocation = true
            userDefaults.setBool(true, forKey: "useLocation")
        case .Denied, .Restricted:
            useLocation = false
            userDefaults.setBool(false, forKey: "useLocation")
        }
    }
}

这里是管理我要更新的设置视图的视图控制器。 (相关部分仅重复。)

class SettingsViewController2: UIViewController, UITableViewDataSource, UITableViewDelegate {
    var theWorldModel : WorldModel?

    func allowLocationChange(sender: UISwitch) {
        guard let ourWorld = theWorldModel else {
            return
        }
        ourWorld.setLocationAllowed(sender.on)
        self.view.setNeedsDisplay()
    }
}

allowLocationChange 方法由屏幕上的开关触发,在关闭它的情况下会立即生效,因为我将 "switch off" 概念直接应用到我的模型中。在 "switch on" 的情况下,我仍然去我的模型来实现它,但是结果不是立竿见影的(由于 OS 弹出请求)所以 setNeedsDisplay 在模型已注册更改。

理论上我可以阻止 allowLocationChange 方法,但这在很多层面上听起来都是个坏主意。

有一个 CLLocationManager class,它是 iOS 中定位功能的根 class。

CLLocationManager Class Reference

我建议您开发自己的 class,它将负责为您的应用程序使用 CLLocationManager 实例。 它会隐藏 CLLocationManager 的实例,一个与该实例一起工作的方法列表(如 currentAuthorizationStatus()、authorise()...),更重要的是,这个 class 将被分配为 CLLocationManager 的委托实例.

CLLocationManagerDelegate 协议方法之一是 locationManager(_:didChangeAuthorizationStatus:)。在这个方法的实现中,你可以通过 NSNoticationCenter post 通知。并且您的设置 viewController 应该订阅此通知并做出相应的反应。

如何让您的 class 实例在您的应用程序中保持活动状态和唯一性取决于您。我使用单例模式。