你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> Widget的簡單應用並適配iOS10

Widget的簡單應用並適配iOS10

編輯:IOS開發基礎

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。

020.png

iOS 10 widget

點擊“編輯”可是添加其他app的widget。

如何創建widget?

  • 創建一個工程,在該工程裡添加targets:

019.png

創建widget

  • 創建成功之後的項目結構:

018.png

項目結構

  • iOS 10和iOS 10之前的界面對比:

017.png

iOS 10

016.png

iOS 10 之前

搭建簡單的交互界面

  • 文件配置:

系統生成的info.plist文件默認是使用Storyboard 實現的界面;如果你想使用代碼實現是界面的搭建,需更改這個配置文件:

015.png

  • NSExtensionMainStoryboard:MainInterface(你Storyboard的名稱)

013.png

  • NSExtensionPrincipalClass:TodayViewController(你widget控制器的名稱)

014.png

NSExtensionAttributes:這是一個描述擴展點具體屬性的字典,就像照片編輯擴展中的PHSupportedMediaTypes一樣。

NSExtensionPrincipalClass:這是擴展模板創建的主體視圖控制器類,比如TodayViewController。當載體應用程序(host app)調用擴展時,擴展點會實例化這個類。

NSExtensionMainStoryboard(只適用於iOS):擴展默認的Storyboard文件,一般名為MainInterface。

注:本文以代碼為例!

方法實現:

界面的搭建(

-(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);
}

運行程序:

012.png

運行效果圖

因此還需要實現:

-(UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets{
  return UIEdgeInsetsMake(0, 10, 0, 10);
}

注意:該方法在iOS 10之後就被淘汰了!

實現點擊按鈕跳轉:
配置URL schemes:

011.png

在按鈕點擊的方法裡實現:(此處小編用的代理)

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 *)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}
  }
}

兩種設計風格:

009.png

iPhone 7的界面效果

010.png

iPhone 6(iOS8.4)的界面效果

擴展:

008.png


注意:有人看到這種界面可能會想到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文件:

007.png

注意:從2017年1月起所有請求需要時https 的,否則審核就會被拒!web連接可以是http的,但是也需要配置!

APP數據互通:

006.png

通過一下沙盒存儲方法存儲數據和獲取數據!

與app使用相同的方法文件:

將公共的文件打包成framework之後,進行相關的配置;

調試:

選擇不同的項目運行,在相應的項目裡的斷點就會起作用!

005.png

本文demo

補充:widget的上線也是需要單獨申請APP ID的 需要配置證書和Provisioning Profiles文件!

?沒有配置相關證書時:

004.png

配置證書及描述文件:(列舉一些)

002.png

003.png


證書與描述文件配置好之後:

001.png

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved