揭秘 iOS App Extension 开发 —— Today 篇
转自:http://www.cocoachina.com/ios/20160619/16760.html
本文授权转载,作者:Cyandev(简书)
从 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 应用,主程序长这个样:
今日面板插件长这个样:
界面都很简单啦~
主程序实现其实很简单,就是 Table View 的使用以及数据持久化,这里就不着重讲了。但注意,我们要留出一个接口给今日面板,假设这里我们要在今日面板里显示前 4 条待办事项,我们必须要单独将这 4 条存在一个主程序和扩展都能访问的地方。后面我会说怎么做。
Tips:
苹果的 HIG 明确指出,不要在今日面板里使用可以滚动的 Scroll View,而是要完全展开,因此对于多条数据,我们要不就分页,要不就只显示前几项。
下面,我们就为工程创建一个 Today Extension:
一路下一步,输入一个子项目名,点 『Finish』就完成 Today Extension 的添加了。
这个子项目的初始目录结构如下:
P.S. 那个 entitiements 文件是后来创建的,一开始不会有
然后我们在 Storyboard 里把大致界面拖出来,如果画布大小不合适可以在这调整一下,但是也就是调整了预览效果,真实的大小不能在 IB 里修改。
那我们怎么修改视图在今日面板里的大小呢?答案是修改 View Controller 的 preferredContentSize 属性,不理会 width,调整 height 到合适的大小即可,因为宽度总是和屏幕宽度相同的。
在这个例子中,我使用 44 * 项目数量 - 1 来作为视图高度,因为一个标准 Table View Cell 的高度是 44,然后减掉最后一个条目分割线的高度就是我们理想的合适高度。
主程序向 App Extension 共享数据
我们在主程序里创建了待办事项,怎么才能让 App Extension 获取到呢?由于两者代码和数据都不互通,所以我们 可以理所当然的想到用 App Group 来解决。首先在主程序中创建一个 App Group:
然后在 App Extension 里添加这个 App Group 即可。
这样,我们就可以用 NSUserDefaults 通过这个 App Group 交流数据了。
还记得我说过要拿出所有数据的前四条放到今日面板中展示吗?下面我们就来实现这个功能:
当主应用的数据变化后就调用这个方法来更新快照数据。
下面我们主要来看 Today Extension 怎么实现,首先看看这两个方法:
其中第一个方法是系统告诉 Extension 需要更新了,当你更新完毕之后通过 block 回调告诉系统你完成了还有做了什么,通常我们就告诉系统我们更新数据了即可(就是给 block 传 NCUpdateResultNewData 枚举项作为参数)。
其中第二个方法是返回一个内补大小,如果不实现,默认情况视图左侧会有一定的缩进。当然,苹果还是希望你不要修改默认的内补~
然后我们实现数据的读取:
P.S. 第三行写错了,不要管它
其实也很简单,就是从 App Group 的配置里拿出前 4 项的快照,然后更新一下 Table View 即可。这个方法在 viewDidLoad 或者 widgetPerformUpdateWithCompletionHandler: 中调用都可以。
到这我们看看效果,选中 Today Extension 的那个 Scheme 点击调试按钮,弹出下面的对话框:
选择我们的主程序,点击 『Run』。
App Extension 调起主程序并执行动作
当我们的 Todo List 是空的情况下,我们希望在今日面板里展示一个按钮,点击后可以快速进入创建 Todo 的界面,就像这样:
由于我们访问不了主程序的代码,所以只剩下一条路可以选,那就是 URL Scheme。
首先,我们给主程序注册一个 URL Scheme:
然后响应按钮点击:
由于 App Extension 访问不了 UIApplication,因此不能用它的 openURL:,但是我们可以用 extensionContext 来打开 URL,用法和效果是一样的。
回到主程序,我们处理 URL 的打开:
这里我用 Notification 的方式告知指定 View Controller 来执行相应动作,当然你也可以用你自己喜欢的方式,这里最复杂也就是处理路由,现在也有很多方法实现,我这里就不深究了。
下面看看效果(不好意思,图没做好,不动请在新窗口中打开):
好了,到这我们就基本打通主程序和 App Extension 的相互通信了,是不是也很简单呢?
最后,一个小提醒
由于通知中心的界面是一大块 UIVisualEffectView ,并且具体参数调整过,所以插件的背景色最好保持透明,主要文字颜色最好是白色,次要文字的颜色最好是 lightTextColor,这样能适应毛玻璃下的 Vibrancy 效果。
今日面板每个插件的高度计算和 UITableView 自适应高度的计算方式一致,如果你没有设置 preferredContentSize,或者把它设为 CGSizeZero 了,就表示你想采用自适应高度,那么系统就会根据你设计的 Auto Layout 来确定适合的高度。如果你想这么做的话,直接参考 UITableViewCell 在 iOS 8 以后自适应高度的方式即可。
揭秘 iOS App Extension 开发 —— Today 篇的更多相关文章
- 关于报错:'sharedApplication' is unavailable: not available on iOS (App Extension) - Use view controller based
最近在看Extension相关知识的时候,自己写了个小demo 发现[UIApplication sharedApplication]这个方法敲不出来了, 总是报错:'sharedApplicatio ...
- iOS9中找不到XXX.dylib 与 is unavailable no availabel on ios (app extension) - use view controller 的解决办法
在 iOS9 中现在找不到 XXX.dylib 了,比如libz.tbd 如果要用到 libz.dylib,可以用下面的办法,来自 Stack Overflow. Go to Build Phase ...
- iOS - App Extension 整体总结
一.App Extension的介绍 App Extension可以让你扩展你APP的自定义功能和内容,使用户可以在与其他应用或者系统进行互动的时候去使用它.app extension即为本文所说的e ...
- 开发外包注意事项——iOS APP的开发
1. APP外包的流程是怎样的? 一般外包的项目都需要经常这几个流程: 1)需求沟通:双方沟通项目的需求,对项目的可行性进行分析 2)工作量评估:在确认了项目的需求后,外包团队对项目的价钱和进度进行评 ...
- iOS App Extension入门
转自简书:http://www.jianshu.com/p/8cf08db29356 iOS 10推出了很多新功能,其中有几个高调的变化:通知栏更加实用,电话可以防骚扰,iMessage变得更加有 ...
- 开发外包注意事项二——iOS APP的开发
目前我的方式是按时间算. 首先这得建立在双方的信任基础上. 以我做过的Case为例: 首先会和客户一起评估需求: 1. 哪些功能是最为重要的 2. 哪些功能是可以删除的 3. 用什么策略保证APP的出 ...
- 不可或缺 Windows Native (25) - C++: windows app native, android app native, ios app native
[源码下载] 不可或缺 Windows Native (25) - C++: windows app native, android app native, ios app native 作者:web ...
- APP定制开发:APP软件开发的语言和开发环境
APP软件开发是移动互联网开发公司常开发的一种手机应用系统,对于刚刚进入APP软件开发领域的新手来说,选择什么编程语言和需要什么开发环境来开发APP软件是常遇到的问题.下面亿合科技小编来为大家分享下: ...
- 征服恐惧!用 Vim 写 iOS App
我们都知道 Vim 和 Emacs 都是文本编辑器中的上古神器,你也许用 ctags,cscopes 配合 Vim 完成过大型 C 或者 C++ 的开发,你也许配合过其他插件,完成过 JavaScri ...
随机推荐
- 最新JetBrains PyCharm 使用教程--常用快捷键和设置PyCharm为Eclipse快捷键(四)
PyCharm常用快捷键使用 Ctrl + D:复制当前行 Ctrl + Y:删除当前行 Ctrl + Z 撤销 Shift + Enter:快速换行 Ctrl + /:快速注释 Ctrl + F: ...
- 域名解析 | A记录 ,CNAME,MX,NS 你懂了吗
域名解析 | A记录 ,CNAME,MX,NS 你懂了吗 域名解析 什么是域名解析?域名解析就是国际域名或者国内域名以及中文域名等域名申请后做的到IP地址的转换过程.IP地址是网路上标识您站点的数字地 ...
- python入门递归之阶乘
def recurursion(n): if n == 1: return 1 else: return n * recurursion(n-1) number = int(input("请 ...
- Linux中文件的SUID、SGID、Sticky权限说明
1.SUID 首先我们要了解,在Linux中启动一个程序或者启动一个进程是需要有用户的,一个文件的存在是要有用户和组的,一个进程启动后,它的属主取决于进程的发起者,比如 我用root用户启动了一个 c ...
- 苹果客户端input时页面自动放大的问题
一.问题: 最近在用vue测试的时候发现,安卓端在输入框input时不存在页面自动缩放的问题,苹果客户端认为是考虑到用户的体验效果,才出现输入框自动放大的功能.但也收到了不少用户反馈体验效果不周. 二 ...
- [spark程序]统计人口平均年龄(本地文件)(详细过程)
一.题目描述 (1)编写Spark应用程序,该程序可以在本地文件系统中生成一个数据文件peopleage.txt,数据文件包含若干行(比如1000行,或者100万行等等)记录,每行记录只包含两列数据, ...
- 【Java】面向对象之封装
面向对象编程是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改.封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问.要访问该类的数据,必须通过指定的方式 ...
- B0宏
在编译android平台用的ffmpeg时,抛出这样一个错误: 这句代码怎么看都找出有毛病,为什么B0会报错? 翻看aaccoder.c,也没有发现问题.为什么B0就成了一个常量数字,这里只有一个可能 ...
- Long, long ago
Tell me the tales that to me were so dear; 请你给我讲那亲切的故事; Long, long ago; long, long ago.; 多年以前,多年以前; ...
- Spring Boot (一) 校验表单重复提交
一.前言 在某些情况下,由于网速慢,用户操作有误(连续点击两下提交按钮),页面卡顿等原因,可能会出现表单数据重复提交造成数据库保存多条重复数据. 存在如上问题可以交给前端解决,判断多长时间内不能再次点 ...