不同 App 之間原本是無法溝通的,但是可運用一些技術來達到效果,運用場景像是同一間公司出的 App 可以互通登入狀態,或是 App 需要與 App Extension 共用資料等等。

官方文件

Apple 有官方文件解釋到相關技術 - Sharing Access to Keychain Items Among a Collection of Apps

  • 兩隻 App 間無法共用資料的狀況
  • 兩隻 App 間共用資料的狀況

共用資料的方式

UserDefaults + suiteName + App Groups

  1. Project > Signing & Capabilites > Add App Groups ( 請自定義一個 suiteName )

  2. 在需要存取資料的地方使用 UserDefaults 的 suiteName 寫法,suiteName = 上一步建立的 suiteName

    1
    2
    3
    let groupUserDefaults = UserDefaults.init(suiteName: "group.pink.company")
    groupUserDefaults?.setValue(fcmToken, forKey: "loginDataKey")
    let data = groupUserDefaults?.value(forKey: "loginDataKey")

Keychain + accessGroup + Keychain Sharing

  1. Project > Signing & Capabilites > Add Keychain Sharing ( 請自定義一個 sharingName )

  2. 在需要存取資料的地方使用 Keychain 的 accessGroup 寫法,accessGroup = 你的 App 的 teamID+.+sharingName

    原始寫法

    1
    2
    3
    4
    5
    6
    7
    let accessGroup = "<# Your Team ID #>.com.pink.sharing"
    let attributes = [kSecClass: kSecClassGenericPassword,
    kSecAttrService: service,
    kSecAttrAccount: username,
    kSecAttrAccessGroup: accessGroup,
    kSecValueData: password] as [String: Any]
    let addStatus = SecItemAdd(attributes as CFDictionary, nil)

    但原始的 Keychain 寫法比較複雜,推薦使用三方 KeychainAccess 來處理

    1
    2
    3
    4
    5
    6
    import KeychainAccess

    let accessGroup = "<# Your Team ID #>.com.pink.sharing"
    let keychain = Keychain(accessGroup: accessGroup)
    keychain["sharingDataKey"] = value
    let keychainData = try? keychain.get("sharingDataKey")