在iOS中,使用Keychain可以把我們要存儲(chǔ)的數(shù)據(jù)以加密的形式存儲(chǔ)在獨(dú)立于App的位置。
通過(guò)當(dāng)前項(xiàng)目的Capabilities>Keychain Sharing>On開(kāi)啟Keychain后,會(huì)自動(dòng)生成一個(gè)對(duì)應(yīng)的Keychain Groups,以及一個(gè)entitlements文件,文件里會(huì)有一個(gè)Keychain Access Groups,這里存儲(chǔ)了所有想要共享部分Keychain數(shù)據(jù)的App對(duì)應(yīng)的keychain groups的ID,默認(rèn)第一項(xiàng)名為“(teamID)就是你開(kāi)發(fā)者賬號(hào)的teamID,xcode之前的版本也寫(xiě)做${AppIdentifierPrefix}。
那么怎么獲取這個(gè)teamID,從而避免硬編碼呢。示例代碼如下:
OC
/** 獲取TeamID,又名AppIdentifierPrefix */
+ (NSString *)teamID
{
NSDictionary *query = @{(id)kSecClass:(id)kSecClassGenericPassword,
(id)kSecAttrAccount:@"bundleSeedID",
(id)kSecAttrService:@"",
(id)kSecReturnAttributes:(id)kCFBooleanTrue
};
CFDictionaryRef result = nil;
OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&result);
if (status == errSecItemNotFound)
status = SecItemAdd((CFDictionaryRef)query, (CFTypeRef *)&result);
if (status != errSecSuccess)
return nil;
NSString *accessGroup = [(__bridge NSDictionary *)result objectForKey:(id)kSecAttrAccessGroup];
NSArray *components = [accessGroup componentsSeparatedByString:@"."];
NSString *teamID = [[components objectEnumerator] nextObject];
CFRelease(result);
return teamID;
}
Swift
func teamID() -> String {
let unknown = "unknown"
let query = NSDictionary(dictionaryLiteral:(kSecClass,kSecClassGenericPassword),
(kSecAttrAccount,"bundleSeedID"),
(kSecAttrService,""),
(kSecReturnAttributes,kCFBooleanTrue as Any)
)
var result:CFTypeRef?
var status = SecItemCopyMatching(query, &result)
if status == errSecItemNotFound{
status = SecItemAdd(query, &result)
}
if status != errSecSuccess{
return unknown
}
let accessGroup:String = result?.object(forKey: kSecAttrAccessGroup)! as! String
let components = accessGroup.components(separatedBy: ".")
let teamID = components.first!
return teamID
}
PS
Keychain 中默認(rèn)的accessGroup為:teamID.bundleID,例如:39E8LGDFGR.com.company.test