ios widget開發


1.證書配置:http://blog.csdn.net/songchunmin_/article/details/51316806

2.編碼階段:http://blog.csdn.net/songchunmin_/article/details/51291752

3.官方文檔:https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Today.html

4.國外有篇比較好的文檔:https://www.appcoda.com/app-extension-programming-today/

5.widget幾個常用功能的實現:http://www.jianshu.com/p/9b3d06236d19

術語:

主項目:往已有的A項目里添加widget,那么A是主項目

 

Start~

環境搭建

1.蘋果后台配置證書,下載Provisioning Profiles文件,得到4個Provisioning Profiles文件(主項目和widget分別有兩個:dev的和release的)。

注意widget項目和主項目其實是兩個獨立的appID,而通過app group來相互交互。

2.對於主項目的配置:

(1)選擇新的pro證書

(2)打開targets-->Capabilities-->App Groups 選項,然后選擇后台配置的group:

3.添加widget項目。

 

 

將Bundle Identifier改為和蘋果后台配置的appid一樣。並且注意當時命名的時候,必須遵循如下規則:前綴要包括主項目的Bundle Identifier。后綴不能是widget關鍵字(。。。這里很坑,試了很多次)。然后因為我的XCode並沒有配置開發者賬號,所以將Automatically manage singing的對勾去掉(反正證書文件都下載給你了)。

然后選擇好Provisioning Profile文件,dev和release的。當前頁的error就都應該消失了。

將Build Setting里的簽名設置好:

 

如果當時在蘋果后台配置證書的時候,deviceid都加上了你的手機,那么直接真機運行,就可以在手機上看到一個“Hello World”的widget。

第一次運行,可能看到左上角名字是WIDGET,這個有點延遲,第二次就可以看到是“寶寶樹小時光”。

業務邏輯實現

1.純代碼實現布局:

通過以上步驟,添加的widget項目,使用的是Storyboard作為布局。使用純代碼需要:

(1)刪除Storyboard文件,widget項目的plist,刪除NSExtensionMainStoryboard

(2)添加NSExtensionPrincipalClass字段 並設為TodayViewController

2.TodayViewController生命周期:

經過測試:基本上超過2秒,widget元素在屏幕上消失(手機沒有停留在widget頁面或者停留在widget頁面,沒有滑動到自己項目的widget),widget再次出現的時候,都會重新調用ViewDidLoad。而短時間的消失再出現,不會執行ViewDidLoad而是執行ViewWillAppear。所以如果不進行處理,每次widget出現,就請求數據的話,即時兩次數據相同也會閃一下(知乎),想不閃可以把數據緩存,每次widget出現都加在緩存數據,並且發送請求,請求回的數據和當前展示數據做對比,如果一樣,則不用刷新列表,如果不一樣則刷新列表。然后緩存的機制,因為一般請求的數據都是json,可以解析成dic對象,使用plist進行緩存,比較方便。

3.展開/折疊,在這個系統方法中設置展開、折疊的高度即可,但是好像不能主動設置在什么情況下是展開的,在什么情況下的折疊的,也就是說不能代碼控制展開還是折疊,只能是用戶點擊按鈕來展開和折疊,蘋果沒有給出那么多的自由。

- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize {
    if (activeDisplayMode == NCWidgetDisplayModeCompact) {
        self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 105);
    } else {
        self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 495);
    }
}

4.使用主項目的自定義類,以及第三方庫:

widget開發時,肯定會遇到想使用主項目的類的情況,只需要將要使用的類的.m文件,多加上一個target,選擇widget項目即可。

使用第三方庫,我的項目里暫時沒有遇到這種需求,但是通過pods維護第三方庫的時候,Podfile文件會指定每個第三方庫要加入的target,那么在widget的target中,加上要使用的第三方庫,應該就可以,可以自己試試。

5.數據共享

widget項目必然經常要和主項目共享數據,可以通過NSUserDefault,注意和平時用有些不同,創建UserDefault的時候,要指定groupid。上代碼:

// widget項目里取數據

+ (NSString *)widgetStringForKey:(NSString *)defaultName {
    NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.appname"];
    return [shared stringForKey:defaultName];
}

 

// 主項目里存數據

+ (void)widgetSetObject:(id)value forKey:(NSString *)defaultName {
    NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.appname"];
    [shared setObject:value forKey:defaultName];
    [shared synchronize];
}

 還有通過NSFileManager數據共享的方式,項目里沒有用到,可以自己查閱資料試一試。

6.喚起主項目

通過URL Schemes的方式:

(1)在主項目里配置一個對應widget的URL。

(2)在需要喚起主項目的地方:

NSString *schemeString = [NSString stringWithFormat:@"HMWidget://jumptab?number=%@",[NSString encodeBase64String:@"3"]];
    [self.extensionContext openURL:[NSURL URLWithString:schemeString] completionHandler:^(BOOL success) {
    }];

(3)在主項目appdelegate的代理方法中,截取URL,做處理:

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    if ([url.description hasPrefix:@"HMWidget://"]) {
        if (![HMUser isLogin]) {
            return YES;
        }
        return [HMSchemeUrlRouter handleScheme:url.description withAppDelegate:self];
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM