揭秘 iOS App Extension 开发 —— Today 篇

2023-10-25 04:08

本文主要是介绍揭秘 iOS App Extension 开发 —— Today 篇,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

从 iOS 8 开始,苹果引入了全新的 App Extension,涉及到方方面面,例如今日面板、键盘、内容拦截器、分享动作等。但是官方对于 App Extension 的开发指南少之又少,入门起来会有很多坑。所以我准备写一系列文章来帮助大家更好入门 App Extension 的开发,也能少走弯路。

何为 App Extension?

顾名思义,它是一种扩展,很类似于一些大型软件(好吧,现在可能是个应用都可以有)的插件机制。App Extension 事实上并不是你应用的插件,而是系统的插件,其生命周期是由系统来管理的,所以如果你想做什么坏事还是行不通的...但是 App Extension 分发的载体是应用,也就是说如果你只是单纯想做一个今日面板插件,也需要有个主程序,你的主程序可以什么都不做,也可以提供一些基本的设置和数据。

App Extension 和主程序的关系?

可以说没有什么关系,基本上就是两个独立的程序,你的主程序既不可以访问 App Extension 的代码,也不可以访问其存储空间,这完完全全就是两个进程、两个程序。这时你可能会问,我擦,都不能交互那有什么卵用??别急,后面我会讲到如何做一些交互。

App Extension 可以干什么?不可以干什么?

基本上什么都能干,有人不是在今日面板里把 Chrome 的恐龙小彩蛋硬塞进去了吗?还有拿输入法当浏览器作分屏多任务的...只有你想不到,没有你做不到......诶等等,有些还是做不到的。比如,内存有限制,App Extension 的可用内存远不如常规应用,以至于如果你真想做游戏,还是掂量掂量你的资源占用问题能不能解决吧。而且还不能访问 UIApplication,因为它的容器应用是系统,你拿系统的 UIApplication 想干嘛...(当然,你可以用递归查找 UIResponder 的方法拿到 UIApplication,但是我没试过)再次,你不能执行长时间的操作,你的 App Extension 可能随时被系统 Kill 掉,who knows?

还有更多不可用的 API 可以看这个苹果官方文档:Understand How an App Extension Works

开始创建一个 App Extension

首先看一下我们要做的东西,是一个简单 Todo 应用,主程序长这个样:

1507403-692445a16f16ec2a.jpg

今日面板插件长这个样:

1507403-1a98bf87cabe11b9.jpg

界面都很简单啦~

主程序实现其实很简单,就是 Table View 的使用以及数据持久化,这里就不着重讲了。但注意,我们要留出一个接口给今日面板,假设这里我们要在今日面板里显示前 4 条待办事项,我们必须要单独将这 4 条存在一个主程序和扩展都能访问的地方。后面我会说怎么做。

Tips:

苹果的 HIG 明确指出,不要在今日面板里使用可以滚动的 Scroll View,而是要完全展开,因此对于多条数据,我们要不就分页,要不就只显示前几项。

下面,我们就为工程创建一个 Today Extension:

1507403-47e6801aa91c0c9e.jpg

1507403-91c009370cdb26b4.jpg

一路下一步,输入一个子项目名,点 『Finish』就完成 Today Extension 的添加了。

这个子项目的初始目录结构如下:

1507403-9ca2f0ac67640d31.png

P.S. 那个 entitiements 文件是后来创建的,一开始不会有

然后我们在 Storyboard 里把大致界面拖出来,如果画布大小不合适可以在这调整一下,但是也就是调整了预览效果,真实的大小不能在 IB 里修改。

1507403-6f2835f6439e0ef9.png

那我们怎么修改视图在今日面板里的大小呢?答案是修改 View Controller 的 preferredContentSize 属性,不理会 width,调整 height 到合适的大小即可,因为宽度总是和屏幕宽度相同的。

在这个例子中,我使用 44 * 项目数量 - 1 来作为视图高度,因为一个标准 Table View Cell 的高度是 44,然后减掉最后一个条目分割线的高度就是我们理想的合适高度。

主程序向 App Extension 共享数据

我们在主程序里创建了待办事项,怎么才能让 App Extension 获取到呢?由于两者代码和数据都不互通,所以我们 可以理所当然的想到用 App Group 来解决。首先在主程序中创建一个 App Group:

1507403-c52079b69b3bb7ed.jpg

然后在 App Extension 里添加这个 App Group 即可。

这样,我们就可以用 NSUserDefaults 通过这个 App Group 交流数据了。

还记得我说过要拿出所有数据的前四条放到今日面板中展示吗?下面我们就来实现这个功能:

