【问题标题】:Why isn't locationManager didUpdateLocation working?为什么 locationManager didUpdateLocation 不起作用?
【发布时间】:2015-08-18 12:35:25
【问题描述】:

将 CoreLocation.Foundation 添加到 BuildPhase 并在文件顶部导入后,如果我将以下内容放入带有按钮的视图控制器中,我可以获得位置信息:

@IBAction func locationButton(sender: AnyObject) {
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestWhenInUseAuthorization()
    locationManager.startUpdatingLocation()
}

它使用 CLGeocoder().reverseGeocodeLocation completionHandler 继续到 locationManager didUpdateLocations,它在另一个函数中显示位置信息 - 这很有效。

但是,当我尝试在我的数据模型中传输相同的代码时,它不起作用。我使用以下设置模型:

import CoreLocation

class Record: NSObject, CLLocationManagerDelegate
{
    let locationManager = CLLocationManager()

因为没有按钮,所以我把locationManager的代码放到了:

        override init()
{
    iD = NSUUID().UUIDString

    super.init()

    if (CLLocationManager.locationServicesEnabled())
    {
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.requestWhenInUseAuthorization()

        switch CLLocationManager.authorizationStatus() {
        case .AuthorizedWhenInUse, .AuthorizedAlways:
            locationManager.startUpdatingLocation()
        case .NotDetermined:
            locationManager.requestWhenInUseAuthorization() // or request always if you need it
        case .Restricted, .Denied:
            print("tell users that they need to enable access in settings")
        default:
            break
        }
        print("Location services available")
        if CLLocationManager.authorizationStatus() == .NotDetermined
        {
            print("Still Not Determined")
        }
    } else { print("Location services not available") }

}

我收到“可用的定位服务”。但是下面的代码从不向控制台打印任何内容,也不会调用函数 toSetLocationStamped。

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!)
{
    print("started location man")
    CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler:        //pass the location co-ordinates
        {
            (placemarks, error) -> Void in

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

            if placemarks.count > 0         //process the location array (placemarks)
            {
                let pm = placemarks[0] as! CLPlacemark
                self.toSetLocationStamped(pm)
                print("got here")
            } else
            {
                println("Problem receiving data from geocoder")
            }
    })
}

如果我把一个deinit类记录,用一个简单的打印日志,没有输出。

deinit
{
    print("deinit")
}

我正在初始化一个 dummyRecord: Record from an required init in MasterViewController class:

class MasterViewController: UITableViewController
{
var records = [Record]()
var subjectDescription: String?

// weak var delegate: MonsterSelectionDelegate?        // property for object conforming to MSDelegate

required init(coder aDecoder: NSCoder)      //      // coder because class is loaded from Storyboard
{
    super.init(coder: aDecoder)

    var dummyRecord1 = Record()
    dummyRecord1.details = "All was very good and strong with a little bit of lemon on the side of the hill."
    dummyRecord1.dateTimeEntered = NSDate(dateString: "2015-07-22")
    dummyRecord1.subject = "Clouds"
    dummyRecord1.locationEntered = "Drittelsgasse 1, 69493 Großsachsen, Germany."
    dummyRecord1.photos.append(UIImage(named: "zombies.jpg")!)

    records.append(dummyRecord1)
}

【问题讨论】:

  • 你如何创建这个对象的一个​​实例,你是否持有一个引用,这样它就不会被释放?
  • 尝试将代码放在主线程块之间的init方法中。我曾经遇到过这样的问题。
  • 就 Paulw11 而言,您可能希望实现一个 deinit 方法来记录此对象何时被释放,以确保在异步调用完成之前它不会被释放。
  • 我已经更新了这个问题,尽我所能解决 cmets - 尤其是 Paulw 和 Rob。我不认为这是另一个问题的重复,如果是,请您解释一下如何设置 NSLocationAlwaysUsageDescription (对于第 1 点);而且,对于第 3 点,我真的很想看到模型中设置的值,而不是在视图控制器级别调用(这不是 MVC,还是我走得太远了)。

标签: ios swift core-location cllocationmanager


【解决方案1】:

打电话后

self.locationManager.requestWhenInUseAuthorization()

您不能立即开始更新位置。该调用是异步的。

以下是正确的做法:

1) 查看授权状态:

switch CLLocationManager.authorizationStatus() {
    case .AuthorizedWhenInUse, .AuthorisedAlways:
        locationManager.startUpdatingLocation()
    case .NotDetermined:
        locationManager.requestWhenInUseAuthorization() // or request always if you need it
    case .Restricted, .Denied:
        // tell users that they need to enable access in settings
    default:
        break
}

2) 如果您之前已授权您的应用,这应该会更新位置。但是,如果您不这样做,则会出现一个弹出窗口。为了响应授权状态的变化,您需要添加另一个函数:

func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
    if (status == .AuthorizedAlways) || (status == .AuthorizedWhenInUse) {
        locationManager.startUpdatingLocation()
    }
}

【讨论】:

  • 这是有道理的。我已经尝试了我认为你的意思,并更新了我的问题 - 请参阅覆盖初始化。但是,不幸的是,它仍然没有要求允许位置服务,我仍然没有进入 didUpdateLocations 方法。而且,如果我在覆盖初始化结束时检查 CLLocationManager.authorizationStatus() == .NotDetermined,它仍然评估为真。我真的一定是在做一些迟钝的事情。
  • 啊——但我确实进入了 didChangeAuthorisationStatus,但 if 语句(.AuthorizedAlways 或 ..WhenInUse)没有评估为 true...
  • @DrWhat 如果您没有收到要求授予位置访问权限的弹出窗口,则意味着您禁用了位置访问权限。它要么被全局禁用,要么被这个特定的应用程序禁用。您只会弹出一次,如果用户按否,您将无法再次询问 - 他们必须在位置设置中手动打开它。转到设置 -> 隐私 -> 位置服务,并确保它们在全局和您的应用程序中均已启用
  • 我认为您是对的,因为我在另一个项目中尝试了您的代码,并且效果很好。但是,如果我进入模拟器的设置,全局设置就会打开。但是,如果我从那里单击系统服务,整个模拟器就会冻结(无法前进,无法返回)。我可以访问“手机”之外的菜单,但我必须关闭整个模拟器才能在实际手机上执行任何操作。我假设在系统服务中将是我的应用设置(?)。
  • @DrWhat 只需从模拟器中删除您的应用并重新安装 :)
猜你喜欢
  • 2013-06-19
  • 2012-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多