开发者社区> 振威> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

浅谈3D Touch(1) -- Home screen quick action

简介:
+关注继续查看

1. 背景:

随着iOS9 和 iPhone 6s的普及,苹果官方提供的3D Touch将带给我们更好玩,更便捷的操作习惯,桌面快捷菜单可谓是3D Touch功能中最实用的一个,有了它,用户不再需要进入app后做额外的操作,便能快速进入指定的页面。

2. 前期工作:

由于手头“并(wo)没(xiang)有(yao)”iPhone 6s 的设备,很多人说,那我怎么开发这个功能呢?不怕,github上早有大神写好了模拟器的解决方案。按照这个文档上的方法依次执行,你的模拟器也能唤出快捷菜单。

3. 正式接入

①.创建UIApplicationShortcutItem

我们先来看一下每个UIApplicationShortcutItem中能够包含哪些信息

key Description required
UIApplicationShortcutItemType 事件的唯一标识,可以通过这个标识来辨别你具体点击了哪个事件 Y
UIApplicationShortcutItemTitle 标题,在没有子标题的情况下如果标题太长能自动换行 Y
UIApplicationShortcutItemSubtitle 子标题,在标题的下方 N
UIApplicationShortcutItemIconType 枚举选取系统中的一个图标类型 N
UIApplicationShortcutItemIconFile 自定义一个图标,以单一颜色35x35的大小展示,如果设置这个,UIApplicationShortcutItemIconType将不起作用 N
UIApplicationShortcutItemUserInfo 字典,里面可以添加各种key、value对 N

UIApplicationShortcutItem 的创建有2种方式

  • 第一种是在info.plist里面静态添加:
<key>UIApplicationShortcutItems</key>
<array>
	<dict>
		<key>UIApplicationShortcutItemType</key>
		<string>3dtouch.homePage</string>
		<key>UIApplicationShortcutItemTitle</key>
		<string>首页</string>
		<key>UIApplicationShortcutItemSubtitle</key>
		<string>这是首页</string>
		<key>UIApplicationShortcutItemIconFile</key>
		<string>shouye.png</string>
		<key>UIApplicationShortcutItemUserInfo</key>
		<dict>
			<key>url</key>
			<string>index</string>
		</dict>
	</dict>
	<dict>
		<key>UIApplicationShortcutItemType</key>
		<string>3dtouch.guanzhupage</string>
		<key>UIApplicationShortcutItemTitle</key>
		<string>关注</string>
		<key>UIApplicationShortcutItemSubtitle</key>
		<string>这是关注</string>
		<key>UIApplicationShortcutItemIconFile</key>
		<string>guanzhu.png</string>
		<key>UIApplicationShortcutItemUserInfo</key>
		<dict>
			<key>url</key>
			<string>guanzhu</string>
		</dict>
	</dict>
</array>
  • 第二种是在程序初始化的时候用代码动态添加:

我们先看一下UIApplicationShortcutItem.h,发现它的使用非常简单,习惯完全符合官方API固有方式,而且和之前那种方式所构建的包含的信息是一一对应的,其中有3个@interface分别是:

  • UIApplicationShortcutIcon
  • UIApplicationShortcutItem
  • UIMutableApplicationShortcutItem
//创建快捷item的icon 即UIApplicationShortcutItemIconFile
UIApplicationShortcutIcon *icon1 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"money"];

UIApplicationShortcutIcon *icon2 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"gouwuche"];

UIApplicationShortcutIcon *icon3 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"wode"];
    
//创建快捷item的userinfo 即UIApplicationShortcutItemUserInfo
NSDictionary *info1 = @{@"url":@"money"};
NSDictionary *info2 = @{@"url":@"gouWuche"};
NSDictionary *info3 = @{@"url":@"wode"};
    
//创建ShortcutItem
UIMutableApplicationShortcutItem *item1 = [[UIMutableApplicationShortcutItem alloc]initWithType:@"3dtouch.moneyPage" localizedTitle:@"资产" localizedSubtitle:@"这是资产" icon:icon1 userInfo:info1];

UIMutableApplicationShortcutItem *item2 = [[UIMutableApplicationShortcutItem alloc]initWithType:@"3dtouch.shopPage" localizedTitle:@"购物车" localizedSubtitle:@"这是购物车" icon:icon2 userInfo:info2];

UIMutableApplicationShortcutItem *item3 = [[UIMutableApplicationShortcutItem alloc]initWithType:@"3dtouch.mypage" localizedTitle:@"我的" localizedSubtitle:@"这是我的" icon:icon3 userInfo:info3];
    
//把原有的shortcutItems拿出来,把动态的放进去
NSArray *items = @[item1, item2, item3];

NSArray *existingItems = [UIApplication sharedApplication].shortcutItems;

NSArray *updatedItems = [existingItems arrayByAddingObjectsFromArray:items];
    
//塞回去
[UIApplication sharedApplication].shortcutItems = updatedItems;

最后我们来看一下效果:

图3

看上去是不是非常和谐?其实我告诉你,我们已经踩到了坑里了

我在运行中发现:

NSArray *existingItems = [UIApplication sharedApplication].shortcutItems;

所获得的existingItems并不是我们之前设置在info.plist里面的,而是上一次

[UIApplication sharedApplication].shortcutItems = updatedItems;

赋值给他的,又因为我自作聪明的做了一次

