2017-07-10 14 views
0

私はアプリでいくつかのビューに必要なため、ロケーション認可を処理するシングルトンクラスを作成しました。そこで私は以下のLocation.swiftクラスを作成しました。アプリが終了した後にロケーション認可の警告が表示される

注:私は、Info.plistのに正しく追加されている、および他の記事が、どれもいくつか見てきましたが、この(私が見つけた、少なくともどれも)

protocol LocationServiceDelegate { 
    func tracingLocation(currentLocation: CLLocation) 
    func tracingLocationDidFailWithError(error: NSError) 
} 

class Location: NSObject,CLLocationManagerDelegate { 

    var latitude: Double! 
    var longitude: Double! 
    var currentLocation : CLLocation! 

    var locationManager: CLLocationManager? 
    var lastLocation: CLLocation? 
    var delegate: LocationServiceDelegate? 

    static let sharedInstance:Location = { 
     let instance = Location() 
     return instance 
    }() 

    override init() { 
     super.init() 
     self.locationManager = CLLocationManager() 
     self.locationManager?.delegate = self 

     guard let locationManagers = self.locationManager else { 
      return 
     } 

     if CLLocationManager.authorizationStatus() == .notDetermined { 
      locationManagers.requestWhenInUseAuthorization() 
     } 

     locationManagers.desiredAccuracy = kCLLocationAccuracyBest 
     locationManagers.pausesLocationUpdatesAutomatically = false 
     locationManagers.distanceFilter = 0.1 

    } 

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { 

    } 

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 
     guard let location = locations.last else { 
      return 
     } 
     self.lastLocation = location 
     updateLocation(currentLocation: location) 

    } 

    @nonobjc func locationManager(manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) { 
     switch status { 
     case .notDetermined: 
      locationManager?.requestWhenInUseAuthorization() 
      break 
     case .authorizedWhenInUse: 
      locationManager?.startUpdatingLocation() 
      break 
     case .authorizedAlways: 
      locationManager?.startUpdatingLocation() 
      break 
     case .restricted: 
      // restricted by e.g. parental controls. User can't enable Location Services 
      break 
     case .denied: 
      // user denied your app access to Location Services, but can grant access from Settings.app 
      break 
     } 
    } 


    // Private function 
    private func updateLocation(currentLocation: CLLocation){ 

     guard let delegate = self.delegate else { 
      return 
     } 

     delegate.tracingLocation(currentLocation: currentLocation) 
    } 

    private func updateLocationDidFailWithError(error: NSError) { 

     guard let delegate = self.delegate else { 
      return 
     } 

     delegate.tracingLocationDidFailWithError(error: error) 
    } 

    func startUpdatingLocation() { 
     print("Starting Location Updates") 
     self.locationManager?.startUpdatingLocation() 
     currentLocation = locationManager?.location 
     Location.sharedInstance.latitude = currentLocation.coordinate.latitude 
     Location.sharedInstance.longitude = currentLocation.coordinate.longitude 
     print(Location.sharedInstance.latitude, Location.sharedInstance.longitude) 
     //  self.locationManager?.startMonitoringSignificantLocationChanges() 
    } 

    func stopUpdatingLocation() { 
     print("Stop Location Updates") 
     self.locationManager?.stopUpdatingLocation() 

    } 


} 

私のアプリがクラッシュさに対処しないように見える、と私は思います位置認可が最初に設定されていないためです。面白いのは、位置情報サービスを許可するようにユーザーに促すリクエストアラートが、あなたがアプリを離れるまで表示されないということです。

アプリを終了して位置情報サービスを受け入れると、アプリは正常に動作します。だから私の質問は、警告が表示されない理由は何ですか?

これは実際のデバイスでのみ発生していることにも注目してください。シミュレータでは、初期ビューがロードされているときに警告がポップアップします。

ロードするようになって、次のようにショーのデータがあるされて私の最初のビュー:

import UIKit 
import Alamofire 

class CurrentWeatherVC: UIViewController { 

    @IBOutlet weak var locationLabel: UILabel! 
    @IBOutlet weak var weatherIcon: UIImageView! 
    @IBOutlet weak var currentTempLabel: UILabel! 
    @IBOutlet weak var weatherTypeLabel: UILabel! 
    var currentWeather : CurrentWeather! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     Location.sharedInstance.locationManager(manager: Location.sharedInstance.locationManager, didChangeAuthorizationStatus: .authorizedWhenInUse) 
     currentWeather = CurrentWeather() 
    } 

    override func viewDidAppear(_ animated: Bool) { 
     super.viewDidAppear(animated) 
     Location.sharedInstance.startUpdatingLocation() 
     currentWeather.downloadWeatherDetails { 
        self.updateMainUI() 
     } 
    } 

    func updateMainUI() { 
     //Double value convterted to string for current temp. 
     //Added the degree symbol here 
     //For forecast it gets added in before saved into list so be aware of that. 
     currentTempLabel.text = "\(currentWeather.currentTemp)°" 
     weatherTypeLabel.text = currentWeather.weatherType 
     locationLabel.text = currentWeather.cityName 
     weatherIcon.image = UIImage(named: currentWeather.weatherType) 
    } 

} 
+0

私は現在の認証ステータスをチェックしません。毎回使用許可があるときにリクエストしてください。 iOSはユーザーに一度だけプロンプトを表示します。 – Paulw11

+0

@ Paulw11ええ私もそれをリクエストしてみましたが、同じ問題はそのままです。アラートは、ホームボタンをクリックしてアプリを終了するまで表示されません。シミュレータの警告が正しく表示されますが、これは奇妙です。たぶんそれはメインビューに読み込まれないビューと関係があるでしょうか? – mufc

+0

メインスレッドをブロックしているか、バックグラウンドスレッドからUIを更新しているようです。ビューコントローラからデリゲートメソッドを呼び出していますが、これを行うべきではありません。 'CLLocationManager'だけがデリゲート関数を呼び出す必要があります。 – Paulw11

答えて

0

私はdownloadWeatherDetailsの実装がdataTaskまたはバックグラウンドで実行される他のNSURLSessionのいずれかの方法を使用しています疑い。

のみmainQueueにUIのものを呼び出していることを確認してください:

// ... 
DispatchQueue.main.async { 
    self.updateMainUI() 
} 
// ... 
関連する問題