swift - 中间件中的闭包为零
问题描述
我正在努力使用 SwiftUI 实现类似通量的实现。
我想跟踪用户的位置以及每当有新的位置更新时。因此我正在使用中间件。日志记录和 Firebase 身份验证中间件正在工作,但位置跟踪不起作用。因为 newLocation 是 nil,但是如果我将闭包 location.newLocation {} 放在 MiddlewareProvider 的 init 中,它会发布位置更改。为什么它在中间件中为零?
我包括了 firebase 和 logging 中间件来显示正在工作的中间件:
class VMiddlewareProvider: MiddlewareProvider {
private var location: TrackLocation
init() {
self.location = TrackLocation()
}
func provideMiddleware() -> [Middleware<FluxState>] {
return [
loggingMiddleware(),
locationTrackingMiddleware(),
firebaseMiddleware()
]
}
private func loggingMiddleware() -> Middleware<FluxState> {
let loggingMiddleware: Middleware<AppState> = { dispatch, getState in
return { next in
return { action in
#if DEBUG
let name = __dispatch_queue_get_label(nil)
let queueName = String(cString: name, encoding: .utf8)
print("#Action: \(String(reflecting: type(of: action))) on queue: \(queueName ?? "??")")
#endif
return next(action)
}
}
}
return loggingMiddleware
}
private func locationTrackingMiddleware() -> Middleware<FluxState> {
let middleware: Middleware<AppState> = { dispatch, getState in
return { next in
return { action in
switch action as? LocationAction {
case .trackLocation:
self.location.newLocation = { result in
/// never gets called because newLocation is nil
print(result)
}
return next(action)
default:
return next(action)
}
return next(action)
}
}
}
return middleware
}
private func firebaseMiddleware() -> Middleware<FluxState> {
let firebaseMiddleware: Middleware<AppState> = { dispatch, getState in
return { next in
return { action in
switch action {
case let action as AccountActions.Authenticate:
let handle = Auth.auth().addStateDidChangeListener { (auth, user) in
if let user = user {
return next(AccountActions.AuthentificationAction(isLoggedIn: true, userUID: user.uid))
} else {
return next(AccountActions.AuthentificationAction(isLoggedIn: false, userUID: nil))
}
}
default:
return next(action)
}
}
}
}
return firebaseMiddleware
}
}
TrackLocation 类如下所示:
class TrackLocation: NSObject {
let locationManager = CLLocationManager()
var newLocation: ((CLLocation)->())?
override init() {
super.init()
askForPermission()
locationManager.delegate = self
locationManager.startUpdatingLocation()
locationManager.startMonitoringSignificantLocationChanges()
locationManager.startMonitoringVisits()
}
func checkAuthorisation() {
askForPermission()
}
func askForPermission() {
locationManager.requestWhenInUseAuthorization()
}
}
extension TrackLocation: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didVisit visit: CLVisit) {
if let location = manager.location {
newLocation?(location)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
newLocation?(locations.last!)
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
print(status)
}
}
解决方案
有两个可能的错误: 1. 这个函数实际上并没有调用 self.location.newLocation
. 请小心并调试它。
private func locationTrackingMiddleware() -> Middleware<FluxState> {
let middleware: Middleware<AppState> = { dispatch, getState in
return { next in
return { action in
switch action as? LocationAction {
case .trackLocation:
//// this code isn't called! please, check
self.location.newLocation = { result in
/// never gets called because newLocation is nil
print(result)
}
return next(action)
default:
return next(action)
}
return next(action)
}
}
}
return middleware
}
- 在您的代码中的某处,您删除了这个变量:
self.location.newLocation = nil
顺便说一句,你可以在某个地方删除变量location
推荐阅读
- php - 当你给一个数组赋值而索引为空时会发生什么?
- javascript - express-validator isAfter 总是假的
- c# - 如何将安装程序单选按钮对话框中的输入用作文件系统 DefaultLocation 的一部分的变量
- python - 有没有办法错开或躲避多个 matplotlib.plot 误差线?
- java - Android File.listFiles() 返回 null
- python - 我只能在python中将某些变量设置为true时记录吗?
- c++ - 我的代码无法将输入验证为整数
- javascript - 如何在JS中存储链接并通过html动态打开?
- ios - 观察者类没有收到通知
- sql-server - SQL Server、LIKE 与 RTRIM 性能