NSArray *updatedItems = [existingItems arrayByAddingObjectsFromArray:items];

所以我们每运行一次,shortcutItems中的元素个数就会多3个,

图4

那为什么展示出来没有问题呢?

仔细看刚刚发的那张效果图,我擦,只有4个,对了,这个就是表象上不出错的原因,在API上并没有写shortcutItems有任何个数限制,也没有写快捷窗口的个数,但是实际上,最多只能显示4个,而且shortcutItems这个里面的对象恐怕是早已被系统默默的存到了某个plist里了,每当程序启动时,会向系统要app的Bundle Identifier对应的shortcutItems,并非我们事先想要的info.plist中的items,当然以上只是我从现象做出的合理猜测,我们并不需要关心info.plist中的那些静态item,只需要动态创建的item直接打包赋值过去

[UIApplication sharedApplication].shortcutItems = @[item1, item2, item3];

至于只展示4个的问题,这个我们无能为力了,系统做了限制。

②.Item点击回调

当app在后台的时候UIApplication提供了一个回调方法

- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler NS_AVAILABLE_IOS(9_0);

我们依据这个回调中的shortcutItem的type和userinfo来做出不同的事件处理,而最后的completionHandler在API的说明中我们看到当应用并非在后台,而是直接重新开进程的时候,直接返回No,那么这个时候,我们的回调会放在

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

UIApplication又给我们一个从launchOptions中获取这个shortcutItem的key–UIApplicationLaunchOptionsShortcutItemKey,所以在这2个都进行对shortcutItem的操作后,我们这个功能算是完成了

在didFinishLaunchingWithOptions中,由于某些客户端会有启动动画,所以这边加了3秒,具体因程序而异

UIApplicationShortcutItem *item = [launchOptions valueForKey:UIApplicationLaunchOptionsShortcutItemKey];
__weak typeof(self) weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
	__strong typeof(weakSelf) strongSelf = weakSelf;
	if (strongSelf)
   	{
   		[strongSelf actionWithShortcutItem:item];
   	}
});

在performActionForShortcutItem回调中

- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler
{
    if (shortcutItem)
    {
        [self actionWithShortcutItem:shortcutItem];
    }
    
    if (completionHandler)
    {
        completionHandler(YES);
    }
}

最后就是统一处理actionWithShortcutItem的地方,由于我这个demo中所有的type对应的行为都一样的,所以我这边没有对type做区分,甚至所以的item可以用同一个type

-(void)actionWithShortcutItem:(UIApplicationShortcutItem *)item
{
    if (item.userInfo)
    {
        NSLog(@"%@",item.userInfo[@"url"]);
    }
}

好了,3D Touch的第一个功能就介绍到这里 Demo

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Command "python setup.py egg_info" failed with error code 1
Command "python setup.py egg_info" failed with error code 1
9 0
Command "python setup.py egg_info" failed with error code 1
Command "python setup.py egg_info" failed with error code 1
47 0
实现Chrome Devtools调试JavaScript V8引擎
最近开发小程序JavaScript的运行时,通过在客户端嵌入JavaScript V8引擎来实现。前端同学需要调试JavaScript代码,正好Chrome浏览器的Devtools是与V8的Inspector调试协议是一脉相承的,理论上是可以使用Chrome Devtools调试JavaScript V8引擎。 [V8的文档](https://github.com/v8/v8/wiki/De
3196 0
Java并发编程 -- AQS入门&实现可重入锁
Java并发编程 -- AQS可能会看的一脸懵逼,今天实战一个项目练手AQS MyAQSLock.java /** * Created by Fant.
1110 0
PgSQL · 实战经验 · 旋转门压缩算法在PostgreSQL中的实现
背景 在物联网、监控、传感器、金融等应用领域,数据在时间维度上流式的产生,而且数据量非常庞大。 例如我们经常看到的性能监控视图,就是很多点在时间维度上描绘的曲线。 又比如金融行业的走势数据等等。 我们想象一下,如果每个传感器或指标每100毫秒产生1个点,一天就是864000个点。 而传感器或指标是非常多的,例如有100万个传感器或指标,一天的量就接近一亿的量。 假设我们要描绘一个时间
2087 0
ActiveMQ第三弹:在Spring中使用内置的Message Broker
在上个例子中我们演示了如何使用Spring JMS来向ActiveMQ发送消息和接收消息。但是这个例子需要先从控制台使用ActiveMQ提供的命令行功能启动一个Message Broker,然后才能运行示例。
813 0
如何用Javascript捕获ActiveX对象的事件
最近参与了一个项目,我的同事在开发一个ActiveX对象,我帮他编写JS脚本来调用这个对象,其中碰到蛮多问题,最难的就是如何响应由ActiveX对象返回的对象事件。正好,现在一起总结一下。    首先,我来介绍一下COM组件,以便说明js如何响应      COM组件         方法:    ...
910 0
巧用WinRAR+Javascript解决activeX的自动安装问题
先纠正一个观点,所谓自动安装并非强制安装,否则就变成流氓软件了,就算是silverlight,flash这类知名ActiveX,用户也有选择安装或是不安装的权利。 较正统的解决办法是提示用户设置IE权限,然后在object里加入codebase='ocx的下载路径',然后制作数字证书,个人觉得这样比较复杂。
822 0
+关注
11
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载