Today Extension(widget)看我就够了

2024-06-17 02:38
文章标签 today extension widget

本文主要是介绍Today Extension(widget)看我就够了,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、介绍
1、app extension、containing app及host app

app extension

extension不能单独存在,必须有一个包含它的containing app,它有一个包含在app bundle中的独立bundle,extension的bundle后缀名是.appex。其生命周期也和普通app不同。

extension需要用户手动激活,不同的extension激活方式也不同。Today中的widget需要在Today中激活和关闭;Custom keyboard需要在设置中进行相关设置;Photo Editing需要在使用照片时在照片管理器中激活或关闭;Storage Provider可以在选择文件时出现;Share和Action可以在任何应用里被激活,但前提是开发者需要设置Activation Rules,以确定extension需要在合适出现。

containing app

extension,不能单独存在,必须依赖主app,主app即containing app, extension会随着containing app的安装/卸载而安装/卸载。

host app

能够调起extension的app被称为host app,比如widget的host app就是Today。

extension和host app之间可以通过extensionContext属性直接通信(该属性是UIViewController类别)实际上extension和host app之间是通过IPC(interprocess communication)实现的。 containing app和host app之间没有任何直接关系,也从来不需要通信。extension和containing app之间的关系最复杂,因为extension依赖与containing app。

2、widget的生命周期

extension是针对某项功能的扩展,不是单独存在的。它的生命周期与app的生命周期的各自独立,为两个进程。

  • 开始:在用户通过host app点击extension时,系统实例化extension,extension的生命周期开始。

  • 执行:extension启动后,执行自己的任务。

  • 消失:任务执行结束或用户通过host app结束任务,又或者系统会将其杀掉,extension的生命周期结束。

    img

二、widget原理
1、widget和containing app
  • widget通过openURL的方式启动containing app

  • 数据交互,使用使用NSUserDefaults或者NSFileManager

    img

2、widget刷新机制

由于,系统会自动保存widget的快照,直到新的数据或UI刷新。短时间内重复展示widget页面,widget的执行路径直接只会执行viewWillAppear方法。而在第一次下拉或超过2s再显示widget页面时,widget的执行路径是viewDidLoad->viewWillAppear

3、widget和app共享资源
  • 共享数据

    开启App Groups, 然后使用 app groups来实现二者共享。开启后 NSUserDefaults 或者 NSFileManager 利用 App Groups 共享数据

  • 代码共享

    (1)在Build Phases下的Compile Sources中添加需要的文件,注意添加想要使用的.m文件的同时,也需要添加该文件中引入的类的.m文件,适用于共用代码少的情况

    (2)创建framework。可参考博文中framework创建部分、Sharing Code with an Embedded Framework

三、遇到的问题及解决方案
1、在widget中,右上方的展开、折叠具体实现

在NSExtensionContext中,新添了widgetLargestAvailableDisplayMode属性,来确认当前widget是展开还是折叠状态。所以,先在viewWillAppear中设置widget的mode为展开。
self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;
    然后,就是展开和折叠的处理了。在NCWidgetProviding协议中,新添了这么个方法

