Closed NasH5169 closed 6 years ago
@NasH5169 Please excuse such a late reply 🙏 . I'm looking at it now :)
@NasH5169 After a bit of test, this seems to come from the fact that CLLocationManager needs a runLoop to work, so typically on the main thread.
LocatorManager.shared.getLocation()
.then { location in
print("then" + String(data: try! JSONEncoder().encode(location), encoding: .utf8)!)
}
works while the following doesn't
DispatchQueue.global(qos: .background).async {
LocatorManager.shared.getLocation()
.then { location in
print("then" + String(data: try! JSONEncoder().encode(location), encoding: .utf8)!)
}
}
So this isn't await per se but the fact that await is using Dispatch group. Will report back when I have it working :)
When using async
wrapping await
, we get a message that corroborates our hypothesis :
A location manager (0xe86bdf0) was created on a dispatch queue executing on a thread other than the main thread. It is the developer's responsibility to ensure that there is a run loop running on the thread on which the location manager object is allocated. In particular, creating location managers in arbitrary dispatch queues (not attached to the main queue) is not supported and will result in callbacks not being received.
Another fun fact ! 😃
// Doesn't work
async {
let userLocation = try await(LocatorManager.shared.getLocation())
print(userLocation)
}
// Works
let promise = LocatorManager.shared.getLocation()
async {
let userLocation = try await(promise)
print(userLocation)
}
@NasH5169 Ok so I think I've got it now :)
First, you want to replace your do
& catch
withasync
& onError
do {
let location = try await(LocatorManager.shared.getLocation().timeout(0.2))
print("await" + String(data: try! JSONEncoder().encode(location), encoding: .utf8)!)
} catch {
print(error)
}
Becomes
async {
let location = try await(LocatorManager.shared.getLocation())
print("await" + String(data: try! JSONEncoder().encode(location), encoding: .utf8)!)
}.onError { error in
print(error)
}
await
without async
is going to block the main thread, and thus block CLLocactionManager
callbacks !
Then concerning the issue we described above, you want to make sure your Location Manager is inited on the main thread, which you can do like so :
static let shared:LocatorManager = {
return DispatchQueue.main.sync { LocatorManager() }
}()
Doing these two things should solve you issue (at least it does on my end)
Hope this helps,
@NasH5169 any news?
Yes, same result on my side. Solved thanks :-)
Hi all,
Like PromiseKit wrapping delegates example on CLLocationManager, I try to do the same with freshOS/then.
https://github.com/mxcl/PromiseKit/blob/master/Documentation/CommonPatterns.md#wrapping-delegate-systems
The promise is working with:
but not with await, my app is blocked. An idea..?
Thank a lot for helping.
All LocatorManager singleton class code