iOS - UIDevice

前言

NS_CLASS_AVAILABLE_IOS(2_0) @interface UIDevice : NSObject 
    @available(iOS 2.0, *)       public class UIDevice : NSObject
  • iOS 的 APP 應用開發的過程當中,有時爲了 bug 跟蹤或者獲取用反饋的須要自動收集用戶設備、系統信息、應用信息等等,這些信息方便開發者診斷問題,固然這些信息是用戶的非隱私信息,是經過開發 api 能夠獲取到的。那麼經過那些 api 能夠獲取這些信息呢,iOS 的 SDK 中提供了 UIDevice,NSBundle,NSLocale。html

  • UIDevice 提供了多種屬性、類函數及狀態通知,幫助咱們全方位瞭解設備情況。從檢測電池電量到定位設備與臨近感應,UIDevice 所作的工做就是爲應用程序提供用戶及設備的一些信息。UIDevice 類還可以收集關於設備的各類具體細節,例如機型及 iOS 版本等。其中大部分屬性都對開發工做具備積極的輔助做用。ios

  • bundle 是一個目錄,其中包含了程序會使用到的資源。這些資源包含了如圖像、聲音、編譯好的代碼、nib 文件(用戶也會把 bundle 稱爲 plug-in),對應 bundle,cocoa 提供了類 NSBundle。一個應用程序看上去和其餘文件沒有什麼區別. 可是實際上它是一個包含了 nib 文件,編譯代碼,以及其餘資源的目錄。咱們把這個目錄叫作程序的 main bundle。經過這個路徑能夠獲取到應用的信息,例如應用名、版本號等。git

  • NSLocale 能夠獲取用戶的本地化信息設置,例如貨幣類型,國家,語言,數字,日期格式的格式化,提供正確的地理位置顯示等等。下面的代碼獲取機器當前語言和國家代碼。github

