Evgeniy Kleban
Evgeniy Kleban

Reputation: 6940

Crash while trying to get UIDevice.current.identifierForVendor?.uuidString

I have crash while trying to do:

static func getDeviceUUID() -> String {
        guard let uuid = UIDevice.current.identifierForVendor?.uuidString else {
            assertionFailure("Nil while unwrapping UIDevice.current.identifierForVendor?.uuidString")
            return ""}
            return uuid
    }

Error says: Thread 9: Fatal error: Nil while unwrapping UIDevice.current.identifierForVendor?.uuidString

But when i try to log it out in console it says:

 po UIDevice.current.identifierForVendor?.uuidString
▿ Optional<String>
  - some : "39DEFA50-D6A1-4788-BCCC-5E2A28A04C57"

So, it actually have value. Why crash is happening?

Upvotes: 1

Views: 1525

Answers (3)

yonivav
yonivav

Reputation: 1033

Maybe because you didn't check if user permit ti check it.

guard ASIdentifierManager.shared().isAdvertisingTrackingEnabled else {
    return nil
}          
return ASIdentifierManager.shared().advertisingIdentifier.uuidString

BTW, for iOS14+ you should check it differently:

import AdSupport
import AppTrackingTransparency

extension ASIdentifierManager {
    //NOTE: if the user has enabled Limit Ad Tracking, this IDFA will be all zeros on a physical device
    static var identifierForAdvertising: String {
        if #available(iOS 14, *) {
            guard ATTrackingManager.trackingAuthorizationStatus == .authorized else {
                return ""
            }
        } else {
            guard ASIdentifierManager.shared().isAdvertisingTrackingEnabled else {
                return ""
            }
        }
        return ASIdentifierManager.shared().advertisingIdentifier.uuidString
    }
}

Upvotes: 0

Patrick O&#39;Leary
Patrick O&#39;Leary

Reputation: 11

I've had a similar problem occur when trying to grab the IDFA from the AdSupport framework:

ASIdentifierManager.shared().advertisingIdentifier.uuidString
// causes exception

In this case, it seems as though the Objective-C code base has an incorrectly marked 'nonnull' method, which can't be worked around because the uuidString method for the UUID class returns a value type (String), whereas in Obj-C it would return a reference type (NSString): https://forums.swift.org/t/is-it-safe-to-cast-a-nonnull-objc-type-to-a-swift-optional/10658

Since these both make use of the UUID class, my guess is that it's the same problem.

The workaround that the above link suggests is to build an Obj-C wrapper for accessing the UUID:

+ (nullable NSString*)getUUIDFromDevice {
    NSString *uuid = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    if (uuid) {
        return uuid;
    } else {
        return nil;
    }
}

Unfortunately this is difficult to test, because it's unclear when exactly the UUID value would ever be nil.

Upvotes: 1

Kamlesh Shingarakhiya
Kamlesh Shingarakhiya

Reputation: 2777

It's working fine

func getDeviceUUID() -> String {
        guard let uuid = UIDevice.current.identifierForVendor?.uuidString else {
            assertionFailure("Nil while unwrapping UIDevice.current.identifierForVendor?.uuidString")
            return ""}
        return uuid
    }

print(getDeviceUUID()) //50E6548C-0BB4-4979-8F5F-DFAD422BEB26

Upvotes: 2

Related Questions