Bug number FB7285688.
Thanks for that.
Are those references to the configuration error what causes the trouble?
Yes. If I comment out lines 11 through 29 of your test code, the reference to
NEHotspotConfigurationErrorDomain
goes away. If I then uncomment lines 28 through 29, it comes back.
Unfortunately can not use
if #available(iOS 13.0, *) {
as it would still crash.
Right. The
#available
guard prevents you from running that code but the issue here is that the linker has added a strong reference to the symbol, and it does that because it thinks the symbol is available all the way back to iOS 11.
It’s tricky to work around this because just touching the error codes, as shown below, triggers the reference )-:
print(NEHotspotConfigurationError.Code.invalid)
The best option I can think of right now is to bounce into
NSError
space:
if let error = error as NSError? {
switch (error.domain, error.code) {
… case clauses here …
}
}
Then declare the
NSError
equivalents of the required values under a new name:
let NEHotspotConfigurationErrorDomainWorkaround: String = {
… tricky code here …
}()
enum NEHotspotConfigurationErrorWorkaround: Int {
case alreadyAssociated = 13
}
Note It’s OK to hard code the 13 here because the error codes are coming from Objective-C, which means they can’t change (changing them would break Objective-C clients).
Now, implement the
case
clause as follows:
case (NEHotspotConfigurationErrorDomainWorkaround, NEHotspotConfigurationErrorWorkaround.alreadyAssociated.rawValue):
… your code here …
Then all you need to do is write the body of
NEHotspotConfigurationErrorDomainWorkaround
. Easy! Nah, not really. Here’s what I eventually come up with:
let NEHotspotConfigurationErrorDomainWorkaround: String = {
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
if let sym = dlsym(RTLD_DEFAULT, "_NEHotspotConfigurationErrorDomain") {
// If `NEHotspotConfigurationErrorDomain` is available, use its value.
return String(cString: sym.assumingMemoryBound(to: CChar.self))
} else {
// If not, meaning we’re on iOS 12 or earlier, use a hard-coded value
// that matches the value used on those systems.
return "NEHotspotConfigurationErrorDomain"
}
}()
Wow, that’s a whole barrel of un-fun.
WARNING I’ve tested bits of this code but haven’t done a full end-to-end test on iOS 12 and iOS 13. Let me know how it goes (-:
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"