为什么在另一个 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
保持对视图控制器的强引用。
所以你还需要把MapController
的viewController
属性改成weak
.
我正在使用 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
保持对视图控制器的强引用。
所以你还需要把MapController
的viewController
属性改成weak
.