【问题标题】:How do I update my view after the user allows location use用户允许使用位置后如何更新视图
【发布时间】:2016-04-30 04:34:34
【问题描述】:

我确信有一个通用的方法,但我无法弄清楚搜索词。

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

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

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

我正在处理模型中位置跟踪状态的变化,即位置委托,所以如果设置视图被关闭并重新打开,一切都是正常的。

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

更新:添加一些代码 sn-ps 以更好地说明。

这是我的模型类的关键部分,它们既存储我自己的位置跟踪状态(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 方法,但这在很多层面上听起来都是个坏主意。

【问题讨论】:

  • 只有描述还不够理解放一些代码和视觉流程@zkarj

标签: ios asynchronous model-view-controller location


【解决方案1】:

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

CLLocationManager Class Reference

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

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

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

【讨论】:

  • 谢谢。正如您从我添加的代码中看到的那样,我已经捕获了更改,但不明白如何将它传递给我认为它必须是这样的视图,否则我错过了一些明显的东西。我现在已经收到通知到达我的视图控制器,只需要让它正确执行更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-30
  • 1970-01-01
  • 2015-02-07
相关资源
最近更新 更多