一、設備相關信息的獲取

  • Objective-Capi

    • 設備基本信息安全

      // 獲取當前設備
          UIDevice *device = [UIDevice currentDevice];
      
          // 獲取設備名稱
          /*
              e.g. "My iPhone"
          */
          NSString *name = device.name;
      
          // 獲取設備類型
          /*
              e.g. @"iPhone", @"iPod touch"
          */
          NSString *model = device.model;
      
          // 獲取本地化設備類型
          /*
              localized version of model
          */
          NSString *localizedModel = device.localizedModel;
      
          // 獲取設備系統名稱
          /*
              e.g. @"iOS"
          */
          NSString *systemName = device.systemName;
      
          // 獲取設備系統版本
          /*
              e.g. @"4.0"
          */
          NSString *systemVersion = device.systemVersion;
      
          // 獲取設備 UUID
          /*
              可用於惟一標識該設備,同一供應商不一樣應用具備相同的 UUID
          */
          NSUUID *identifierForVendor = device.identifierForVendor;
          NSString *UUID = identifierForVendor.UUIDString;
    • 設備方向網絡

      // 判斷設備是否生成設備轉向通知
          BOOL generatesDeviceOrientationNotifications = device.isGeneratingDeviceOrientationNotifications;
      
          // 開啓設備轉向通知
          /*
              經過調用該方法通知設備:若是用戶改變了設備的朝向,咱們想獲悉這一點
              在註冊設備方向通知時,須要先調用該方法
          */
          [device beginGeneratingDeviceOrientationNotifications];
      
          // 中止設備轉向通知
          /*
              在移除設備方向通知後,須要調用該方法
          */
          [device endGeneratingDeviceOrientationNotifications];
      
          // 註冊屏幕方向變化通知
          [[NSNotificationCenter defaultCenter] addObserver:self 
                                                   selector:@selector(deviceOrientationDidChange) 
                                                       name:@"UIDeviceOrientationDidChangeNotification"
                                                     object:nil];
      
          // 獲取設備方向
          /*
              UIDeviceOrientationUnknown,
              UIDeviceOrientationPortrait,            // home button on the bottom    豎向,頭向上
              UIDeviceOrientationPortraitUpsideDown,  // home button on the top       豎向,頭向下
              UIDeviceOrientationLandscapeLeft,       // home button on the right     橫向,頭向左
              UIDeviceOrientationLandscapeRight,      // home button on the left      橫向,頭向右
              UIDeviceOrientationFaceUp,              // face up                      平放,屏幕朝上
              UIDeviceOrientationFaceDown             // face down                    平放,屏幕朝下
      
              除非正在生成設備方向的通知,不然返回 UIDeviceOrientationUnknown
          */
          UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
    • 設備電池監控app

      // 判斷設備是否開啓電池監控
          /*
              default is NO
          */
          BOOL batteryMonitoringEnabled = device.isBatteryMonitoringEnabled;
      
          // 開啓電池監控
          /*
              default is NO
          */
          device.batteryMonitoringEnabled = YES;
      
          // 獲取設備電池狀態
          /*
              UIDeviceBatteryStateUnknown,
              UIDeviceBatteryStateUnplugged,   // on battery, discharging      未充電
              UIDeviceBatteryStateCharging,    // plugged in, less than 100%   正在充電
              UIDeviceBatteryStateFull,        // plugged in, at 100%          滿電
      
              若是禁用電池監控,則電池狀態爲 UIDeviceBatteryStateUnknown
          */
          UIDeviceBatteryState batteryState = device.batteryState;
      
          // 註冊電池狀態變化通知
          [[NSNotificationCenter defaultCenter] addObserver:self 
                                                   selector:@selector(deviceBatteryStateDidChange) 
                                                       name:@"UIDeviceBatteryStateDidChangeNotification" 
                                                     object:nil];
      
          // 獲取電池電量
          /*
              0 .. 1.0. 若是電池狀態爲 UIDeviceBatteryStateUnknown,百分比爲 -1.0
          */
          float batteryLevel = device.batteryLevel;
      
          // 註冊電池電量變化通知
          [[NSNotificationCenter defaultCenter] addObserver:self 
                                                   selector:@selector(deviceBatteryLevelDidChange) 
                                                       name:@"UIDeviceBatteryLevelDidChangeNotification" 
                                                     object:nil];
    • 設備接近狀態監控框架

      // 判斷設備是否開啓接近狀態監控
          /*
              default is NO
          */
          BOOL proximityMonitoringEnabled = device.isProximityMonitoringEnabled;
      
          // 開啓接近狀態監控
          /*
              default is NO
          */
          device.proximityMonitoringEnabled = YES;
      
          // 獲取接近狀態
          /*
              若是設備不具有接近感應器,則老是返回 NO
          */
          BOOL proximityState = device.proximityState;
      
          // 註冊接近狀態變化通知
      
          [[NSNotificationCenter defaultCenter] addObserver:self 
                                                   selector:@selector(deviceProximityStateDidChange) 
                                                       name:@"UIDeviceProximityStateDidChangeNotification" 
                                                     object:nil];
    • 設備性能less

      // 判斷設備是否支持多任務
          BOOL multitaskingSupported = device.multitaskingSupported;
    • 設備操做

      // 獲取用戶界面模式
          /*
              UIUserInterfaceIdiomUnspecified = -1,
              UIUserInterfaceIdiomPhone   // iPhone and iPod touch style UI    iPhone 和 iPod touch 風格
              UIUserInterfaceIdiomPad     // iPad style UI                     iPad 風格
              UIUserInterfaceIdiomTV      // Apple TV style UI                 Apple TV 風格
              UIUserInterfaceIdiomCarPlay // CarPlay style UI                  CarPlay 風格
          */
          UIUserInterfaceIdiom userInterfaceIdiom = device.userInterfaceIdiom;
      
          // 播放一個輸入的聲音
          [device playInputClick];
      
          // UIInputViewAudioFeedback 協議方法
          /*
              實現該方法,返回 YES 則自定義的視圖可以播放輸入的聲音
          */
          - (BOOL)enableInputClicksWhenVisible {
      
              return YES;
          }
  • Swift

    • 設備基本信息

      // 獲取當前設備
          let device:UIDevice = UIDevice.currentDevice()
      
          // 獲取設備名稱
          /*
              e.g. "My iPhone"
          */
          let name:String = device.name
      
          // 獲取設備類型
          /*
              e.g. @"iPhone", @"iPod touch"
          */
          let model:String = device.model
      
          // 獲取本地化設備類型
          /*
              localized version of model
          */
          let localizedModel:String = device.localizedModel
      
          // 獲取設備系統名稱
          /*
              e.g. @"iOS"
          */
          let systemName:String = device.systemName
      
          // 獲取設備系統版本
          /*
              e.g. @"4.0"
          */
          let systemVersion:String = device.systemVersion
      
          // 獲取設備 UUID
          /*
              可用於惟一標識該設備,同一供應商不一樣應用具備相同的 UUID
          */
          let identifierForVendor:NSUUID = device.identifierForVendor!
          let UUID:String = identifierForVendor.UUIDString
    • 設備方向

      // 判斷設備是否生成設備轉向通知
          let generatesDeviceOrientationNotifications:Bool = device.generatesDeviceOrientationNotifications
      
          // 開啓設備轉向通知                                     /*
              經過調用該方法通知設備:若是用戶改變了設備的朝向,咱們想獲悉這一點
              在註冊設備方向通知時,須要先調用該方法
          */
          device.beginGeneratingDeviceOrientationNotifications()
      
          // 中止設備轉向通知
          /*
              在移除設備方向通知後,須要調用該方法
          */
          device.endGeneratingDeviceOrientationNotifications()
      
          // 註冊屏幕方向變化通知
          NSNotificationCenter.defaultCenter().addObserver(self, 
                                                  selector: #selector(UiDevice.deviceOrientationDidChange), 
                                                      name: UIDeviceOrientationDidChangeNotification, 
                                                    object: nil)
      
          // 獲取設備方向
          /*
              UIDeviceOrientationUnknown,
              UIDeviceOrientationPortrait,            // home button on the bottom   豎向,頭向上
              UIDeviceOrientationPortraitUpsideDown,  // home button on the top      豎向,頭向下
              UIDeviceOrientationLandscapeLeft,       // home button on the right    橫向,頭向左
              UIDeviceOrientationLandscapeRight,      // home button on the left     橫向,頭向右
              UIDeviceOrientationFaceUp,              // face up    平放,屏幕朝上
              UIDeviceOrientationFaceDown             // face down  平放,屏幕朝下
      
              除非正在生成設備方向的通知,不然返回 UIDeviceOrientationUnknown
          */
          let orientation:UIDeviceOrientation = UIDevice.currentDevice().orientation
    • 設備電池監控

      // 判斷設備是否開啓電池監控
          /*
              default is NO
          */
          let batteryMonitoringEnabled:Bool = device.batteryMonitoringEnabled
      
          // 開啓電池監控
          /*
              default is NO
          */
          device.batteryMonitoringEnabled = true
      
          // 獲取設備電池狀態
          /*
              UIDeviceBatteryStateUnknown,
              UIDeviceBatteryStateUnplugged,  // on battery, discharging      未充電
              UIDeviceBatteryStateCharging,   // plugged in, less than 100%   正在充電
              UIDeviceBatteryStateFull,       // plugged in, at 100%          滿電
      
              若是禁用電池監控,則電池狀態爲 UIDeviceBatteryStateUnknown
          */
          let batteryState:UIDeviceBatteryState = device.batteryState
      
          // 註冊電池狀態變化通知
          NSNotificationCenter.defaultCenter().addObserver(self, 
                                                  selector: #selector(UiDevice.deviceBatteryStateDidChange), 
                                                      name: UIDeviceBatteryStateDidChangeNotification, 
                                                    object: nil)
      
          // 獲取電池電量
          /*
              0 .. 1.0. 若是電池狀態爲 UIDeviceBatteryStateUnknown,百分比爲 -1.0
          */
          let batteryLevel:Float = device.batteryLevel
      
          // 註冊電池電量變化通知
          NSNotificationCenter.defaultCenter().addObserver(self, 
                                                  selector: #selector(UiDevice.deviceBatteryLevelDidChange), 
                                                      name: UIDeviceBatteryLevelDidChangeNotification, 
                                                    object: nil)
    • 設備接近狀態監控

      // 判斷設備是否開啓接近狀態監控
          /*
              default is NO
          */
          let proximityMonitoringEnabled:Bool = device.proximityMonitoringEnabled
      
          // 開啓接近狀態監控
          /*
              default is NO
          */
          device.proximityMonitoringEnabled = true
      
          // 獲取接近狀態
          /*
              若是設備不具有接近感應器,則老是返回 NO
          */
          let proximityState:Bool = device.proximityState
      
          // 註冊接近狀態變化通知
          NSNotificationCenter.defaultCenter().addObserver(self, 
                                                  selector: #selector(UiDevice.deviceProximityStateDidChange), 
                                                      name: UIDeviceProximityStateDidChangeNotification, 
                                                    object: nil)
    • 設備性能

      // 判斷設備是否支持多任務
          let multitaskingSupported:Bool = device.multitaskingSupported
    • 設備操做

      // 獲取用戶界面模式
          /*
              UIUserInterfaceIdiomUnspecified = -1,
              UIUserInterfaceIdiomPhone     // iPhone and iPod touch style UI   iPhone 和 iPod touch 風格
              UIUserInterfaceIdiomPad       // iPad style UI                    iPad 風格
              UIUserInterfaceIdiomTV        // Apple TV style UI                Apple TV 風格
              UIUserInterfaceIdiomCarPlay   // CarPlay style UI                 CarPlay 風格
          */
          let userInterfaceIdiom:UIUserInterfaceIdiom = device.userInterfaceIdiom
      
          // 播放一個輸入的聲音
          device.playInputClick()

