I have existing code based on PromiseKit that I am migrating to Swift Concurrency, and in migrating it to use AsyncLocationKit, my actual sequence of events differed from your sample code in the README.md. Because of this, I created an AsyncLocationManager instance inside an async function, it didn't work at all, due to that fact that AsyncLocationManager's initializer creates a CLLocationManager without first switching to the main thread. It took me a long time to figure out what was wrong. Because of this, I would suggest that AsyncLocationKit do one or more of the following:
- Include text in the main README.md stating that when an instance of AsyncLocationManager is created, that must happen in a thread with an active RunLoop (probably the main thread). Side note on this: a globally initialized AsyncLocationManager doesn't work (I'm guessing because it is initialized before the main thread's RunLoop is created).
- Include a check inside
AsyncLocationManager.init
that throws an exception if there isn't an active RunLoop on the current thread. (I don't actually know how to check this, since RunLoop.current
will create an inactive RunLoop on the current thread when called on a thread with no RunLoop.)
- Update the first line of
AsyncLocationManager.init
to be wrapped in a call to DispatchQueue.main.sync()
if it is called from anything other than the main thread. (Note: calling DispatchQueue.main.sync()
on the main thread will result in deadlock, so this would need to check Thread.isMainThread
.)
- Add DocC-compatible documentation to the library and make sure the documentation for
AsyncLocationManager.init
and AsyncLocationManager.init(desiredAccuracy:)
states the fact that they must be called from a thread with a RunLoop.
In short, given that AsyncLocationManager is designed to be used from async code, the fact that it must be constructed outside of async code is something that I feel should be either mentioned in the documentation, or corrected to not be the case. I realize that CLLocationManager itself makes it clear in its main class documentation that there must be a RunLoop at the time of initialization. But it is not at all clear (to me, anyway) that the same is also true of AsyncLocationManager, and AsyncLocationManager's very nature of being used with async code makes it much more likely to be created from an async function.