iOS widget擴(kuò)展功能最主要的目的是可快捷查看該App里面的某些功能,無(wú)需每次進(jìn)入app才能查看。為app提供一個(gè)“小應(yīng)用”。iOS widget擴(kuò)展已經(jīng)不是一個(gè)新鮮的技能了,最近公司對(duì)widget 有一個(gè)新的需求,為此也做了一下總結(jié)以便回顧。
widget擴(kuò)展顧名思義就是在原有的項(xiàng)目上做一個(gè)擴(kuò)展,所以首先需要有一個(gè)項(xiàng)目,創(chuàng)建項(xiàng)目對(duì)大家來(lái)說(shuō)已經(jīng)是一件非常簡(jiǎn)單的事情,在這里我就不演示。打開(kāi)項(xiàng)目后
在項(xiàng)目的設(shè)置頁(yè)面創(chuàng)建一個(gè)target擴(kuò)展


創(chuàng)建成功后該項(xiàng)目多了一個(gè)文件夾文件夾中多了三個(gè)文件

值得注意的是widget擴(kuò)展在iOS10之前是不能點(diǎn)擊右上角的展開(kāi)/折疊這個(gè)功能的。只有一個(gè)默認(rèn)高度為110(220px),通過(guò)3D touch drop app的應(yīng)用圖標(biāo)時(shí),顯示的widget也只能顯示高度為110(220px)。
如果需要有展開(kāi)/折疊個(gè)功能的需要在viewDidLoad中指定
if #available(iOSApplicationExtension 10.0, *) {
self.extensionContext?.widgetLargestAvailableDisplayMode = .expanded
}
@available(iOS 10.0, *)
public enum NCWidgetDisplayMode : Int {
case compact // 固定高
case expanded // 可變高
}
widgetLargestAvailableDisplayMode 是一個(gè)枚舉,有兩種樣式可以做選擇。具體就要看該項(xiàng)目的實(shí)際需求,我這邊指定的是可展開(kāi)/折疊 這個(gè)模式。
當(dāng)視圖創(chuàng)建時(shí)或點(diǎn)擊右上角視圖高度發(fā)生改變時(shí)會(huì)觸發(fā)( iOS 9前不可伸縮且固定高度為110 ,此方法只作用在iOS 9 以上的版本)
@available(iOSApplicationExtension 10.0, *)
func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize) {
if activeDisplayMode == .compact {
self.preferredContentSize = CGSize(width: 0, height: 110);
...
}else {
self.preferredContentSize = CGSize(width: 0, height: 150);
...
}
}
self.preferredContentSize 該屬性是設(shè)置該擴(kuò)展的高度。在compact模式下高度為110,無(wú)論設(shè)置多高都為110.在expanded模式下可以指定你需要的高度,但是也并不是你想多高就多高.經(jīng)測(cè)試最高只能顯示一個(gè)屏幕完全展示的大小。
在項(xiàng)目中也想使用pod工具來(lái)集成第三方庫(kù),通過(guò)不同target來(lái)導(dǎo)入不同的框架
platform :ios, '7.0'
target 'widgetTest' do
pod 'AFNetworking', '~> 3.0.4'
pod 'SDWebImage', '~> 3.7.5'
pod 'MJExtension', '~> 3.0.13'
pod 'MJRefresh', '~> 3.1.12'
pod 'SWTableViewCell', '~>0.3.7'
pod 'JPush'
pod 'SocketRocket', '~> 0.5.1'
pod 'UMengUShare/UI'
pod 'UMengUShare/Social/WeChat'
pod 'UMengUShare/Social/QQ'
pod 'UMengAnalytics-NO-IDFA'
end
target 'TodayWidget' do
pod 'SocketRocket', '~> 0.5.1'
end
到了編輯我們的展示頁(yè)面的時(shí)候了。依然還是可以使用純代碼、storyboard或者混編都可以,控件與我們app中的UIKit 是完全一樣的,可根據(jù)具體的業(yè)務(wù)需求搭建你的視圖。
在擴(kuò)展中點(diǎn)擊某個(gè)按鈕打開(kāi)app并跳到響應(yīng)的位置。我們可以使用Schemes跳轉(zhuǎn)。在擴(kuò)展中對(duì)應(yīng)位置加上
let url = URL(string: "TodayWidget://Buy")
self.extensionContext?.open(url! , completionHandler: { (bool) in
})
回到主app中加上對(duì)應(yīng)的TodayWidget

在Appdelegate中實(shí)現(xiàn)
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
if ([url.absoluteString containsString:@"Buy"]){
....
}
return YES;
}
在開(kāi)發(fā)過(guò)程中,我做了一件非常愚蠢的事情,在運(yùn)行擴(kuò)展的時(shí)候把斷點(diǎn)加載回調(diào)openURL中,發(fā)現(xiàn)始終都進(jìn)不了,調(diào)試了一天始終發(fā)現(xiàn)找不出原因,正打算通過(guò)其他方式來(lái)實(shí)現(xiàn)回調(diào)的時(shí)候,突然發(fā)覺(jué)app其實(shí)不在調(diào)試狀態(tài),調(diào)試的是擴(kuò)展,可以看出,擴(kuò)展調(diào)試的時(shí)候跟app是不會(huì)同時(shí)運(yùn)行的,請(qǐng)不要在運(yùn)行擴(kuò)展的時(shí)候去調(diào)試app。
widget開(kāi)發(fā)中,如果你很熟練的掌握app中各個(gè)控件的開(kāi)發(fā)的話。其實(shí)沒(méi)有任何難度。widget擴(kuò)展中遵循的是NCWidgetProviding 協(xié)議。只要進(jìn)去協(xié)議中瀏覽一遍,相信每個(gè)人都很快就能完成這個(gè)擴(kuò)展功能。