如何在继续之前等待功能完成

时间:2017-06-05 16:05:31

标签: ios swift

在我目前的项目中,我希望能够在地图上显示用户的当前位置。 我已经通过Apple提供的requestLocation方法实现了此功能,但问题是我的代码仍在继续,而不等待requestLocation函数完成。

流程如下:首先我调用positionController.setPositionViaLocationData()函数,该函数处理requestLocation方法的设置和执行。最后,它接收坐标并将它们存储在userPosition的{​​{1}}成员中。 在下一行代码中,我想通过PositionController访问userPosition,但问题就出现了:

线......

PositionController

...在 var userPosition = positionController.getPosition() 完成之前执行,因此它采用positionController.setPositionViaLocationData()中存储的默认值。

如何在执行前让代码等待userPosition positionController.setPositionViaLocationData()? 我已经阅读了关于闭包和完成管理员的内容,但我不能让那些东西为我工作。

这两个类的代码,首先是调用函数的ViewController:

var userPosition = positionController.getPosition()

现在我的import UIKit import GoogleMaps import CoreLocation class MapViewController: UIViewController, CLLocationManagerDelegate { let positionController = PositionController() override func viewDidLoad() { super.viewDidLoad() positionController.setPositionViaLocationData() var userPosition = positionController.getPosition() setUserPositionMarkerOnMapAndShowMap(userPositionLatitude: userPosition.userLatitude, userPositionLongitude: userPosition.userLongitude) } func setUserPositionMarkerOnMapAndShowMap(userPositionLatitude: Double, userPositionLongitude: Double){ let camera = GMSCameraPosition.camera(withLatitude: userPositionLatitude, longitude: userPositionLongitude, zoom:3) let mapView = GMSMapView.map(withFrame: CGRect.zero, camera:camera) let marker = GMSMarker() self.view = mapView marker.snippet = "Munich" marker.appearAnimation = GMSMarkerAnimation.pop marker.map = mapView self.view = mapView } } 班级:

PositionController

3 个答案:

答案 0 :(得分:1)

您可以使用委托通知MapViewController用户位置已更新。

您可以在PositionController类定义

之上添加下一个协议
protocol PositionControllerDelegate: class {
  func didUpdatePosition(_ newPosition: Position)
}

然后向PositionController

添加一个新的可选属性

weak var delegate: PositionControllerDelegate?

然后调用委托方法:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let locValue: CLLocationCoordinate2D = manager.location!.coordinate
    print("locations = \(locValue.latitude) \(locValue.longitude)")
    userPosition.latitude = locValue.latitude
    userPosition.longitude = locValue.longitude
    delegate?.didUpdatePosition(userPosition)
}

在MapViewController方面,您只需要实现协议并将self分配给PositionController的委托。

override func viewDidLoad() {
    super.viewDidLoad()

    positionController.setPositionViaLocationData()
    positionController.delegate = self
    var userPosition = positionController.getPosition()
    setUserPositionMarkerOnMapAndShowMap(userPositionLatitude: userPosition.userLatitude, userPositionLongitude: userPosition.userLongitude)
}

extension MapViewController: PositionControllerDelegate {
  func didUpdatePosition(_ newPosition: Position) {
    //Do whatever you want with the position
  }
}

答案 1 :(得分:0)

我知道在CLLocationManager.requestLocation()有值时访问位置信息的两种方法。

  1. 在您的位置管理员的委托方法中调用您的函数。

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        //call function when you get user location
    }
    
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        //handle error
    }
    
  2. 使用PromiseKit,它提供只在位置管理器更新后才返回的Promise。您需要CLLocationManager.promise()才能获得在位置管理员更新其位置时返回的承诺。

  3. 如果你计划使用大量的异步调用,我会选择PromiseKit,因为它使顺序处理和运行异步函数变得非常简单。但是,了解PromiseKit的工作原理需要一些时间,所以如果你只将它用于这个单一用例,我宁愿选择方法1。

答案 2 :(得分:0)

正如Rob评论的那样,人们不能等待locationRequest方法结束。

查看代码时,应MapViewController.setUserPositionMarkerOnMapAndShowMap方法调用PositionController .locationManager(didUpdateLocations)方法。

这样做的问题是PositionController并不了解MapViewController

一些选项:

  1. MapViewController的实例传递给PositionController

  2. 完全忽略PositionController控制器并在MapViewController中实施功能(' didUpdateLocations')。

  3. PS:直接与您的问题无关,但可能表示存在一些混淆,MapViewControllerPositionController都声明了CLLocationManagerDelegate协议,但只有PositionController正在实施它。< / p>