zoukankan      html  css  js  c++  java
  • iOS

    1、Widget

    • iOS extension 的出现,方便了用户查看应用的服务,比如用户可以在 Today 的 widgets 中查看应用的简略信息,然后点击进入相关的应用界面。

      Widget1 Widget2

    2、添加 Widget

    • 添加 Widget 流程

      • 1、添加 Today Extension
      • 2、绘制 UI
      • 3、调起 app
      • 4 、数据共享

    2.1 添加 Today Extension

    • 在 Xcode菜单 => File => New => Target.. => 中选择 Today Extension

      Widget3

      Widget4

      Widget5

    2.2 绘制 UI

    • 创建 Today Extension 时会默认创建 MainInterface.storyboard,可以在里面绘制显示的 Widget 内容,也可以使用代码绘制 UI。

      Widget6

    • 设置 Widget 展示视图的大小。关于 Widget 的背景色,以及具体展示的内容大家按需绘制。

      	- (void)viewDidLoad {
      		[super viewDidLoad];
      		    
      		// 设置 Widget 展示视图的大小
      		self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 100);
      		
      		self.view.backgroundColor = [UIColor yellowColor];
      	}
      
    • 在 iOS8 - iOS9 中运行程序后,会发现一个问题:绘制的内容与左侧边界有一定距离(约 30px)。如何解决这个问题呢,NCWidgetProviding 协议给出了解决方案。iOS10 中不存在这个问题。

      	// 实现 NCWidgetProviding 协议方法
      	- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets {
      		return UIEdgeInsetsMake(0, 0, 0, 0);
      	}
      

    2.3 调起 app

    • 因为 extension 和 containing app 是两个完全独立的进程,所以它们之间不能直接通信(不能像应用内部点击按钮,跳转到指定页面)。为了实现 Widget 调起 app,这里通过 openURL 的方式来启动 containing app。

    • 在 containing app 中设置 URL Schemes

      Widget9

    • 在 extension 的 ViewController 中添加如下代码。

      	// 通过 extensionContext 借助 host app 调起 app
      	    
      	// TodayWidget 为在 containing app 中设置的 URL Schemes
      	[self.extensionContext openURL:[NSURL URLWithString:@"TodayWidget://"] completionHandler:^(BOOL success) {
      	    
      		NSLog(@"open url result:%d", success);
      	}];
      

    2.4 数据共享

    • 通过 App Groups 提供的同一 group 内 app 共同读写区域,可以用 NSUserDefaults 和 NSFileManager 两种方式实现 extension 和 containing app 之间的数据共享。

      Widget7

      Widget8

      1. 通过 NSUserDefaults 共享数据
      • 保存数据

        	- (void)saveDataByNSUserDefaults {
        	
        		NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.qianqianstudio.freeInHouse"];
        		[shared setObject:@"asdfasdf" forKey:@"widget"]; 
        		[shared synchronize];
        	}
        
      • 读取数据

        	- (NSString *)readDataFromNSUserDefaults { 
        	
        		NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.qianqianstudio.freeInHouse"]; 
        		NSString *value = [shared valueForKey:@"widget"]; 
        		return value;
        	}
        
      1. 通过 NSFileManager 共享数据
      • 保存数据

        	- (BOOL)saveDataByNSFileManager {
        	
        		NSError * error = nil;
        		
        		NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.qianqianstudio.freeInHouse"]; 
        		containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/widget"]; 
        		NSString *value = @"asdfasdfasf"; 
        		BOOL result = [value writeToURL:containerURL atomically:YES encoding:NSUTF8StringEncoding error:&error];
        		
        		if (!result) { 
        			NSLog(@"%@", error); 
        		} else { 
        			NSLog(@"save value:%@ success.", value); 
        		} 
        		
        		return result;
        	}
        
      • 读取数据

        	- (NSString *)readDataByNSFileManager {
        	
        		NSError *error = nil;
        		
        		NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.qianqianstudio.freeInHouse"];
        		containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/widget"];
        		NSString *value = [NSString stringWithContentsOfURL:containerURL encoding:NSUTF8StringEncoding error:& error];
        		
        		return value;
        	}
        

    3、设置 Widget

    • 1、Widget 中展开、折叠

      • iOS10 在 NSExtensionContext 中,新添了 widgetLargestAvailableDisplayMode 属性,来确认当前 Widget 是展开还是折叠状态。所以,先在 viewWillAppear 中设置 Widget 的 mode 为展开。

        	- (void)viewWillAppear:(BOOL)animated {
        		[super viewWillAppear:animated];
        		
        		self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;
        	}
        
      • 然后,就是展开和折叠的处理了。在 NCWidgetProviding 协议中,新添了这个方法 widgetActiveDisplayModeDidChange。

        	- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize {
        	
        		if (activeDisplayMode == NCWidgetDisplayModeCompact) {
        			self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 110);
        		} else {
        			self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 300);
        		}
        	}
        
    • 2、启动 app 后,第一次显示的是折叠,而不是展开 ?

      • 这个问题,归咎于 preferredContentSize 的设置,确认 Widget 的 mode 之前,不要设置这个值。在 widgetActiveDisplayModeDidChange 中设置展开或折叠状态下 Widget 的高度,iOS10 环境下在这里设置高度也就足够了。
    • 3、为什么有时展开或折叠 "失灵" 了,没有对应的展开或折叠呢 ?

      • 这个问题的前提,肯定是你展开、折叠对应的 Widget 高度不一样,只是看到了右上角按钮内容改变,但高度却没有变。
      • 这个问题的原因在于,点击展开、折叠按钮修改了 Widget 的 mode 之后,却没有设置对应的高度 preferredContentSize。怎么办呢?mode 改变后,设置对应状态下的高度即可。

    4、真机调试 Widget

    • 真机调试 Widget,牵扯到配置 group。首先我们的宿主 app id 为 com.qianqianstudio.TodayWidget, Today widget 插件的 bundle id 为 com.qianqianstudio.TodayWidget.Widget 这里我们需要注意,widget 的 bundle id 必须以宿主 bundle id 作为前缀。然后它俩之间建立的 group id 为 group.qianqianstudio.freeInHouse(可以取任意名)。

    • 开发者证书配置

      • Identifiers => App Groups 里添加一个 app group id 为:group.qianqianstudio.freeInHouse

        Widget10

      • 创建 app id。创建的时候选择 Explict App ID,App Services 里面勾选上 App Groups

        Widget11

      • 主 app

        Widget12

      • widget

        Widget13

      • 配置 provisioning profile(这里不再赘述 certificate 的生成步骤,添加 device 等),此时因为选择了勾选了 App Groups 这个 service 的 app id,所以可以看到 enabled services 那里有此项。

        Widget14

  • 相关阅读:
    【设计】概要设计-详细设计-到底需要输出什么???
    【Java】Eclipse代码格式化-代码模板
    【Scala】Scala学习资料
    【Java】阿里巴巴Java开发手册(纪念版)
    【Storm】学习笔记
    【HBase】学习笔记
    【Hadoop】Combiner的本质是迷你的reducer,不能随意使用
    【Hadoop】mapreduce采用多进程与spark采用多线程比较
    【ES】elasticsearch学习笔记
    【MySQL】MySQL统计NULL字段处理
  • 原文地址:https://www.cnblogs.com/QianChia/p/6232054.html
Copyright © 2011-2022 走看看