为什么在另一个 class 中使用 locationManager 弹出窗口会立即消失?

Why does locationManager popup immediately disappear when used in another class?

我正在使用 MapKit 来使用 CLLocationManagerDelegate 来获取用户的位置。如果我要在 ViewController 的 viewDidLoad() 函数中请求用户的位置,则会出现弹出窗口,询问用户的输入。注意:请求位置所需的两个属性(Location When In Use和Location Always And When In Use)添加到Info.plist

import UIKit
import MapKit
class ViewController: UIViewController, CLLocationManagerDelegate {
      var locationManager: CLLocationManager?

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

上面的代码工作正常;当程序开始时,它会显示一个弹出窗口,询问用户他们的位置。

但是,如果我要创建一个新的 class MapController 并将相同的代码放入 class,并在 MapController 中创建一个新实例 viewDidLoad(),则当程序为运行.

时弹窗立即消失

import UIKit
class ViewController: UIViewController {

     override func viewDidLoad() {
           super.viewDidLoad()
           let mapController = MapController(viewController: self)
           mapController.initialise()
     }
}

import MapKit
class MapController: NSObject, CLLocationManagerDelegate {
      private let viewController: UIViewController
      private var locationManager: CLLocationManager

      required init(viewController: UIViewController) {
          self.viewController = viewController
          locationManager = CLLocationManager()
      }

      func initialise() {
           self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
           self.locationManager.requestWhenInUseAuthorization()
           self.locationManager.delegate = self
           self.locationManager.startUpdatingLocation()
      }
}

当上述代码为 运行 时,询问用户位置的弹出窗口立即消失。

我的问题是:为什么当 locationManager 代码在 viewDidLoad() 中时弹出窗口仍然存在,但是当代码被分离到另一个 class 并调用 viewDidLoad() 时,它立即消失。为什么会这样?

如何将 locationManager 代码分离到另一个 class 而弹出窗口不会立即消失?

这是一个内存管理问题。在 ViewController 中,您在 viewDidLoad 中创建了一个名为 mapController 的局部变量。在 viewDidLoad 结束时,那个 MapController 实例超出范围并被释放。

不要在 viewDidLoad 中使用局部变量,而是创建一个 属性。

class ViewController: UIViewController {
     var mapController: MapController!

     override func viewDidLoad() {
           super.viewDidLoad()

           mapController = MapController(viewController: self)
           mapController.initialise()
     }
}

但这现在创建了一个引用循环,因为 MapController 保持对视图控制器的强引用。

所以你还需要把MapControllerviewController属性改成weak.