如何在 React Native 專案新增 iOS Widgets

React Native 專案設定

新增 widget extension 之後,專案會發生無法 build 的錯誤, 請參考此

issue: https://github.com/facebook/react-native/issues/29246

調整 swift 版本

imgur
imgur
調整完後請新增一個 swift 檔,Xcode 會詢問你是否要加入 bridge-header 檔來讓 Objective-c 的程式可以讀 swift 的程式,新增完成後,專案就可以正常 compile 了

imgur

Widget 工作原理

Widget 依照 TimelineProvider 提供的 Snapshot/Placeholder 和 Timeline 進行顯示與更新,只要 Timeline 更新,Widget 就會更新

預設顯示畫面 (Snapshot/Placeholder)

工具列選擇 Widget 時,預設的 Widget 顯示資

imgur
imgur

Timeline

  • entries(entry[]): 每時間點需要顯示的資料

    • entry: 由 顯示時間(date)和其他自定義資料組成
  • Policy: 更新 Timeline 的規則

    Policy 種類:

    • atEnd: 當 TimelineProvider 提供 TimelineEntry 為陣列的最後一個時,系統將會要求新的 Timeline。
    • after(Date): 當指定的時間到,取得新的 Timeline
    • never: 不再抓取,但可以在 App 開啟時主動 reload Timeline

imgur
使用 atEnd policy 的 Timeline

imgur
使用 after policy 的 Timeline

在 App 裡更新 Timeline

  • 更新一個 Widget 的 Timeline
WidgetCenter.shared.reloadTimelines(ofKind: "com.brian.MyApp.My-Widget")
  • 更新所有 Widget 的 Timeline
WidgetCenter.shared.reloadAllTimelines()

Widget 如何與 App 共享資料

AppGroup

在 App Traget 下面選擇 AppGroup, 如果沒有建立過,點擊下面 + 號即可建立

imgur
重複上面動作,將 Widget 也加到相同名稱的 AppGroup, 我們就可以讀取、存取 UserDefault 裡面的資料

let userDefaults = UserDefaults(suiteName: "group.widget.store");
userDefaults?.setValue(value, forKey: "text" )
let userDefault = UserDefaults(suiteName: "group.widget.store")
let text = userDefault?.value(forKey: "text") as? String ?? "No text!!"

點擊 Widget 後導頁至特定頁面 (Deep Linking)

建立 App urlType

imgur

React Navgation 設定

在 iOS 專案裡的 AppDelegate.m 加入

// Add the header at the top of the file:
#import <React/RCTLinkingManager.h>

// Add this above the `@end`:
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:app openURL:url options:options];
}

設定 Deeplink prefix

const SimpleApp = createAppContainer(
createStackNavigator({
Home: { screen: HomeScreen },
Chat: {
screen: ChatScreen,
// :user 是 navigation 的參數
path: 'chat/:user',
},

);

const prefix = 'mychat://';

const MainApp = () => <SimpleApp uriPrefix={prefix} />;

設定點擊 Widget 的 url

var body: some View {
VStack {
// 到 Chat screen 的按鈕
Link(destination: homeDeepLink) {
Text("mychat://Chat/abc123")
}
}.widgetURL("mychat://Home") // 點擊 Widget 外框
}

Reference Article:

Reference Video :

Express 筆記 React Native Beacon 功能開發
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×