讓不同 App 共享資料的 App Group

一般的情況下,iOS App 只能存取自己資料夾下的東西,無法存取其它 App 的內容。Apple 這麼做主要是為了安全,比方彼得潘如果不小心裝了虎克船長開發的邪惡 App,它也無法讀取我在 LINE 裡傳給溫蒂的私密照片。

不過有時我們會開發好幾個 App,如果自己開發的 App 能夠共享資料,應該會方便許多。Apple 其實提供一些方法讓不同的 App 可以共享資料,比方我們接下來要介紹的 App Group。Different ways to share data between apps — iOSA good idea is about ten percent and implementation and hard work, and luck is 90 percent. — Guy Kawasakimedium.com

App Group 讓不同的 App 或是 App & App extension 之間可以透過以下兩種方法共享資料(不過必須是同一個帳號開發的 App):

1 利用 UserDefaults 共享資料。

2 共同存取某個特別的資料夾。

接下來就讓我們建立兩個專案,梁山伯和茱麗葉,讓茱麗葉 App 可以收到梁山伯 App 輸入的情話吧。

1 建立兩個專案

使用者可在梁山伯 App 的畫面上打字,輸入他想對茱麗葉說的話。

茱麗葉 App 打開後,可看到最近一次梁山伯 App 輸入的文字。

2 製作梁山伯 App

(1) 從 Project navigator 選擇專案檔,切換到 Capabilities 頁面後,將 App Groups 的開關打開。

App 必須設定 Team 才能加入 App Groups,因此如果之前沒設定,此時 Xcode 會跳出視窗要我們選擇。此功能不一定要付費的開發帳號,所以免費帳號也可以測試。

打開開關後,App Groups 的開關變成 ON 的狀態。

(2) 點選 App Groups 左下角的 +,新增 container。

此時輸入的 container 名字(group id)十分重要,到時候不同的 App 將使用此名字搭配 UserDefaults 共享資料。

經過以上步驟,此時 Xcode 將產生 entitlements 檔,裡面包含剛剛設定的 App container 名字。

如果是付費的開發帳號,此時還可以連到 Apple 的開發網站查詢,Apple 會幫此 App 的 App ID 加入 App Groups 功能,並且綁定剛剛在 Xcode 指定的 container 名字。

(3) 在 button 按下時將 text filed 的文字存到共享的 UserDefaults。

class ViewController: UIViewController {   @IBOutlet weak var textField: UITextField!   @IBAction func buttonPressed(_ sender: Any) {      let userDefaults = UserDefaults(suiteName: "group.peter.boy")      userDefaults?.set(textField.text, forKey: "loveMessages")   }}

原本不同的 App 無法共享 UserDefaults 的資料。然而在這裡我們卻做到了,因為我們利用 UserDefaults(suiteName: "group.peter.boy") 建立 UserDefaults,在參數 suitName 傳入 container 的名字。

此 UserDefaults 厲害多了,存在裡面的資料可以讓不同的 App 共享,只要這些 App 是同一個帳號開發,而且在 Xcode 的 App Groups 下設定一樣的 container 名字。init(suiteName:) – UserDefaults | Apple Developer DocumentationYou can use this method when developing an app suite, to share preferences or other data among the apps, or when…developer.apple.com

3 製作茱麗葉 App

(1) 設定跟梁山伯專案一樣的 App Groups。

由於我們曾經建立過 App Group group.peter.boy,所以打開 App Groups 的開關時,Xcode 將自動幫我們加入 group.peter.boy。

不過它並不會勾選,所以請記得勾選 group.peter.boy,如此才代表我們的 App 要使用它。

(2) 從 UserDefaults 讀取文字,顯示到 label 上。

class ViewController: UIViewController {   @IBOutlet weak var label: UILabel!    override func viewDidLoad() {      super.viewDidLoad()      let userDefaults = UserDefaults(suiteName: "group.peter.boy")      if let messages = userDefaults?.string(forKey: "loveMessages") {         label.text = "茱麗葉聽到梁山伯說:\n\(messages)"      }   }}

記得用 UserDefaults(suiteName: "group.peter.boy") 生成 UserDefaults,並且傳入一樣的 container name,如此茱麗葉 App 才能讀取梁山伯 App 儲存的內容。

4 執行 App

如下圖所示,當我們用梁山伯 App 輸入文字,然後再打開茱麗葉 App,果然看到了梁山伯輸入的文字,原來他們是在 Christmas 時一見鍾情的 !

container name(group id) 必須要獨一無二

在 Capabilities 頁面設定 App Group 時,有些人會遇到問題。比方以下的錯誤。

錯誤訊息說,An Application Group with Identifier ‘group.peter.boy’ is not available. Please enter a different string.。原因是此 group id 已經被別的開發帳號使用了,所以我們必須取別的名字,group id 必須要獨一無二,不能跟別人一樣。

將檔案存到共享的 container 資料夾

剛剛我們利用 UserDefaults 實現資料的共享,可惜它只適合儲存少量的資料,如果想儲存大量的資料,則可另外將檔案存在共享的 container 資料夾,方法如下。

存檔的程式範例

if let shareUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.peter.boy") {   let imagePath = shareUrl.appendingPathComponent("image.png")   try? UIImage(named: "chocolate")?.pngData()?.write(to: imagePath)}

利用 FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.peter.boy") 得到共享的 container 資料夾 url,參數 forSecurityApplicationGroupIdentifier 傳入 App Group 下設定的 container name。containerURL(forSecurityApplicationGroupIdentifier:) – FileManager | Apple Developer DocumentationIf you call the method with an invalid group identifier, namely one for which you do not have an entitlement, the…developer.apple.com

讀檔的程式範例

if let shareUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.peter.boy") {   let imagePath = shareUrl.appendingPathComponent("image.png")   let image = UIImage(contentsOfFile: imagePath.path)   imageView.image = image}

執行 App

茱麗葉 App 顯示梁山伯 App 儲存在 container 資料夾的圖片。

刪除 App Group 的 group id

雖然我們在 Xcode 建立 group id,不過若想刪除它,卻必須另外登入 Apple 的開發網站,在它的 App Groups 頁面做刪除的動作。(因此只有付費的帳號能夠刪除 group id。)

Leave a Comment