二、App 應用相關信息的獲取

  • NSBundle

  • Objective-C

    NSDictionary *dicInfo = [[NSBundle mainBundle] infoDictionary];
        CFShow((__bridge CFTypeRef)(dicInfo));
    
        // App 應用名稱
        NSString *appName = [dicInfo objectForKey:@"CFBundleName"];
    
        // App 應用版本
        NSString *appVersion = [dicInfo objectForKey:@"CFBundleShortVersionString"];
    
        // App 應用 Build 版本
        NSString *appBuild = [dicInfo objectForKey:@"CFBundleVersion"];
  • Swift

    let dicInfo:[String : AnyObject]? = NSBundle.mainBundle().infoDictionary
        CFShow(dicInfo)
    
        // App 應用名稱
        let appName = dicInfo!["CFBundleName"]
    
        // App 應用版本
        let appVersion = dicInfo!["CFBundleShortVersionString"]
    
        // App 應用 Build 版本
        let appBuild = dicInfo!["CFBundleVersion"]

三、用戶的本地化信息的獲取

  • NSLocale

  • Objective-C

    // 語言 en
        NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0];
    
        // 國家 en_US
        NSString *country = [[NSLocale currentLocale] localeIdentifier];
  • Swift

    // 語言 en
        let language:String = NSLocale.preferredLanguages()[0]
    
        // 國家 en_US
        let country:String = NSLocale.currentLocale().localeIdentifier

