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。
iOS 10 widget
點擊“編輯”可是添加其他app的widget。
如何創建widget?
創建一個工程,在該工程裡添加targets:
創建widget
創建成功之後的項目結構:
項目結構
iOS 10和iOS 10之前的界面對比:
iOS 10
iOS 10 之前
搭建簡單的交互界面
文件配置:
系統生成的info.plist文件默認是使用Storyboard 實現的界面;如果你想使用代碼實現是界面的搭建,需更改這個配置文件:
NSExtensionMainStoryboard:MainInterface(你Storyboard的名稱)
NSExtensionPrincipalClass:TodayViewController(你widget控制器的名稱)
NSExtensionAttributes:這是一個描述擴展點具體屬性的字典,就像照片編輯擴展中的PHSupportedMediaTypes一樣。
NSExtensionPrincipalClass:這是擴展模板創建的主體視圖控制器類,比如TodayViewController。當載體應用程序(host app)調用擴展時,擴展點會實例化這個類。
NSExtensionMainStoryboard(只適用於iOS):擴展默認的Storyboard文件,一般名為MainInterface。
注:本文以代碼為例!
方法實現:
界面的搭建( 更新widget視圖:(demo目前只是按鈕 不需要更新) 運行程序: 運行效果圖 因此還需要實現: 注意:該方法在iOS 10之後就被淘汰了! 實現點擊按鈕跳轉: 在按鈕點擊的方法裡實現:(此處小編用的代理) 目前就可以跳轉到app了!當然是四個按鈕,你需要再AppDelegate裡面進行處理: 然後處理相應的通知,判斷url.host點擊的第幾個按鈕! 適配iOS 10: NCWidgetDisplayMode 需要再設置高度之前設置該屬性; 模式改變後會執行下面這個方法: 兩種設計風格: iPhone 7的界面效果 iPhone 6(iOS8.4)的界面效果 擴展: 如果是http請求需要配置info.plist文件: 注意:從2017年1月起所有請求需要時https 的,否則審核就會被拒!web連接可以是http的,但是也需要配置! APP數據互通: 通過一下沙盒存儲方法存儲數據和獲取數據! 與app使用相同的方法文件: 將公共的文件打包成framework之後,進行相關的配置; 調試: 選擇不同的項目運行,在相應的項目裡的斷點就會起作用! 本文demo 補充:widget的上線也是需要單獨申請APP ID的 需要配置證書和Provisioning Profiles文件! ?沒有配置相關證書時: 配置證書及描述文件:(列舉一些)-(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);
}
-(void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {
// NCUpdateResultNewData 新的內容需要重新繪制視圖
// NCUpdateResultNoData 部件不需要更新
// NCUpdateResultFailed 更新過程中發生錯誤
completionHandler(NCUpdateResultNoData);
}
-(UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets{
return UIEdgeInsetsMake(0, 10, 0, 10);
}
配置URL schemes:NSString *urlStr = [NSString stringWithFormat:@"medicalWdget://%li",index];
NSURL *url = [NSURL URLWithString:urlStr];
[self.extensionContext openURL:url completionHandler:^(BOOL success) {
}];
-(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 *)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;
}
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 {
}
證書與描述文件配置好之後: