Acceda al Prefijo de Identificador de la Aplicación programáticamente

¿Cómo puedo acceder a la cadena de prefijo Bundle ID / Team ID / App Prefix mediante progtwigción? (Estas son todas las mismas cosas que puedo decir).

Estoy usando la envoltura de llavero UICKeychainStore para conservar los datos en varias aplicaciones. Cada una de estas aplicaciones tiene un grupo de acceso de llavero compartido en sus listas de derechos, y comparten el mismo perfil de aprovisionamiento. De forma predeterminada, los servicios de llavero usan el primer grupo de acceso en el plist como el grupo de acceso para guardar datos. Esto se ve como “AS234SDG.com.myCompany.SpecificApp” cuando depuro UICKeychainStore. Me gustaría establecer el grupo de acceso a “AS234SDG.com.myCompany.SharedStuff”, pero parece que no puedo localizar cómo obtener la cadena “AS234SDG” del grupo de acceso mediante progtwigción, y me gustaría evitar la encoding rígida. si es posible.

Puede recuperar programáticamente la ID de semilla Bundle mirando el atributo de grupo de acceso (es decir, kSecAttrAccessGroup ) de un elemento KeyChain existente. En el siguiente código, busco una entrada KeyChain existente y creo una si no existe. Una vez que tengo una entrada KeyChain, extraigo la información del grupo de acceso y regreso el primer componente del grupo de acceso separado por “.” (punto) como la identificación de la semilla Bundle.

 + (NSString *)bundleSeedID { NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys: (__bridge NSString *)kSecClassGenericPassword, (__bridge NSString *)kSecClass, @"bundleSeedID", kSecAttrAccount, @"", kSecAttrService, (id)kCFBooleanTrue, kSecReturnAttributes, nil]; 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; NSString *accessGroup = [(__bridge NSDictionary *)result objectForKey:(__bridge NSString *)kSecAttrAccessGroup]; NSArray *components = [accessGroup componentsSeparatedByString:@"."]; NSString *bundleSeedID = [[components objectEnumerator] nextObject]; CFRelease(result); return bundleSeedID; } 

Info.plist puede tener su propia información y si escribe un valor con $(AppIdentifierPrefix) , se reemplaza por el prefijo del identificador de aplicación real en la fase de construcción.

Por lo tanto, intente esto:

En su Info.plist, agregue una información sobre el prefijo del identificador de la aplicación.

 AppIdentifierPrefix $(AppIdentifierPrefix) 

A continuación, puede recuperarlo programáticamente con Objective-C:

 NSString *appIdentifierPrefix = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"AppIdentifierPrefix"]; 

y con Swift:

 let appIdentifierPrefix = Bundle.main.infoDictionary!["AppIdentifierPrefix"] as! String 

Tenga en cuenta que appIdentifierPrefix termina con un punto; por ejemplo, AS234SDG.

En swift3: (Basado en la solución @Hiron)

Simplemente una línea:

 var appIdentifierPrefix = Bundle.main.infoDictionary!["AppIdentifierPrefix"] as! String 

Dado que en su Info.plist, agregue la siguiente propiedad clave-valor:

clave: AppIdentifierPrefix

string-value: $ (AppIdentifierPrefix)

Esta es una buena pregunta, pero para lograr lo que se pretendía que hiciera, podría haber una solución que no requiera recuperar la ID de Bundle Seed.

De este artículo , acerca de la misma envoltura de llavero que estás usando:

De forma predeterminada, seleccionará el primer grupo de acceso especificado en su Entitlements.plist al escribir y buscará en todos los grupos de acceso cuando no se especifique ninguno.

La clave será búsqueda en todos los grupos donde se concede acceso. Entonces, para resolver su problema, puede agregar un grupo de acceso de todas sus aplicaciones en sus derechos. En vez de usar un grupo de “cosas compartidas”, ponga $ (CFBundleIdentifier) ​​como su primer grupo de llavero (su envoltorio de llavero luego escribirá en este grupo) y ya está todo listo

Aquí está la versión Swift de la respuesta de @David H:

 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($0)) } if status == errSecItemNotFound { status = withUnsafeMutablePointer(to: &result) { SecItemAdd(queryLoad as CFDictionary, UnsafeMutablePointer($0)) } } if status == noErr { if let resultDict = result as? Dictionary, 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 } }