先吐個槽:隨著iOS14系統(tǒng)發(fā)布草姻,新的小組件掀起了一股熱潮钓猬,在距離十一假期還有3天的時候,領(lǐng)導看著App Store排行榜沉思了一秒鐘就做出了決定:我們也要做小組件撩独,并且要在十一假期前上架App Store敞曹,先搶占一波流量。但是對我而言跌榔,WidgetKit沒看過异雁、swiftUI沒用過、swift不熟練僧须,所以只能現(xiàn)學現(xiàn)賣了纲刀。領(lǐng)導動動嘴,我們累斷了腰啊,沒辦法示绊,Just Do IT吧??
正文
widgetKit出來已經(jīng)有段時間了锭部,關(guān)于新小組件的說明和原理網(wǎng)上很多,蘋果開發(fā)者網(wǎng)站也有詳細的解釋說明面褐,這里就不贅述了拌禾,需要了解基礎(chǔ)的同學可以去?Developer查看官方文檔,目前網(wǎng)上的說明和示例基本都是翻譯的官方文檔展哭,今天主要說一下我自己在開發(fā)小組件中遇到的問題及解決方案(主要是原理和想法上的問題湃窍,不涉及具體方法的實現(xiàn))。
一匪傍、小組件與主APP數(shù)據(jù)互通
由于小組件是一個extension您市,需要在項目中新建一個target,所以在小組件中無法獲取到主APP的沙盒數(shù)據(jù)役衡,但可以通過APP Groups的方式實現(xiàn)數(shù)據(jù)互通茵休。
1.UserDefaults使用[[NSUserDefaults alloc] initWithSuiteName:@"group_id"]
來獲取共享數(shù)據(jù)。
2.數(shù)據(jù)庫可以使用[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group_id"]
筆者目前的做法是在主APP中設(shè)置完小組件內(nèi)容后手蝎,生成plist文件再通過
[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group_id"]
的方式將plist文件保存到共享沙盒中榕莺,再在小組件中獲取,圖片同理棵介。
ps:通過網(wǎng)絡(luò)請求的方式钉鸯,將配置信息上傳到服務(wù)器,再在小組件中請求服務(wù)器信息應(yīng)該也可以鞍时。
二亏拉、持續(xù)刷新問題
小組件的刷新在Provider的getTimeline 方法里有一個 policy
參數(shù)扣蜻,表示刷新的時機逆巍,可以選擇.never(不自動刷新)
、.atEnd(時間線中的數(shù)據(jù)顯示完畢之后自動刷新)
莽使、.after(date)(到達自己設(shè)置的時間后自動刷新)
锐极。
然而在開發(fā)過程中發(fā)現(xiàn),有時候即使到達刷新時間或者時間線中的數(shù)據(jù)顯示完畢芳肌,小組件也不自動刷新灵再,這是由于小組件有自己的刷新機制,記得好像是15分鐘(不確定在哪里看到過)亿笤,既然如此那就在時間線中添加更多的entry來保證小組件可以持續(xù)刷新翎迁。然而事與愿違,當添加的entry太多時運行小組件崩潰净薛,顯示內(nèi)存不能超過30M汪榔。
由于組件中有圖片及其他自定義屬性,所以添加多個entry時內(nèi)存太大肃拜,于是嘗試使用單例的方式將entry中除Date之外的屬性和圖片全部放在單例中痴腌,這樣entry中只包含Date一個屬性雌团,創(chuàng)建多個entry占用的內(nèi)存也不會太大。
至此士聪,問題貌似解決了锦援,但每次添加和刷新小組件時需要更長的時間加載時間線中的內(nèi)容,導致小組件一片空白剥悟。目前只能平衡一下灵寺,在時間線中添加300條即5分鐘的數(shù)據(jù)。
ps:目前看了很多持續(xù)刷新的小組件(大多為時間顯示類)区岗,發(fā)現(xiàn)都存在刷新停止的問題替久,只有《氫時鐘》沒有這個問題,不知道是怎么做到的
三躏尉、用戶自定義配置的問題
用戶自己選擇小組件配置的方式是使用Configuration Intent配合Intent Extension來實現(xiàn)蚯根,這個倒是不難實現(xiàn),只是產(chǎn)品經(jīng)理要求我們只做小中大三個組件內(nèi)容根據(jù)用戶自己選擇的配置來顯示胀糜,且三個組件的內(nèi)容是分開的颅拦,即假如有時間、天氣教藻、和健康三個組件距帅,如果用戶在小組件中添加了時間組件,則在手機中添加的組件中只有小號組件的配置中有天氣選項括堤,而中號和大號組件中不能有天氣選項碌秸。
在網(wǎng)上找了好久也找不到解決方案,最后想到一個方案悄窃,使用3個Intent來實現(xiàn)讥电,機智!
解決方式:
在Configuration.intentdefinition
中添加小轧抗、中恩敌、大三個Intent,如圖:
再添加3個Intent Extension來處理這三個Intent中的數(shù)據(jù)横媚,如圖:
在Info.plist
中NSExtension
->NSExtensionAttributes
->IntentsSupported
數(shù)組中添加對應(yīng)的Intent名稱纠炮,如:SmallIntent
的Info.plist
中添加SmallConfigurationIntent
注意:
1、添加的值是SmallConfigurationIntent
而不是SmallConfiguration
灯蝴,即SmallConfiguration
后需要加上Intent
2恢口、如果修改了Configuration.intentdefinition
中的值(包括Configuration的Parameter
、ENUMS
和TYPES
中的值)穷躁,在三個Info.plist
文件中會自動增加小中大三個ConfigurationIntent耕肩,需要將其他兩個刪除,只保留一個對應(yīng)的ConfigurationIntent,坑翱戳啤沙峻!
3、如果需要與主APP數(shù)據(jù)互通两芳,那么三個Intent Extension
中都需要添加App Groups
這里要吐槽一下XCode自動生成代碼是真的惡心摔寨,配置完Configuration.intentdefinition后在IntentHandler
類中使用代理ConfigurationIntentHandling時總是提示找不到,開始我以為自己寫錯了怖辆,檢查了半天也不知道咋回事是复,后來莫名其妙又好了,最后才知道需要Clean后再Build一下才行竖螃,有時候需要退出Xcode才行淑廊。