IOS小元件(8):App與Widget資料共享

popfisher發表於2021-06-11

引言

  Widget是一個迷你版的App,IOS有沙盒機制,不同App之間無法直接共享資料。元件和主App之間其實就是不同App的關係,所以也無法通過userdefaults.standard來傳資料,蘋果為了在不打破沙盒的前提下能夠傳資料,就想出了App Group的方法。

資料共享方式

 可以通過網路和本地資料兩種方式進行資料的共享,本地資料共享可以通過 App Groups。

App Groups 原理

  它是 iOS 8 之後推出的在 App 之間共享資料的方式,只需要簡單的配置就可以實現資料的共享。它主要用於同一group下的app共享同一份讀寫空間,以實現資料共享。編碼 App Groups只能非同步同步資料,當Widget讀取資料的時候,只能讀之前手機App儲存的資料,相反也是如此。當手機App有新的資料儲存時,不能及時的通知Widget更新資料,只能是Widget下次去主動獲取資料。

配置證書

  由於widget專案和主專案其實是兩個獨立的appID,因為需要單獨給widget配置證書,配置證書的過程參考APP證書配置;

開啟APP Groups

  開啟APP Groups是為了widget和app之間實現資料共享;為了便於後續操作,請先確保你的開發者賬號在Xcode上處於登入狀態。

在app中開啟:

    • TARGETS-->AppExtensionDemo-->Capabilities-->App Groups
    • 找到以後,將App Groups右上角的開關開啟,然後選擇新增groups,注意命名要規範,比如:group.com.company.app;

在extension中開啟

假設建立widget target的名稱為TodayExtension,對應的App Group位於

  • TARGETS-->TodayExtension-->Capabilities-->App Groups
  • 開啟的方式和APP中一樣,注意必須要保證這裡的App Groups名稱和APP中相同。

App Groups特點

  App Group容器只是在宿主app執行期間才存在,其中的容器用於擴充套件與宿主的檔案共享,宿主被關閉了,共享也就沒意義了。
以上來自於實際測試,測試過程是:在宿主app執行期間,點選其中的按鈕彈出模態檢視控制器,進行資料填充。完成後儲存資料到App Group容器中的檔案中,以供today extension擴充套件進行資料使用。只要將宿主app殺掉後重啟啟動宿主app,today extension 中已經顯示的資料就完全沒有了。單純將宿主app殺掉不重啟,today extension的任然hi顯示之前的內容。由於宿主app中顯示的資料也是從app group中的檔案中取出來的,所以資料也沒了。

  由於這個共享機制的特殊性,這個容器不能用來長期儲存檔案!!!應該將檔案儲存到宿主app的資料夾中,可以長期儲存。today extension展示的資料量較少,在合適的時候將其需要的資料搬運到app group中!

共享資料核心程式碼

FileManager實現建立一個資料夾

/*
 * 建立並返回目錄路徑URL
 */
static private func makeShareFolderExists(folderName: String) -> URL? {
    let documentsDirectory = FileManager().containerURL(forSecurityApplicationGroupIdentifier: groupId)
    guard let folderURL = documentsDirectory?.appendingPathComponent(folderName) else { return nil}
    
    var isDir : ObjCBool = false
    var isExists = FileManager.default.fileExists(atPath: folderURL.path, isDirectory: &isDir)
    if isExists && !isDir.boolValue {
        do {
            try FileManager.default.removeItem(at: folderURL)
            isExists = false;
        } catch {
            return nil
        }
    }
    if !isExists {
        do {
            try FileManager.default.createDirectory(atPath: folderURL.path, withIntermediateDirectories: true, attributes: nil)
        } catch {
            return nil
        }
    }
    return folderURL
}

  更多 FileManager 請檢視官網Api https://developer.apple.com/documentation/foundation/filemanager/

參考

結語

  本文講解了App與小元件的資料共享方式是用App Groups機制來實現的,配置相關的請參考其他文章裡面的詳細操作步驟。另外請特別注意App Groups裡面的資料不是永久的,只是暫存而已

相關文章