Делегат должен ответить на locationManager:didUpdateLocations swift eroor

Привет, ребята, я делаю приложение в Swift 3.0, но довольно скоро столкнулся с проблемой. Я настроил необходимые функции, чтобы запросить разрешение на использование местоположения, но каждый раз, когда я запускаю приложение, я получаю ту же ошибку...

Viewcontroller.h

import UIKit
import MapKit

class ViewController: UIViewController {

    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.requestLocation()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

extension ViewController : CLLocationManagerDelegate {
    private func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
        if status == .authorizedWhenInUse {
            locationManager.requestLocation()
        }
    }

    private func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if locations.first != nil {
            print("location:: (location)")
        }
    }

    private func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        print("error:: (error)")
    }
}

Ошибка:

2016-10-31 16:12:11.436192 Assemble[57741:2743477] bundleid: com.AssembleTm.Assemble, enable_level: 0, persist_level: 0, propagate_with_activity: 0
2016-10-31 16:12:11.437006 Assemble[57741:2743477] subsystem: com.apple.siri, category: Intents, enable_level: 1, persist_level: 1, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 0, enable_private_data: 0
2016-10-31 16:12:11.524494 Assemble[57741:2743668] subsystem: com.apple.UIKit, category: HIDEventFiltered, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0
2016-10-31 16:12:11.526709 Assemble[57741:2743668] subsystem: com.apple.UIKit, category: HIDEventIncoming, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0
2016-10-31 16:12:11.561488 Assemble[57741:2743658] subsystem: com.apple.BaseBoard, category: MachPort, enable_level: 1, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 0, enable_private_data: 0
2016-10-31 16:12:11.638717 Assemble[57741:2743477] subsystem: com.apple.UIKit, category: StatusBar, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0
2016-10-31 16:12:11.744 Assemble[57741:2743477] *** Assertion failure in -[CLLocationManager requestLocation], /BuildRoot/Library/Caches/com.apple.xbs/Sources/CoreLocationFramework_Sim/CoreLocation-2100.0.12/Framework/CoreLocation/CLLocationManager.m:865
2016-10-31 16:12:11.855 Assemble[57741:2743477] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Delegate must respond to locationManager:didUpdateLocations:'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010a58d34b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x000000010873b21e objc_exception_throw + 48
    2   CoreFoundation                      0x000000010a591442 +[NSException raise:format:arguments:] + 98
    3   Foundation                          0x0000000106799edd -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
    4   CoreLocation                        0x0000000106291523 CLClientGetCapabilities + 13233
    5   Assemble                            0x00000001061e1976 _TFC8Assemble14ViewController11viewDidLoadfT_T_ + 294
    6   Assemble                            0x00000001061e19e2 _TToFC8Assemble14ViewController11viewDidLoadfT_T_ + 34
    7   UIKit                               0x000000010708f06d -[UIViewController loadViewIfRequired] + 1258
    8   UIKit                               0x000000010708f4a0 -[UIViewController view] + 27
    9   UIKit                               0x0000000106f59045 -[UIWindow addRootViewControllerViewIfPossible] + 71
    10  UIKit                               0x0000000106f59796 -[UIWindow _setHidden:forced:] + 293
    11  UIKit                               0x0000000106f6d0a9 -[UIWindow makeKeyAndVisible] + 42
    12  UIKit                               0x0000000106ee6259 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4818
    13  UIKit                               0x0000000106eec3b9 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1731
    14  UIKit                               0x0000000106ee9539 -[UIApplication workspaceDidEndTransaction:] + 188
    15  FrontBoardServices                  0x000000010e1cf76b __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 24
    16  FrontBoardServices                  0x000000010e1cf5e4 -[FBSSerialQueue _performNext] + 189
    17  FrontBoardServices                  0x000000010e1cf96d -[FBSSerialQueue _performNextFromRunLoopSource] + 45
    18  CoreFoundation                      0x000000010a532311 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    19  CoreFoundation                      0x000000010a51759c __CFRunLoopDoSources0 + 556
    20  CoreFoundation                      0x000000010a516a86 __CFRunLoopRun + 918
    21  CoreFoundation                      0x000000010a516494 CFRunLoopRunSpecific + 420
    22  UIKit                               0x0000000106ee7db6 -[UIApplication _run] + 434
    23  UIKit                               0x0000000106eedf34 UIApplicationMain + 159
    24  Assemble                            0x00000001061e3fcf main + 111
    25  libdyld.dylib                       0x000000010af5b68d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

