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

时间:2016-04-30 04:34:34

标签: ios asynchronous model-view-controller location

我确信这是一种通用方法,但我无法弄清楚搜索条件。

我有一个设置视图控制器,它包含一个表视图,在一个单元格中有一个开关来打开位置使用。当用户切换该开关时,我触发视图控制器方法以采取必要的操作。

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

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

我正在处理模型中位置跟踪状态的更改,即位置委托,因此如果设置视图被取消并重新打开,则所有内容都应该是这样。

我的问题是如何异步告诉我的视图更新,假设它仍然显示。除非用户是超人,否则在物理上肯定它仍会在屏幕上显示,但逻辑上它不一定是。

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

以下是我的模型类的关键部分,它们都存储我自己的位置跟踪状态(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方法,并且在关闭它的情况下立即生效,因为我将“关闭”概念直接用于我的模型。在“开启”的情况下,我仍然会转到我的模型来实现它,但结果不是立即的(由于操作系统弹出请求),因此setNeedsDisplay在模型注册更改之前设置显示

理论上我可以在allowLocationChange方法中阻塞,但这听起来像是一个很糟糕的想法。

1 个答案:

答案 0 :(得分:1)

有一个CLLocationManager类,它是iOS中位置功能的根类。

CLLocationManager Class Reference

我建议您开发自己的类,它将负责为您的应用程序使用CLLocationManager实例。 它将隐藏CLLocationManager的实例,一个使用该实例的方法列表(如currentAuthorizationStatus(),authorize()...),更重要的是这个类将被指定为CLLocationManager实例的委托。

CLLocationManagerDelegate协议方法之一是 locationManager(_:didChangeAuthorizationStatus:)。在实施此方法时,您可以通过NSNoticationCenter发布通知。并且您的Settings viewController应该订阅此通知并做出相应的反应。

由您决定如何使您的类实例在您的应用程序中保持活力和独特性。我使用单身模式。