1466345362730926.png

当主应用的数据变化后就调用这个方法来更新快照数据。

下面我们主要来看 Today Extension 怎么实现,首先看看这两个方法:

1466345382538005.png

其中第一个方法是系统告诉 Extension 需要更新了,当你更新完毕之后通过 block 回调告诉系统你完成了还有做了什么,通常我们就告诉系统我们更新数据了即可(就是给 block 传 NCUpdateResultNewData 枚举项作为参数)。

其中第二个方法是返回一个内补大小,如果不实现,默认情况视图左侧会有一定的缩进。当然,苹果还是希望你不要修改默认的内补~

然后我们实现数据的读取:

1466345404481861.png

P.S. 第三行写错了,不要管它

其实也很简单,就是从 App Group 的配置里拿出前 4 项的快照,然后更新一下 Table View 即可。这个方法在 viewDidLoad 或者 widgetPerformUpdateWithCompletionHandler: 中调用都可以。

到这我们看看效果,选中 Today Extension 的那个 Scheme 点击调试按钮,弹出下面的对话框:

1507403-a09545817417f2c6.png

选择我们的主程序,点击 『Run』。

1507403-7e4a5eaaa42701e7.gif

App Extension 调起主程序并执行动作

当我们的 Todo List 是空的情况下,我们希望在今日面板里展示一个按钮,点击后可以快速进入创建 Todo 的界面,就像这样:

1507403-40af78df3f6c5fcb.jpg

由于我们访问不了主程序的代码,所以只剩下一条路可以选,那就是 URL Scheme。

首先,我们给主程序注册一个 URL Scheme:

1466345550866054.png

然后响应按钮点击:

1466345568482170.png

由于 App Extension 访问不了 UIApplication,因此不能用它的 openURL:,但是我们可以用 extensionContext 来打开 URL,用法和效果是一样的。

回到主程序,我们处理 URL 的打开:

1466345585359717.png

这里我用 Notification 的方式告知指定 View Controller 来执行相应动作,当然你也可以用你自己喜欢的方式,这里最复杂也就是处理路由,现在也有很多方法实现,我这里就不深究了。

下面看看效果(不好意思,图没做好,不动请在新窗口中打开):

1507403-5701ee5d06de795f.gif

好了,到这我们就基本打通主程序和 App Extension 的相互通信了,是不是也很简单呢?

最后,一个小提醒

由于通知中心的界面是一大块 UIVisualEffectView ,并且具体参数调整过,所以插件的背景色最好保持透明,主要文字颜色最好是白色,次要文字的颜色最好是 lightTextColor,这样能适应毛玻璃下的 Vibrancy 效果。

今日面板每个插件的高度计算和 UITableView 自适应高度的计算方式一致,如果你没有设置 preferredContentSize,或者把它设为 CGSizeZero 了,就表示你想采用自适应高度,那么系统就会根据你设计的 Auto Layout 来确定适合的高度。如果你想这么做的话,直接参考 UITableViewCell 在 iOS 8 以后自适应高度的方式即可。

这篇关于揭秘 iOS App Extension 开发 —— Today 篇的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

基于Python开发批量提取Excel图片的小工具

《基于Python开发批量提取Excel图片的小工具》这篇文章主要为大家详细介绍了如何使用Python中的openpyxl库开发一个小工具,可以实现批量提取Excel图片,有需要的小伙伴可以参考一下... 目前有一个需求,就是批量读取当前目录下所有文件夹里的Excel文件,去获取出Excel文件中的图片,并

基于Python开发PDF转PNG的可视化工具

《基于Python开发PDF转PNG的可视化工具》在数字文档处理领域,PDF到图像格式的转换是常见需求,本文介绍如何利用Python的PyMuPDF库和Tkinter框架开发一个带图形界面的PDF转P... 目录一、引言二、功能特性三、技术架构1. 技术栈组成2. 系统架构javascript设计3.效果图

基于Python开发PDF转Doc格式小程序

《基于Python开发PDF转Doc格式小程序》这篇文章主要为大家详细介绍了如何基于Python开发PDF转Doc格式小程序,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用python实现PDF转Doc格式小程序以下是一个使用Python实现PDF转DOC格式的GUI程序,采用T

使用Python开发一个图像标注与OCR识别工具

《使用Python开发一个图像标注与OCR识别工具》:本文主要介绍一个使用Python开发的工具,允许用户在图像上进行矩形标注,使用OCR对标注区域进行文本识别,并将结果保存为Excel文件,感兴... 目录项目简介1. 图像加载与显示2. 矩形标注3. OCR识别4. 标注的保存与加载5. 裁剪与重置图像