ios 以编程方式访问应用程序标识符前缀
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11726672/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Access App Identifier Prefix programmatically
提问by Jacob Jennings
How can I access the Bundle Seed ID/Team ID/App Identifier Prefix string programmatically? (These are all the same thing as far as I can tell).
如何以编程方式访问捆绑种子 ID/团队 ID/应用程序标识符前缀字符串?(据我所知,这些都是一样的)。
I am using the UICKeychainStore keychain wrapper to persist data across several applications. Each of these applications has a shared keychain access group in their entitlement plists, and share the same provisioning profile. By default, the keychain services use the first access group in the plist as the access group to save data to. This looks like "AS234SDG.com.myCompany.SpecificApp" when I debug UICKeychainStore. I would like to set the access group to "AS234SDG.com.myCompany.SharedStuff", but I can't seem to locate how to get the "AS234SDG" string of the access group programmatically, and would like to avoid hard-coding it if possible.
我正在使用 UICKeychainStore 钥匙串包装器在多个应用程序中保存数据。这些应用程序中的每一个在其权利 plist 中都有一个共享的钥匙串访问组,并共享相同的配置文件。默认情况下,钥匙串服务使用 plist 中的第一个访问组作为保存数据的访问组。当我调试 UICKeychainStore 时,它看起来像“AS234SDG.com.myCompany.SpecificApp”。我想将访问组设置为“AS234SDG.com.myCompany.SharedStuff”,但我似乎无法找到如何以编程方式获取访问组的“AS234SDG”字符串,并希望避免对其进行硬编码如果可能的话。
回答by Hiron
Info.plist can have your own information and if you write a value with $(AppIdentifierPrefix)
, it is replaced to the real app identifier prefix at building phase.
Info.plist 可以有你自己的信息,如果你用 写一个值$(AppIdentifierPrefix)
,它会在构建阶段替换为真正的应用程序标识符前缀。
So, try this:
所以,试试这个:
In your Info.plist, add an info about app identifier prefix.
在您的 Info.plist 中,添加有关应用标识符前缀的信息。
<key>AppIdentifierPrefix</key>
<string>$(AppIdentifierPrefix)</string>
You can then retrieve it programmatically with Objective-C:
然后,您可以使用 Objective-C 以编程方式检索它:
NSString *appIdentifierPrefix =
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"AppIdentifierPrefix"];
and with Swift:
和斯威夫特:
let appIdentifierPrefix =
Bundle.main.infoDictionary!["AppIdentifierPrefix"] as! String
Note that appIdentifierPrefix
ends with a period; e.g. AS234SDG.
请注意,appIdentifierPrefix
以句点结尾;例如AS234SDG.
回答by David H
You can programmatically retrieve the Bundle Seed ID by looking at the access group attribute (i.e. kSecAttrAccessGroup
) of an existing KeyChain item. In the code below, I look up for an existing KeyChain entry and create one if it doesn't not exist. Once I have a KeyChain entry, I extract the access group information from it and return the access group's first component separated by "." (period) as the Bundle Seed ID.
您可以通过查看kSecAttrAccessGroup
现有 KeyChain 项目的访问组属性(即)以编程方式检索 Bundle Seed ID 。在下面的代码中,我查找现有的 KeyChain 条目,如果它不存在则创建一个。获得 KeyChain 条目后,我会从中提取访问组信息并返回访问组的第一个组件,以“.”分隔。(句号)作为捆绑种子 ID。
+ (NSString *)bundleSeedID {
NSString *tempAccountName = @"bundleSeedID";
NSDictionary *query = @{
(__bridge NSString *)kSecClass : (__bridge NSString *)kSecClassGenericPassword,
(__bridge NSString *)kSecAttrAccount : tempAccountName,
(__bridge NSString *)kSecAttrService : @"",
(__bridge NSString *)kSecReturnAttributes: (__bridge NSNumber *)kCFBooleanTrue,
};
CFDictionaryRef result = nil;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
if (status == errSecItemNotFound)
status = SecItemAdd((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
if (status != errSecSuccess) {
return nil;
}
status = SecItemDelete((__bridge CFDictionaryRef)query); // remove temp item
NSDictionary *dict = (__bridge_transfer NSDictionary *)result;
NSString *accessGroup = dict[(__bridge NSString *)kSecAttrAccessGroup];
NSArray *components = [accessGroup componentsSeparatedByString:@"."];
NSString *bundleSeedID = [[components objectEnumerator] nextObject];
return bundleSeedID;
}
回答by Ronen Rabinovici
In swift3:(Based on @Hiron solution)
在 swift3 中:(基于@Hiron 解决方案)
Simply one line:
只需一行:
var appIdentifierPrefix = Bundle.main.infoDictionary!["AppIdentifierPrefix"] as! String
Given that in your Info.plist, add the following key-value property:
鉴于在您的 Info.plist 中,添加以下键值属性:
key: AppIdentifierPrefix
键:AppIdentifierPrefix
string-value: $(AppIdentifierPrefix)
字符串值:$(AppIdentifierPrefix)
回答by balkoth
Here is the Swift version of @David H answer:
这是@David H 答案的 Swift 版本:
static func bundleSeedID() -> String? {
let queryLoad: [String: AnyObject] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: "bundleSeedID" as AnyObject,
kSecAttrService as String: "" as AnyObject,
kSecReturnAttributes as String: kCFBooleanTrue
]
var result : AnyObject?
var status = withUnsafeMutablePointer(to: &result) {
SecItemCopyMatching(queryLoad as CFDictionary, UnsafeMutablePointer(##代码##))
}
if status == errSecItemNotFound {
status = withUnsafeMutablePointer(to: &result) {
SecItemAdd(queryLoad as CFDictionary, UnsafeMutablePointer(##代码##))
}
}
if status == noErr {
if let resultDict = result as? [String: Any], let accessGroup = resultDict[kSecAttrAccessGroup as String] as? String {
let components = accessGroup.components(separatedBy: ".")
return components.first
}else {
return nil
}
} else {
print("Error getting bundleSeedID to Keychain")
return nil
}
}
回答by Aurelien Porte
This is a good question but to achieve what you were intended to do, there could have been a solution that does not require to retrieve the Bundle Seed ID.
这是一个很好的问题,但要实现您的意图,可能有一个不需要检索捆绑种子 ID 的解决方案。
From this article, about the same keychain wrapper you're using:
在这篇文章中,关于您正在使用的相同钥匙串包装器:
By default it will pick the first access-group specified in your Entitlements.plist when writing and will search across all access-groups when none is specified.
默认情况下,它会在写入时选择您的 Entitlements.plist 中指定的第一个访问组,并在没有指定时搜索所有访问组。
The key will then be search in all groups where access is granted. So to solve your problem, you could add access group of all your bundle apps into your entitlements.plist instead of using a "shared stuff" group, put $(CFBundleIdentifier) as your first keychain group (your keychain wrapper will then write in this group) and you're all set
然后将在所有授予访问权限的组中搜索该密钥。因此,为了解决您的问题,您可以将所有捆绑应用程序的访问组添加到您的 entitlements.plist 中,而不是使用“共享内容”组,将 $(CFBundleIdentifier) 作为您的第一个钥匙串组(然后您的钥匙串包装器将写入此组),你都准备好了