在做流量精靈的時候有這樣一個需求,帳戶默認需要取手機的imsi 信息。這就有一個好處,即便用戶刪除我們的應用后從新下載,下次進入時他們還會以同樣的身份登陸,並且獲得原先紀錄。這樣不僅對於開發公司人員來說可以統計他是不是新用戶,而且對於用戶來說可以不用擔心之前記錄是否被刪除。(——我們的軟件是不需要注冊的,只要用戶登錄就默認以imsi 為唯一標示來登記的)。
但是在iOS開發中,發現不同的系統如 iOS5、iOS6.0、以及iOS7,蘋果對它處理的態度是完全不同的。估計蘋果是對系統安全的考慮,6.0之后你若想取這些私密信息是完全不可能的。所有的函數都已經被封鎖。 雖說作為一個開發來說很不願意看得此景,但另一方面作為一個喬布斯粉絲的我來說,完全可以理解蘋果的此舉。(反過來想一想,若你是一個用戶,而你手機中裝的每個軟件都可以在任意情況下獲取你的 私密信息如:imsi,imei,手機號碼或者你的地理位置信息。 那是多么可怕的一件事情。——喬布斯當初不想開放iOS開發給世界就是為了不讓其他人污染了他的商店,污染用戶,污染了系統)。
基於種種原因,我還是相對崇拜喬布斯的。
既然不能直接解決問題,那么我們就嘗試着解決吧:這里也嘗試過幾種吧
1、利用 NSUserDefaults 存取
- (NSString*)uniqueAppInstanceIdentifier
{
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
static NSString* UUID_KEY = @"MPUUID";
NSString* app_uuid = [userDefaults stringForKey:UUID_KEY];
if (app_uuid == nil) {
CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
app_uuid = [NSString stringWithString:(__bridge NSString*)uuidString];
[userDefaults setObject:app_uuid forKey:UUID_KEY];
[userDefaults synchronize];
CFRelease(uuidString);
CFRelease(uuidRef);
}
return app_uuid;
}
這種方法可以保證用戶不刪除軟件情況下的獲取同一個數據。因為NSUserDefaults 數據時保存在 沙盒里面的,會隨着軟件刪除而被清空。
2、利用 [[UIDevice currentDevice] identifierForVendor].UUIDString
此方法是官方6.0系統后推出的,指定唯一標示符號;不同軟件,不同機器,運行的時候指都是不一樣的;也就是說可以滿足標識唯一性,前一段時間我都是用該方法來獲取數據的。 但是有個讓人糾結的問題:
a、大部分正版的手機在軟件卸載了,然后重新安裝的情況下還是會保持和原先保存同一個值。
b、我一直以為這個方法沒問題的同時,在某一天,突然有個測試說:“我軟件卸載了,但是數據都清空了。。。。怎么回事啊。”,后來發現 you right。有些越獄或者美版的手機 在卸載后都會重現獲取數據。------我的天哪。。。。
最方便的方案,就那么被否決,還是有些失落!
也基於這些現在才有空重新來思考這個問題.... 設備唯一標示符,並且這個標示符在軟件卸載重裝之后能和原先保持一致.....
3、KeyChian 方案
這個方案我開發之間就一直知道,也給新中大弄個過,只是自己完全不想弄。理由很簡單,一個工具軟件這樣弄有什么意思呢?對於沒用的開發我向來都是很反感,很討厭的。 人們總想着完美的東西,卻壓根不知道自己所要的完美是什么東西,總是說以后會有用的,總以為這樣就會讓自己變得成為一個思考全面的人。 可是在我認為並非如此,大部分都這樣思考,都是由於本身思考的太少,將來太過於迷茫,而又保守於不想犯錯而已..........還記得剛畢業的時候那樣一句話:“做一個萬能的東西是萬萬不能的.....也不要整天為以后的因素來進行編碼。” 所以我的答案很簡單:你要清楚的知道你要什么,我也會給你清楚的答案。
言歸正轉:
KeyChian 是保存在沙盒之外的存儲數據,相當於Dictionary, 所有應用都可以獲取和保存,因此當一個軟件卸載之后完全不影響里面的數據,這樣當軟件重新安裝之后,理所當然的可以獲取里面的原數據。
這里我用的還是別人封裝過的一些代碼SFHFKeychainUtils(可以在網上任意下載):
//保存數據
BOOL s = [SFHFKeychainUtils storeUsername:name andPassword:pswd forServiceName:server updateExisting:NO error:nil];
//獲取密碼
NSString * psw = [SFHFKeychainUtils getPasswordForUsername:name andServiceName:server error:nil];
好吧,此方案完結。