-(void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize 设置不同模式下的widget展现内容的高度。

2、widget处于折叠状态时,然后系统2s刷新后,第一次点击展开失效

这个问题是preferredContentSize的设置问题,确认widget的mode之前,谨慎设置这个值。之后,在点击展开、折叠按钮修改了mode之后,一定要设置对应model的preferredContentSize

3、界面的UI的更新要在主线程操作

dispatch_async(dispatch_get_main_queue(), ^{ //...........; });

4、widget和app共用数据

使用NSUserDefaults或者NSFileManager(ios7,NSFileManager提供了containerURLForSecurityApplicationGroupIdentifier方法,可实现app groups共享数据)

5、widget横竖屏兼容

widget默认为竖屏,但我们不能安照app内处理横竖屏的适配方式来处理widget的横竖屏适配。我们可以使用下面的方式来处理横竖屏的问题。之后根据全局属性isLandscape来判读是否为横屏,然后设置横竖屏的UI布局

//横屏/竖屏重新布局
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{CGSize  screenSize = [UIScreen mainScreen].bounds.size;if (screenSize.width > screenSize.height) {self.isLandscape = YES;}else{self.isLandscape = NO;}
}

也可以在- (void)viewWillLayoutSubviews或者- (void)viewDidLayoutSubviews方法中判断是否为横屏(这两个方法都是viewWillAppear方法必然执行的)

6、containing app能够控制extension的出现和隐藏

如果隐藏extension,用户在Today的展示页面看不到隐藏的extension,但是在编辑设置页面可以看到extension还是存在的,这样容易给用户错觉。

//让隐藏的插件重新显示 
-(void)showTodayExtension 
{ [[NCWidgetController widgetController] setHasContent:YES forWidgetWithBundleIdentifier:@"com.app.extension"]; 
} //隐藏插件 
-(void)hiddeTodayExtension 
{ [[NCWidgetController widgetController] setHasContent:NO forWidgetWithBundleIdentifier:@"com.app.extension"]; 
}

注意:

  • 调用隐藏方法之后,需要调用展示方法才可以再次展示该extension

  • 该方法在App Extension和Containing App中都可以调用,需要导入<NotificationCenter/NotificationCenter.h>头文件。

7、widget不显示

检查下 widget 的 Deployment Target 是不是小于等于你的真机版本

8、设置extension的名字

在extension target下的info.plist下设置

9、3DTouch效果增加widget,在app图标上touch之后展示一个widget

在app 的 info.plist 文件中增加一组key-value,即Home Screen Widget–widget的bundleID

10、天气、新闻类app,当数据发生改变需要及时更改widget页面,展示最新数据。

我们首先想到的是使用 Timer 来实现,根据与后台协商好的时间,定时获取数据更新widget那么我们在什么时机下触发、销毁timer,由于widget 中controller 特殊的生命周期,为了适应用户不同的操作,我们在控制器的viewWillAppear方法中出发timer,在viewDidDisappear方法销毁timer。

11、国际化
  • widget名字的国际化:New file选择Strings file,然后更名为InfoPlist,生成InfoPlist.strings文件后点击右边中Localize…,在弹窗中选择自己支持的多语言即可;在生成的多语言文件中写app的名称

    CFBundleDisplayName = “简体”/“繁體”/“English”

  • widget内容多语言:New file选择Strings file,然后更名为Localizable,生成Localizable.strings文件后点击右边中Localize…,在弹窗中选择自己支持的多语言即可;在生成的多语言文件中写支持的多语言即可。

12 widget隐藏

​ NCWidgetController *widgetController = [NCWidgetController widgetController];

​ [widgetController setHasContent:NO forWidgetWithBundleIdentifier:WB_BUNDLE_ID_FOR_HOTWEIBO_WIDGET_STRING];

添加这行代码后,在app第一次运行的时候,widget会隐藏,但是在设置页面还会有,但是即使再移除、在添加,在today extension界面也不会显示该widget。

扩展
1、如果Container app数据发生改变需要Extension马上更新应该怎样操作?
  • 方案研究如下

(1)NSNotificationCenter 仅在 app 内部起作用,在 apps 之间不起作用。

(2) UserDefaults(KVO)的方式是在main app 与 extension 之间起作用,apps之间无用。

(3)使用 NSFileCoordinator 和 NSFilePresenter 实现,虽可实现但有点复杂。

(4)使用 CFNotificationCenterGetDarwinNotifyCenter 实现。

  • 原理

    CFNotificationCenterGetDarwinNotifyCenter 是 core foundation中系统级别的通知,使用它需要用到Toll-Bridge的知识与CoreFoundation相关的类进行桥接。

参考链接

  • MMWormhole第三方库,用于Container app 与 entension 之间传递数据信息

  • CFNotificationCenterGetDarwinNotifyCenter使用方法

  • App与Extensions间通信共享数据

参考

Entitlement Key Reference

App Extension Programming Guide(Today Extension)

这篇关于Today Extension(widget)看我就够了的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1068259

相关文章

Android 10.0 系统开机重启桌面时钟小部件widget加载慢解决方案

1.前言 在10.0的系统rom产品定制化开发中,在Launcher3桌面系统默认会有时钟widget小部件显示在首屏的,但是发现在开机过程 中会显示的好慢,等进入桌面了 还没显示,所以接下来分析下相关的源码流程,来实现相应的功能 2.系统开机重启桌面时钟小部件widget加载慢解决方案的核心类 frameworks\base\services\appwidget\java\com\andr

Flutter原理—深入Widget原理

事实上在 Flutter 中渲染是经历了从 Widget 到 Element 再到 RenderObject 的过程。 Widget 只是 Element 的一个配置描述 ,告诉 Element 这个实例如何去渲染。 Widget 和 Element 之间是一对多的关系 。实际上渲染树是由 Element 实例的节点构成的树,而作为配置文件的 Widget 可能被复用到树的多个部分,对应产

ARM-V9 RME(Realm Management Extension)系统架构之系统初始化流程

安全之安全(security²)博客目录导读 目录 一、重置取消 二、应用处理单元(PE)初始启动 三、MSD初始化 四、GPT初始化 五、初始启动退出(由所有应用PE执行) 六、RMSD初始化 七、PE进入丢失上下文的低功耗状态 本博客提供了RME系统初始化流程的示例,并描述了系统组件之间的关系以及系统启动序列的相应安全注意事项,不包括有关安全启动序列或软件测量流程的具体细

【Rust项目推荐】Rust search extension 0.7发布!地址栏快速搜索Rust文档、crates的浏览器插件...

大家好, Rust Search Extension是我从2018年开始开发的浏览器插件,方便大家在浏览器地址栏快速搜索官方文档、内置属性、crates和错误码。目前发布了v0.7版! 目前在Reddit上获得了将近200个赞,欢迎大家下载体验。 Reddit帖子:Announcing rust-search-extension v0.7! Search std docs, crates, e

【Rus项目推荐】Rust search extension 0.8发布!快速搜索Rust文档、属性和库的浏览器插件...

Rust Search Extension 是一款可以在地址栏快速搜索Rust文档、crates、内置属性和错误码等的浏览器插件,支持Chrome和Firefox,希望能给每一个Rust开发者带来便利和效率提升。 之前的文章 介绍了0.7版的功能,这篇文章我讲介绍一下Rust Search Extension这一版的新功能: 支持实时搜索top 20K的官方crates支持实时搜索Rust官方书

Rust Search Extension两周年,发布1.0版!

大家好, Rust Search Extension是我从2018年开始开发的浏览器插件,方便Rust开发者在浏览器地址栏快速搜索官方文档、内置属性、crates和错误码等。经过两年多的时间,迭代了12个版本,终于是时候可以发布1.0版了!???????? 这是截止到目前Rust Search Extension取得的一些成绩: 迭代12个版本382个star542个commit5个contri

Eclipse报错:An internal error has occurred. Widget is disposed

在使用Eclipse编写JavaWeb项目时,突然遇到了这样一个error: An internal error has occurred.Widget is disposed 之前Eclipse用的好好的,这个问题出现的甚是突然。采用以下方法后解决了这个问题,现在记录以下。 右键Eclipse的快捷方式,在兼容性窗口的兼容模式中,将“以兼容模式运行这个程序”选项打对勾,如下图

ARM-V9 RME(Realm Management Extension)系统架构之系统启动

本节描述了初始化RME系统的要求。 目录 一、复位需求 二、RME禁用 一、复位需求 RME系统重置(即复位)是指重置整个系统的全局功能状态的任何系统事件。 RME系统重置包括处理单元(PEs)、处理单元集群(PE-clusters)、系统核心逻辑和辅助逻辑、所有系统总线以及所有系统外围设备的重置。 从MSD的角度来看,RME系统重置事件被视为逻辑上相当于对平台进行电源循环(po

Error Loading extension section usr_cert

在用easy_rsa生成ovpn配置时,出现如下错误: [ root: /usr/share/easy-rsa] #/usr/share/easy-rsa/build-key --batch zzzz.29761Using Common Name: zzzz.29761Generating a 2048 bit RSA private key...............+++.....

AI播客下载:AI Today(今日AI)

AI Today播客的背后公司是Cognilytica ,这家公式专注于为组织和专业人士提供人工智能、机器学习、自动化、数据和分析的最佳实践研究、培训和认证。自2018年以来,Cognilytica 的旗舰产品 CPMAI™ 人工智能和机器学习项目管理培训和认证已被全球各种规模的组织采纳。Cognilytica 通过最佳实践方法和管理方法,提高了组织和个人实施新兴技术成功率。 AI To