Widget的簡單應用並適配iOS10
widget這個小外掛不知道有多少人習慣使用?又或者有多少使用iphone手機的使用者知道這東西的存在?好了,不說廢話了;既然公司有這需求,小編也只能去研究了!下面來和大家介紹小編研究成果!查詢了網上的相關內容,沒有發現什麼特別全面詳細的文章!只能自己查官方文件嘍!
官方對widget的解釋:App Extension Programming Guide: Today
People view Today widgets in the Today area of Notification Center. Because people configure the Today area so that it displays the information they value most, it works well to approach the design of your widget with the goal of earning a place among the user’s most important items.
extension是iOS8新開放的一種對幾個固定系統區域的擴充套件機制,extension並不是一個獨立的app,它有一個包含在app bundle中的獨立bundle,extension的bundle字尾名是.appex;需要依賴於containning app。
點選“編輯”可是新增其他app的widget。
如何建立widget?
- 建立一個工程,在該工程裡新增targets:
- 建立成功之後的專案結構:
- iOS 10和iOS 10之前的介面對比:
搭建簡單的互動介面
- 檔案配置:
系統生成的info.plist檔案預設是使用Storyboard 實現的介面;如果你想使用程式碼實現是介面的搭建,需更改這個配置檔案:The Xcode Today template provides default header and implementation files for the principal class (named TodayViewController), an Info.plist file, and an interface file (that is, a storyboard or xib file).
By default, the Today template supplies the following Info.plist keys and values (shown here for an OS X target):
<key>NSExtension</key><dict> <key>NSExtensionPointIdentifier</key> <string>com.apple.widget-extension</string> <key>NSExtensionPrincipalClass</key> <string>TodayViewController</string> </dict>
If you use a custom view controller subclass, use the custom class name to replace the TodayViewController value for the NSExtensionPrincipalClass key.
-
NSExtensionMainStoryboard:MainInterface(你Storyboard的名稱)
-
NSExtensionPrincipalClass:TodayViewController(你widget控制器的名稱)
NSExtensionAttributes:這是一個描述擴充套件點具體屬性的字典,就像照片編輯擴充套件中的PHSupportedMediaTypes一樣。
NSExtensionPrincipalClass:這是擴充套件模板建立的主體檢視控制器類,比如TodayViewController。當載體應用程式(host app)呼叫擴充套件時,擴充套件點會例項化這個類。
NSExtensionMainStoryboard(只適用於iOS):擴充套件預設的Storyboard檔案,一般名為MainInterface。
注:
本文以程式碼為例!
方法實現:
- 介面的搭建(<iOS 10):
-(void)viewDidLoad { [super viewDidLoad]; WGHeaderView *headerView = [[WGHeaderView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 110)]; headerView.delegate_ = self; [self.view addSubview: headerView]; self.headerView = headerView; } // 設定介面的高度 -(void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 110); }
- 更新widget檢視:(demo目前只是按鈕 不需要更新)
執行程式:-(void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler { // NCUpdateResultNewData 新的內容需要重新繪製檢視 // NCUpdateResultNoData 部件不需要更新 // NCUpdateResultFailed 更新過程中發生錯誤 completionHandler(NCUpdateResultNoData); }
因此還需要實現:-(UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets{ return UIEdgeInsetsMake(0, 10, 0, 10); }
注意:
該方法在iOS 10之後就被淘汰了! -
實現點選按鈕跳轉:
配置URL schemes:
在按鈕點選的方法裡實現:(此處小編用的代理)NSString *urlStr = [NSString stringWithFormat:@"medicalWdget://%li",index]; NSURL *url = [NSURL URLWithString:urlStr]; [self.extensionContext openURL:url completionHandler:^(BOOL success) { }];
目前就可以跳轉到app了!當然是四個按鈕,你需要再AppDelegate裡面進行處理:
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{ if ([url.scheme isEqualToString:@"medicalWdget"]) { [[NSNotificationCenter defaultCenter] postNotificationName:@"ExtenicationNotification" object:url.host]; } return YES; } // ios9 之後 -(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{ if ([url.scheme isEqualToString:@"medicalWdget"]) { [[NSNotificationCenter defaultCenter] postNotificationName:@"ExtenicationNotification" object:url.host]; } ![72BBF230-83EB-4650-BE27-EE0FBBAAD35F.png](http://upload-images.jianshu.io/upload_images/1109379-2530dc667076faee.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) return YES; }
然後處理相應的通知,判斷url.host點選的第幾個按鈕!
適配iOS 10:
-
NCWidgetDisplayMode
NCWidgetDisplayModeCompact, // Fixed height NCWidgetDisplayModeExpanded, // Variable height
需要再設定高度之前設定該屬性;
-(void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; if ([[UIDevice currentDevice].systemVersion doubleValue] >= 10.0) { self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeCompact; } self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 110); }
模式改變後會執行下面這個方法:
-(void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize{ if (activeDisplayMode == NCWidgetDisplayModeCompact) { NSLog(@"maxSize-%@",NSStringFromCGSize(maxSize));// maxSize-{359, 110} }else{ NSLog(@"maxSize-%@",NSStringFromCGSize(maxSize));// maxSize-{359, 616} } }
兩種設計風格:
擴充套件:
注意:
有人看到這種介面可能會想到tableview實現,開始小編也是這樣想的。可是實現起來發現佈局都是亂的(具體原因沒有找出來,如哪位研究出來了,麻煩交流一下)!所以建議大家使用UIView就可以了!
網路請求資料:
@try {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSMutableDictionary *param = [[NSMutableDictionary alloc] init];
[param setObject:@"gettopics" forKey:@"action"];
[param setObject:@"135644452322" forKey:@"EchoToken"];
[param setValue:@"data" forKeyPath:@"type"];
[param setValue:[NSString stringWithFormat:@"%i",widgetCount] forKeyPath:@"pagesize"];
[param setValue:@"1" forKeyPath:@"pageindex"];
[param setValue:@"" forKeyPath:@"username"];
[param setValue:@"cF54141DC1FA8E736B45244428874CE46==" forKeyPath:@"token"];
NSDictionary *headers = @{@"Content-Type":@"application/json; charset=utf-8",
@"Accept":@"application/json"
};
NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:[@"v1/api.ashx?action=" stringByAppendingString:@"gettopics"]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0];
request.HTTPBody = [[NSString stringWithFormat:@"type=data&pagesize=%i&pageindex=1",widgetCount ] dataUsingEncoding:NSUTF8StringEncoding];
request.allHTTPHeaderFields = headers;
request.HTTPMethod = @"POST";
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:param options:NSJSONWritingPrettyPrinted error:&error];
request.HTTPBody = jsonData;
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSError *jsonError = nil;
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonError];
if (!jsonError) {
NSMutableArray *mutArr = [NSMutableArray array];
for (NSDictionary *dict in jsonDict[@"list"]) {
WGTopic *topic = [[WGTopic alloc] initWithDict:dict];
[mutArr addObject:topic];
}
self.hotTopicArr = mutArr;
}
}];
// 啟動任務
[dataTask resume];
dispatch_async(dispatch_get_main_queue(), ^{
[self.view layoutIfNeeded];
});
});
} @catch (NSException *exception) {
} @finally {
}
如果是http請求需要配置info.plist檔案:
注意:
從2017年1月起所有請求需要時https 的,否則稽核就會被拒!web連線可以是http的,但是也需要配置!
APP資料互通:
通過一下沙盒儲存方法儲存資料和獲取資料!
與app使用相同的方法檔案:
將公共的檔案打包成framework之後,進行相關的配置;
除錯:
選擇不同的專案執行,在相應的專案裡的斷點就會起作用!
本文demo
補充:widget的上線也是需要單獨申請APP ID的 需要配置證書和Provisioning Profiles檔案!
沒有配置相關證書時:
配置證書及描述檔案:(列舉一些)
證書與描述檔案配置好之後:
感謝您的閱讀,希望對您有所幫助!
原文連結:http://www.jianshu.com/p/42516ee26a45
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。
相關文章
- iOS10 CAAnimationDelegate 的簡單適配iOS
- 【CoCollider】讓系統和應用適配如此簡單IDE
- iOS10推送通知適配iOS
- 並查集的簡單應用並查集
- [iOS]適配iOS10問題iOS
- iOS13簡單適配iOS
- iPhoneX簡單適配iPhone
- 應用適配資料庫還是資料庫適配應用資料庫
- iOS10推送適配完整說明iOS
- 極其簡單的Flutter 螢幕適配Flutter
- iPhone X和iOS 11的簡單適配iPhoneiOS
- 食物鏈(並查集的簡單應用)並查集
- Flutter螢幕適配,簡單粗暴的全域性適配方式Flutter
- iOS10 再談 CAAnimationDelegate 相關協議的適配iOS協議
- iOS開發 適配iOS10以及Xcode8iOSXCode
- 網頁適配 iPhoneX,就是這麼簡單網頁iPhone
- websoket的簡單應用Web
- npm的簡單應用NPM
- Widget小元件如何自適應高度元件
- Flutter多平臺適配機制就是這麼簡單Flutter
- Android適配:DP簡述Android
- iOS10適配 完美解決相機、相簿等許可權的使用iOS
- 教你實現華為快應用深色主題適配
- HarmonyOS NEXT應用開發之深色模式適配模式
- H5 頁面適配iPhone X,就是那麼簡單H5iPhone
- jsp的簡單應用JS
- 遞迴的簡單應用遞迴
- rename命令的簡單應用
- Android適配: 拉伸適配的缺點Android
- thymeleaf 簡單應用
- div 簡單應用
- ajax簡單應用
- smbclient 簡單應用client
- 用REM單位進行移動端適配的最佳實現REM
- fir.im Weekly - 關於 iOS10 適配、開發、推送的一切iOS
- iOS12、iOS11、iOS10、iOS9常見適配iOS
- 適配可摺疊裝置,您的應用準備好了嗎?
- 安卓元件化應用的6.0許可權適配優化方案安卓元件化優化