Я новичок в Swift 3.0, но я не смог найти ничего, как решить эту проблему (я уже посмотрел его на stackru, но ответ, который они дали, не помог мне...)

7 ответов

Решение

Вы используете xcode8 и swift3, но ваши методы делегата копируются из swift 2. Измените методы делегата, как показано ниже.

extension ViewController : CLLocationManagerDelegate {

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
         print("error:: \(error.localizedDescription)")
    }

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if status == .authorizedWhenInUse {
            locationManager.requestLocation()
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        if locations.first != nil {
            print("location:: (location)")
        }

    }

}

Эту ошибку можно получить, если вы запрашиваете местоположение у менеджера местоположений, и его делегат равен нулю. Убедитесь, что вы всегда устанавливаете делегата перед вызовом любого запроса местоположения.

import UIKit
import CoreLocation

class ViewController: UIViewController {
    
    var locationManager = CLLocationManager()

    override func viewDidLoad() {
        
        super.viewDidLoad()

        locationManager.delegate = self        
        locationManager.requestWhenInUseAuthorization()
        locationManager.requestLocation()
    }
}

extension ViewController : CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if let location = locations.first {
            print("Location data received.")
            print(location)
        }
    }
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("Failed to get users location.")
    }
}

Делегат должен быть назначен перед вызовом функции requestLocation(), потому что после завершения requestLocation() он вызовет didUpdateLocations, но для вызова didUpdateLocations он должен знать, какой объект didUpdateLocations вызывается. Чтобы уточнить, что для компилятора используется
locationManager.delegate = self до вызова locationManager.requestLocation().

В расширении протокола CLLocationManagerDelegate реализуйте didUpdateLocations и didFailWithError.

Другая возможная причина ошибки заключается в том, что у вас есть только метод для

locationManager(_:didUpdateLocations:)

и вам не хватает метода для

locationManager(_:didFailWithError:)

Согласно документации requestLocation():

При использовании этого метода связанный делегат должен реализовать методы locationManager (: didUpdateLocations:) и locationManager (: didFailWithError:). Невыполнение этого требования - ошибка программиста.

Это сработало для меня

      import UIKit
import CoreLocation

class WeatherViewController: UIViewController {
    @IBOutlet weak var conditionImageView: UIImageView!
    @IBOutlet weak var temperatureLabel: UILabel!
    @IBOutlet weak var cityLabel: UILabel!
    @IBOutlet weak var searchInputField: UITextField!
    var weatherManager = WeatherManager()
    var locationManager=CLLocationManager()
    override func viewDidLoad() {
        super.viewDidLoad()
        self.searchInputField.delegate=self
        weatherManager.delegate=self
        locationManager.delegate = self
        locationManager.requestWhenInUseAuthorization()
        locationManager.requestLocation()
        // Do any additional setup after loading the view.
    }
 
}
extension WeatherViewController : CLLocationManagerDelegate {

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
         print("error:: \(error.localizedDescription)")
    }

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if status == .authorizedWhenInUse {
            locationManager.requestLocation()
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        if locations.first != nil {
            print("location:: \(locations[0])")
        }

    }

}

Как упоминалось в этом ответе , ваша проблема может быть похожа на мою, имея свой собственный Errorкласс, который конфликтует с Swift.Error

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

Перепробовал все способы выше. И обнаружил, что для этого необходимы следующие 2 шага.

  1. Установка свойства делегата на себя
    locationManager.delegate = self

  2. Добавление метода делегата DidFailWithError, даже если не требуется конкретной реализации.
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { print("Failed") }

Другие вопросы по тегам