2016-04-30 3 views
0

これには一般的なアプローチがあると確信していますが、検索用語を特定できません。ユーザーが場所の使用を許可した後にビューを更新するには

私は、テーブルビューと1つのセルに位置の使用をオンにするスイッチを含む設定ビューコントローラを持っています。ユーザーがそのスイッチを切り替えると、必要なアクションを実行するためにView Controllerメソッドが起動されます。

スイッチをオフにすると、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方法は、画面上とオフの場合にはスイッチによって発射されたことがある私は私のモデルに直接「オフ」のコンセプトを取っていますので、即時の効果。 「スイッチオン」の場合、私はまだそれを有効にするために私のモデルに行きますが、結果は即座に(要求がポップアップするOSによって)発生しないため、モデルが変更を登録する前にsetNeedsDisplayがディスプレイを設定しています。

理論的に私はallowLocationChangeメソッドでブロックすることができましたが、それは非常に多くのレベルでは悪い考えのように聞こえるだけです。

+1

説明が分からないだけでコードやビジュアルフローを入れてください。 – Jaimish

答えて

1

iOSのロケーション機能のルートクラスであるCLLocationManagerクラスがあります。

CLLocationManager Class Reference

私はあなたのアプリケーションのためにCLLocationManagerインスタンスを操作するための責任を負うことになる独自のクラスを、開発するためにあなたを提供すると思います。 これは、CLLocationManagerのインスタンスを隠すことになります(currentAuthorizationStatus()、authorize()...)のようなインスタンスで動作するメソッドのリストと、このクラスがCLLocationManagerインスタンスの代理人として割り当てられることが重要です。

CLLocationManagerDelegateプロトコルメソッドの1つは locationManager(_:didChangeAuthorizationStatus:)です。このメソッドの実装では、NSNoticationCenterを介して通知を送信できます。また、あなたのSettings viewControllerはこの通知に登録され、それに応じて反応する必要があります。

アプリケーションでクラスインスタンスを生き生きとしたものにする方法はあなた次第です。私はシングルトンパターンを使用します。

+0

ありがとうございます。私が追加したコードからわかるように、私はすでに変更をキャプチャしていましたが、それをビューに渡す方法を理解していないので、それが何かのようなものでなければならないと思いました。 通知が表示コントローラに届きました。正しく更新を実行するために通知を受け取るだけです。 – zkarj

関連する問題