四、獲取設備惟一標識

  • iOS系統中,獲取設備惟一標識的方法有不少:

    • 一、UDID:UDID 的全稱是 Unique Device Identifier Description,顧名思義,它就是蘋果 iOS 設備的惟一識別碼。
      • UDID 是由子母和數字組成的 40 個字符串的序號,用來區別每個惟一的 iOS 設備,包括 iPhones, iPads, 以及 iPod touches,這些編碼看起來是隨機的,其實是跟硬件設備特色相聯繫的。
      • UDID 能夠關聯其它各類數據到相關設備上。例如,鏈接到開發者帳號,能夠容許在發佈前讓設備安裝或測試應用;也可讓開發者得到 iOS 測試版進行體驗。蘋果用 UDID 鏈接到蘋果的 ID,這些設備能夠自動下載和安裝從 App Store 購買的應用、保存從 iTunes 購買的音樂、幫助蘋果發送推送通知、即時消息。 在 iOS 應用早期,UDID 被第三方應用開發者和網絡廣告商用來收集用戶數據,能夠用來關聯地址、記錄應用使用習慣,以便推送精準廣告。
    • 二、OPEN UDID
      • iOS 2.0 版本之後 UIDevice 提供一個獲取設備惟一標識符的方法 uniqueIdentifier,經過該方法咱們能夠獲取設備的序列號,這個也是目前爲止惟一能夠確認惟一的標示符。許多開發者把 UDID 跟用戶的真實姓名、密碼、住址、其它數據關聯起來;網絡窺探者會從多個應用收集這些數據,而後順藤摸瓜獲得這我的的許多隱私數據。同時大部分應用確實在頻繁傳輸 UDID 和私人信息。 爲了不集體訴訟,蘋果最終決定在 iOS 5 的時候,將這一慣例廢除,開發者被引導生成一個惟一的標識符,只能檢測應用程序,其餘的信息不提供。如今應用試圖獲取 UDID 已被禁止且不容許上架。因此這個方法做廢。
    • 三、UUID:UUID 是 Universally Unique Identifier 的縮寫,中文意思是通用惟一識別碼.
      • 咱們能夠獲取到 UUID,而後把 UUID 保存到 KeyChain 裏面。這樣之後即便 App 刪了再裝回來,也能夠從 KeyChain 中讀取回來。使用 group 還能夠能夠保證同一個開發商的全部程序針對同一臺設備可以獲取到相同的不變的 UDID。可是刷機或重裝系統後 UDID 仍是會改變。
    • 四、MAC Address
      • 使用 WiFi 的 mac 地址來取代已經廢棄了的 uniqueIdentifier 方法。
      • 然而在 iOS 7 中蘋果再一次無情的封殺 mac 地址,使用以前的方法獲取到的 mac 地址所有都變成了 02:00:00:00:00:00。
    • 五、IDFA:廣告標示符(IDFA-identifierForIdentifier),iOS6.0 及之後
      • 全名 advertisingIdentifier。直譯就是廣告 id, 在同一個設備上的全部 App 都會取到相同的值,是蘋果專門給各廣告提供商用來追蹤用戶而設的,用戶能夠在 設置|隱私|廣告追蹤 裏重置此id的值,或限制此 id 的使用,故此 id 有可能會取不到值,但好在 Apple 默認是容許追蹤的,並且通常用戶都不知道有這麼個設置,因此基本上用來監測推廣效果,是戳戳有餘了。因爲 IDFA 會出現取不到的狀況,故毫不能夠做爲業務分析的主 id,來識別用戶。
      • 獲取代碼:

        #import <AdSupport/AdSupport.h>
            NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
      • 從 17 年 2 月初開始,Apple 開始拒絕採集 IDFA(identifier for advertising)而未集成任何廣告服務的應用進入 AppStore。

    • 六、IDFV:應用提供商標示符(IDFV-identifierForVendor),iOS6.0 及之後
      • 全名 identifierForVendor。顧名思義,是給 Vendor 標識用戶用的,每一個設備在所屬同一個 Vender 的應用裏,都有相同的值。其中的 Vender 是指應用提供商,但準確點說,是經過 BundleID 的反轉的前兩部分進行匹配,若是相同就是同一個 Vender,例如對於 com.taobao.app1, com.taobao.app2 這兩個 BundleID 來講,就屬於同一個 Vender,共享同一個 idfv 的值。和 IDFA 不一樣的是,IDFV 的值是必定能取到的,因此很是適合於做爲內部用戶行爲分析的主 id,來標識用戶,替代 OpenUDID。若是用戶將屬於此 Vender 的全部 App 卸載,則 IDFV 的值會被重置,即再重裝此 Vender 的 App,IDFV 的值和以前不一樣。
      • 獲取代碼:

        NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
  • 上面全部這些表示設備惟一的標識,在 iOS 7 中要麼被禁止使用,要麼從新安裝程序後兩次獲取的標識符不同。因爲 iOS 系統存儲的數據都是在 sandBox 裏面,一旦刪除 App,sandBox 也不復存在。

  • iOS 中獲取設備惟一標示符的方法一直隨版本的更新而變化。iOS 2.0 版本之後 UIDevice 提供一個獲取設備惟一標識符的方法 uniqueIdentifier,經過該方法咱們能夠獲取設備的序列號,這個也是目前爲止惟一能夠確認惟一的標示符。好景不長,由於該惟一標識符與手機一一對應,蘋果以爲可能會泄露用戶隱私,因此在 iOS 5.0 以後該方法就被廢棄掉了;iOS 6.0 系統新增了兩個用於替換 uniqueIdentifier 的接口,分別是:identifierForVendor,advertisingIdentifier,但這兩個接口會在應用從新安裝時改變數值,並非惟一的標示符,因此開發者改成使用 WiFi 的 mac 地址來取代;iOS 7 中蘋果又封殺 mac 地址,因此開發者再次改變思路使用 KeyChain 來保存獲取到的 UDID,這樣之後即便 App 刪了再裝回來,也能夠從 KeyChain 中讀取回來。

  • 首先保存設備的 UUID,可使用類方法 + (id)UUID 是一個類方法,調用該方法能夠得到一個 UUID。經過下面的代碼能夠得到一個 UUID 字符串:

    NSString *uuid = [[NSUUID UUID] UUIDString];
  • 也能夠保存在 iOS 6 中新增的 Vindor 標示符 (IDFV-identifierForVendor),獲取這個 IDFV 的新方法被添加在已有的 UIDevice 類中。跟 advertisingIdentifier 同樣,該方法返回的是一個 NSUUID 對象。

    NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
  • 若是用戶卸載了同一個 vendor 對應的全部程序,而後在從新安裝同一個 vendor 提供的程序,此時 identifierForVendor 會被重置,因此這裏要用到 KeyChain 來保存。KeyChain(鑰匙串)是使用蘋果設備常用的,一般要調試的話,都得安裝證書之類的,這些證書就是保存在 KeyChain 中,還有咱們平時瀏覽網頁記錄的帳號密碼也都是記錄在 KeyChain 中。iOS 中的 KeyChain 相比 OS X 比較簡單,整個系統只有一個 KeyChain,每一個程序均可以往 KeyChain 中記錄數據,並且只能讀取到本身程序記錄在 KeyChain 中的數據。iOS 中 Security.framework 框架提供了四個主要的方法來操做 KeyChain:

    // 查詢 OSStatus
        SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result);
    
        // 添加 OSStatus
        SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result); 
    
        // 更新 KeyChain 中的 ItemOSStatus
        SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate);
    
        // 刪除 KeyChain 中的 ItemOSStatus
        SecItemDelete(CFDictionaryRef query)
  • 這四個方法參數比較複雜,一旦傳錯就會致使操做 KeyChain 失敗,文檔中介紹的比較詳細,你們能夠查查官方文檔。而蘋果提供的 KeyChain 使用起來略麻煩,因此這裏推薦一個第三方庫 SSKeychain/SAMKeychain 對蘋果安全框架 API 進行了簡單封裝,支持對存儲在鑰匙串中密碼、帳戶進行訪問,包括讀取、刪除和設置。SSKeyChains 使用簡單,經過實例代碼即可掌握。

    // 保存一個 UUID 字符串到鑰匙串:
        CFUUIDRef uuid = CFUUIDCreate(NULL);
        assert(uuid != NULL);
        CFStringRef uuidStr = CFUUIDCreateString(NULL, uuid);
    
        [SSKeychain setPassword:[NSString stringWithFormat:@"%@", uuidStr] forService:@"com.yourapp.yourcompany"account:@"user"];
    
        // 從鑰匙串讀取 UUID:
        NSString *retrieveuuid = [SSKeychainpasswordForService:@"com.yourapp.yourcompany"account:@"user"];
    
        // 注意: setPassword 和 passwordForSevice 方法中的 services 和 accounts 參數應該是一致的。
  • 基本的實現思路即是這樣,下面是具體的一種具體實現代碼,僅供參考。

    + (NSString *)getDeviceId {
    
            NSString *currentDeviceUUIDStr = [SSKeychain passwordForService:[NSBundle mainBundle].bundleIdentifier account:@"uuid"];
    
            if (currentDeviceUUIDStr == nil || [currentDeviceUUIDStr isEqualToString:@""]) {
    
                NSUUID *currentDeviceUUID  = [UIDevice currentDevice].identifierForVendor;
                currentDeviceUUIDStr = currentDeviceUUID.UUIDString;
                currentDeviceUUIDStr = [currentDeviceUUIDStr stringByReplacingOccurrencesOfString:@"-" withString:@""];
                currentDeviceUUIDStr = [currentDeviceUUIDStr lowercaseString];
                [SSKeychain setPassword: currentDeviceUUIDStr forService:[NSBundle mainBundle].bundleIdentifier account:@"uuid"];
            }
            return currentDeviceUUIDStr;
        }
相關文章
相關標籤/搜索