iOS企业应用:如何在Swift中编程获取IMEI、序列号及UUID?
Hey there! Since you're building an enterprise iOS app that won't hit the App Store, you’ve got more flexibility than standard App Store apps. Let’s break down how to get each piece of device info you need, including workarounds for IMEI and serial number (since Apple blocks those via public APIs):
For UUID, you have two solid options depending on your needs:
Persistent UUID (survives app uninstalls): Generate a custom UUID once and store it in the Keychain (so it stays even if the user deletes and reinstalls your app). Here’s a quick implementation:
import Security func getPersistentDeviceUUID() -> String? { let service = "com.yourcompany.yourapp.device-uuid" let account = "unique-device-id" // Check if UUID already exists in Keychain let query: [CFString: Any] = [ kSecClass: kSecClassGenericPassword, kSecAttrService: service, kSecAttrAccount: account, kSecReturnData: kCFBooleanTrue!, kSecMatchLimit: kSecMatchLimitOne ] var result: AnyObject? let status = SecItemCopyMatching(query as CFDictionary, &result) if status == errSecSuccess, let data = result as? Data, let uuid = String(data: data, encoding: .utf8) { return uuid } else if status == errSecItemNotFound { // Generate and store new UUID let newUUID = UUID().uuidString guard let data = newUUID.data(using: .utf8) else { return nil } let addQuery: [CFString: Any] = [ kSecClass: kSecClassGenericPassword, kSecAttrService: service, kSecAttrAccount: account, kSecValueData: data ] let addStatus = SecItemAdd(addQuery as CFDictionary, nil) return addStatus == errSecSuccess ? newUUID : nil } return nil }Vendor-specific UUID: If you don’t need persistence across uninstalls, use Apple’s built-in identifier:
let vendorUUID = UIDevice.current.identifierForVendor?.uuidStringNote: This resets if the user deletes all apps from your developer account.
Apple strictly blocks access to IMEI and serial number via public APIs for privacy reasons, but enterprise apps can use private APIs (just be aware these can break with iOS updates, since Apple doesn’t support them).
Getting the Serial Number
You can call a private method on UIDevice to fetch the serial number:
import UIKit extension UIDevice { var serialNumber: String? { let serialSelector = NSSelectorFromString("serialNumber") guard responds(to: serialSelector) else { return nil } return perform(serialSelector)?.takeUnretainedValue() as? String } } // Usage if let serial = UIDevice.current.serialNumber { print("Device Serial: \(serial)") }
Getting the IMEI
IMEI is tied to cellular hardware, so this only works on iPhones (Wi-Fi-only iPads won’t have an IMEI). Use a private CoreTelephony API:
import CoreTelephony extension CTTelephonyNetworkInfo { var imei: String? { let imeiSelector = NSSelectorFromString("IMEI") guard responds(to: imeiSelector) else { return nil } return perform(imeiSelector)?.takeUnretainedValue() as? String } } // Usage let networkInfo = CTTelephonyNetworkInfo() if let imei = networkInfo.imei { print("Device IMEI: \(imei)") }
There are open-source frameworks that wrap these private APIs to simplify access, but keep in mind they may not be maintained across iOS versions. Some options include:
- DeviceKit: While it primarily uses public APIs, some forks add private method support for serial number/IMEI (check the repo’s issues for enterprise-specific builds).
- Custom Wrappers: Most frameworks just do what the code above does—call private selectors—so rolling your own implementation gives you more control over updates and stability.
A quick note: Even for enterprise apps, make sure you’re complying with local privacy laws (like GDPR or CCPA) when collecting device identifiers—always get user consent if required.
内容的提问来源于stack exchange,提问作者Viral Mithani

