2016-06-22 6 views
4

ユーザーがボタンをタップするとユーザーの場所を収集し、後でその場所をアプリケーションで使用します。私の現在の実装では、ボタンをタップすると、ユーザは場所を共有できるようにするように促され、アプリにログインする必要があります(迷っている場合は匿名でFirebase経由でログインする必要があります)。コンソールに接続します。プロンプトの作品は、しかし、許可する場所ボタンがヒットした後、私のアプリケーションはdue to uncaught exception 'NSInternalInconsistencyException'エラー:ユーザーの場所を収集するときに 'DelegateはlocationManager:didUpdateLocations:に応答する必要があります'

を終了した理由は、私は私のコードでdidUpdateLocations:機能を持っているので'Delegate must respond to locationManager:didUpdateLocations:'

は奇妙されたものです。

私は何が起こっているのか分かりません。どんな助けもありがとうございます。私のViewControllerのコードは下です、ありがとう!

/* 
* Copyright (c) 2016 Ahad Sheriff 
* 
*/ 

import UIKit 
import Firebase 
import CoreLocation 

class LoginViewController: UIViewController { 

    // MARK: Properties 
    var ref: FIRDatabaseReference! // 1 
    var userID: String = "" 

    var locationManager = CLLocationManager() 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     ref = FIRDatabase.database().reference() // 2 
    } 

    @IBAction func loginDidTouch(sender: AnyObject) { 

     //ask user to enable location services 
     locationManager.requestWhenInUseAuthorization() 

     if CLLocationManager.locationServicesEnabled() { 
      //collect user's location 
      locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers 
      locationManager.requestLocation() 
      locationManager.startUpdatingLocation() 

      let location = self.locationManager.location 

      var latitude: Double = location!.coordinate.latitude 
      var longitude: Double = location!.coordinate.longitude 

      print("current latitude :: \(latitude)") 
      print("current longitude :: \(longitude)") 

      //Log in to application anonymously using Firebase 
      FIRAuth.auth()?.signInAnonymouslyWithCompletion() { (user, error) in 
       if let user = user { 
        print("User is signed in with uid: ", user.uid) 
        self.userID = user.uid 
       } else { 
        print("No user is signed in.") 
       } 

       self.performSegueWithIdentifier("LoginToChat", sender: nil) 

      } 

     } 

     else { 
      print("Unable to determine location") 
     } 

    } 

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 
     super.prepareForSegue(segue, sender: sender) 
     let navVc = segue.destinationViewController as! UINavigationController // 1 
     let chatVc = navVc.viewControllers.first as! ChatViewController // 2 
     chatVc.senderId = userID // 3 
     chatVc.senderDisplayName = "" // 4 
    } 

    func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) 
    { 
     //--- CLGeocode to get address of current location ---// 
     CLGeocoder().reverseGeocodeLocation(manager.location!, completionHandler: {(placemarks, error)->Void in 

      if (error != nil) 
      { 
       print("Reverse geocoder failed with error" + error!.localizedDescription) 
       return 
      } 

      if placemarks!.count > 0 
      { 
       let pm = placemarks![0] as CLPlacemark 
       self.displayLocationInfo(pm) 
      } 
      else 
      { 
       print("Problem with the data received from geocoder") 
      } 
     }) 

    } 


    func displayLocationInfo(placemark: CLPlacemark?) 
    { 
     if let containsPlacemark = placemark 
     { 
      //stop updating location 
      locationManager.stopUpdatingLocation() 

      let locality = (containsPlacemark.locality != nil) ? containsPlacemark.locality : "" 
      let postalCode = (containsPlacemark.postalCode != nil) ? containsPlacemark.postalCode : "" 
      let administrativeArea = (containsPlacemark.administrativeArea != nil) ? containsPlacemark.administrativeArea : "" 
      let country = (containsPlacemark.country != nil) ? containsPlacemark.country : "" 

      print(locality) 
      print(postalCode) 
      print(administrativeArea) 
      print(country) 
     } 

    } 


    func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) { 
     print("Error while updating location " + error.localizedDescription) 
    } 


} 

答えて

9

まず、あなたがCLLocationManagerDelegateを確認することを明示的に追加します。CLLocationManagerのためのデリゲートプロパティを設定

class LoginViewController: UIViewController, CLLocationManagerDelegate 

第二に、:

override func viewDidLoad() { 
    super.viewDidLoad() 
    locationManager.delegate = self 
    ref = FIRDatabase.database().reference() 
} 

第三に、CLLocationManagerDelegateドキュメントに私はあなたの宣言は異なる見ますdidUpdateLocationsdidFailWithErrorの方法:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 
func locationManager(_ manager: CLLocationManager, didFailWithError error: NSError) 

また、コードには他にもいくつか問題があります。彼らはすべて安全でないラッピングについてです。安全でないアンラップを使用しないでください!どこでも。これを行うと、選択哲学を殺している。一方、正しいことをすると、アプリの安定性が大幅に向上します。 loginDidTouch機能メイク、次の修正では:あなたは、あなたの場所はまだ決まっていない、この機能を初めて呼び出すと

var latitude: Double? = location?.coordinate.latitude 
var longitude: Double? = location?.coordinate.longitude 

は(それはあなたは、デリゲートメソッド内の位置を取得します、非同期で決定されます)、あなたは致命的なエラー時にを持っている理由のthats使用されていない力unwrapp。 didUpdateLocations機能で:

if let pm = placemarks?.first 
{ 
    self.displayLocationInfo(pm) 
} 

コードのこの部分の補正は、元のコード、その後短く、一度に2クラッシュする可能性を防ぎます - placemarksがnilのときplacemarksがnilではありませんが、空の配列

とき
+0

あなたが提案した変更を追加してアプリケーションを実行したとき、私は '致命的なエラーが発生しました:オプションの値をアンラッピングしている間に予期せぬ発見なし ' –

+0

' _ manager'行 –

+0

@AhadSheriffのチェックが修正された答え –

関連する問題