【问题标题】:Can't get coordinates from CLLocationManager in separate variable/constant无法从单独的变量/常量中的 CLLocationManager 获取坐标
【发布时间】:2017-05-24 06:31:30
【问题描述】:

我试图在 Swift 中使用一个函数的值来设置一个变量/常量,该函数在应用程序打开时查找用户的当前位置。当我取消注释打印函数时,它成功打印了坐标,但我无法访问函数之外的值。

我目前将此作为我的代码的一部分,它在 MainVC.swift 文件中作为 MainVC 类的一部分:

import UIKit
import MapKit
import CoreLocation

class MainVC: UIViewController, CLLocationManagerDelegate {
    //Map
    @IBOutlet weak var map: MKMapView!

    let manager = CLLocationManager()
    let coordinates = locationManager()
    //I've also tried using let coordinates = currentCoords

    override func viewDidLoad() {
        super.viewDidLoad()

        manager.delegate = self
        manager.desiredAccuracy = kCLLocationAccuracyBest
        manager.requestWhenInUseAuthorization()
        manager.startUpdatingLocation()
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) -> String {
        let location = locations[0]

        let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
        let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
        let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
        map.setRegion(region, animated: true)
        lat = String(myLocation.latitude)
        long = String(myLocation.longitude)
        let currentCoords:String = "\(lat);\(long)"

        //print(currentCoords)
        self.map.showsUserLocation = true

        return currentCoords
    }
}

但是我遇到了这个错误:

“不能在属性初始化器中使用实例成员 'locationManager';属性初始化器在 'self' 可用之前运行”。

当我更改代码并使用时

let coordinates = currentCoords

我得到另一个错误显示:

“使用未解析的标识符‘currentCoords’”

我也尝试过使用lazy var 和lazy let。

【问题讨论】:

  • 您需要为您发布的代码提供更多上下文。
  • 你的错误不是来自初始化程序吗?将代码从 initializer 粘贴到出现错误的位置。
  • @rmaddy 对此感到抱歉,最初发布时忘记添加它,更新了主帖子并提供了一些上下文希望对您有所帮助。
  • 发布包含您发布的代码的整个函数。请注意,“坐标”对于位置管理器的实例来说是一个可怕的名称。
  • @DuncanC 这是整个功能,我在应用程序中使用了不同的标识符,我只是在发布时更改了它以提高可读性。我在原始帖子中添加了更多信息,希望对您有所帮助。

标签: ios swift swift3 core-location


【解决方案1】:

这就是您定义公共变量的方式

let coordinates:CLLocation = nil

然后在您的 didUpdateLocations 中为坐标变量分配位置数组的最后一个元素。然后,您将可以在任何地方访问它。 请记住,didUpdateLocations 最多可能会在几秒钟后被调用,因此您的公共变量坐标将在最多几秒钟后被填充。

func coordinatesBecomeAvailable() {
    // Here you can print your coordinates or start using them for the first time
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
 let firstTime:Bool = (coordinates == nil)
 coordinates = locations[0]
 if (firstTime) // This is first time this function is called
     coordinatesBecomeAvailable()
 ......
 < Rest of your code here >
 ......
 < This function does have any return value! no String nothing >
 }

你只需要检查坐标的值是否为零。 或者您可以在 didUpdateLocations 内部检查这是否是第一次调用此委托方法。 这不是初始化和使用位置管理器的最有效和最完整的方法,我假设您刚刚发布了与您的问题相关的代码。

【讨论】:

  • 我更改了代码并添加了这个,但是当我打印坐标时它显示为零
  • 我更改了代码,以便您知道在坐标可用时何时打印。
  • @robycyr 出于某种原因我仍然没有得到 nil ?
  • 我更改了 didUpdateLocations 函数并将“locations.last”替换为“locations[0]”,就像您的代码一样,现在您可以在该行代码中放置一个断点并在调试模式下单步执行一次一行代码,看看“坐标”是否得到值。从这一点开始就是调试的问题。并且您使用“coordinatesBecomeAvailable”函数来打印或使用您第一次使用的变量。
【解决方案2】:

您应该能够像我的 buttonClick 方法一样访问 locationManager.location?.coordinate :

import UIKit
import MapKit

class ViewController: UIViewController,CLLocationManagerDelegate,MKMapViewDelegate {

    let locationManager = CLLocationManager()

    @IBAction func buttonClick(_ sender: Any) {
        let location = locationManager.location?.coordinate
        let lat:Double = (location?.latitude)!
        let lon:Double = (location?.longitude)!
        print(lat,lon)
    }

    @IBOutlet weak var mapView: MKMapView!

        override func viewDidLoad() {
        super.viewDidLoad()

        mapView.delegate = self
        mapView.showsUserLocation = true
        mapView.userTrackingMode = .follow

        locationManager.delegate = self
        locationManager.distanceFilter = kCLLocationAccuracyNearestTenMeters
        locationManager.desiredAccuracy = kCLLocationAccuracyBest

    }

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

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print("viewDidAppear")
        // status is not determined
        if CLLocationManager.authorizationStatus() == .notDetermined {
            locationManager.requestAlwaysAuthorization()
        }
            // authorization were denied
        else if CLLocationManager.authorizationStatus() == .denied {
            showAlert("Location services were previously denied. Please enable location services for this app in Settings.")
        }
            // we do have authorization
        else if CLLocationManager.authorizationStatus() == .authorizedAlways {
            locationManager.startUpdatingLocation()
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        print("didUpdateLocations")
        print(locations.last?.coordinate)
    }

    func showAlert(_ title: String) {
        let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
            alert.dismiss(animated: true, completion: nil)
        }))
        self.present(alert, animated: true, completion: nil)

    }
}

【讨论】:

  • 您好,感谢您的发帖。我试着这样做,但由于某种原因它不喜欢那种方法,我明天一上我的 MacBook 就会发布我用那种方法得到的错误。
  • 我收到以下错误:'(MainVC) -> (CLLocationManager, [CLLocation]) -> String' 类型的值没有成员'location'
  • 我在let location = locationManager.location?.coordinate 线上得到它
  • 你使用的是 swift 3.0 吗?
  • 我应该是,使用 Xcode 8 并且部署目标设置为 iOS 10
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多