浅谈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;
最后我们来看一下效果:
看上去是不是非常和谐?其实我告诉你,我们已经踩到了坑里了
我在运行中发现:
NSArray *existingItems = [UIApplication sharedApplication].shortcutItems;
所获得的existingItems并不是我们之前设置在info.plist里面的,而是上一次
[UIApplication sharedApplication].shortcutItems = updatedItems;
赋值给他的,又因为我自作聪明的做了一次
NSArray *updatedItems = [existingItems arrayByAddingObjectsFromArray:items];
所以我们每运行一次,shortcutItems中的元素个数就会多3个,
那为什么展示出来没有问题呢?
仔细看刚刚发的那张效果图,我擦,只有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。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Android单元测试初探
Android下有很多单元测试的框架,这里简单介绍一下我最近使用的两个,android SDK自带的单元测试框架和Robolectric。 ###AndroidTestCase AndroidTestCase使用JUnit框架进行单元测试,首先需要在gradle中进入依赖 testCompile 'junit:junit:4.12' androidTestCompile 'com.android.support.test:runner:0.4' 这里一定要引入com.android.support.test:runner。然后在gradle中配置AndroidJUnitRunner defaultConfig { minSdkVersion 14 targetSdkVersion Integer.parseInt(System.properties['compileSdkVersion']) versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUni...
- 下一篇
解耦神器 —— 统跳协议和Rewrite引擎
题记:天猫App长大了,已经长成了流量以千万计规模的App,当下至少有10个团队在直接维护天猫App。在App长大,团队扩充的过程中解耦是一个永恒的话题,而界面解耦又是App架构的重中之重。 统跳协议是天猫App统一跳转协议,主要负责天猫App界面之间的串联,也就是界面跳转服务。Rewrite引擎是与之配合的一套URL重写引擎,可以通过配置实现重写规则动态化。 历史上的今天 统跳协议的前身是一套叫做internal的协议,internal要重点解决的问题是在WebView和推送通知中如何跳转到指定的界面,进一步在任何动态场景下如何跳转到指定界面。在这样的思路下,internal中定义了多种协议格式,如:tmall://tmallclient/?{"action":""}internal:url=link:url=tmall://mobile.tmall.com/page/ 几乎每一种场景都有一种格式的协议与之对应。在具体操作过程中这些协议都以URL表现出来。不难看出,这套协议最大的问题在于协议格式异构化严重,且不符合W3C的URL标准。随着App规模的扩大,场景日趋复杂,界面越来越多,...
相关文章
文章评论
共有0条评论来说两句吧...