浅谈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

目录
相关文章
|
9天前
|
安全 PHP
文件上传--Upload-labs--Pass19--move_upload_file()函数特性
文件上传--Upload-labs--Pass19--move_upload_file()函数特性
|
Android开发
【错误记录】Android 可执行权限报错 ( Cannot run program “/data/user/0/cn.e/ffmpeg“: error=13,Permission denied )
【错误记录】Android 可执行权限报错 ( Cannot run program “/data/user/0/cn.e/ffmpeg“: error=13,Permission denied )
1636 0
【错误记录】Android 可执行权限报错 ( Cannot run program “/data/user/0/cn.e/ffmpeg“: error=13,Permission denied )
|
9月前
UE Select File / Folder Window 插件说明
UE Select File / Folder Window 插件说明
75 0
|
11月前
|
jenkins 持续交付 iOS开发
iOS Jenkins打包报错The stickers icon set or app icon set named "AppIcon" did not have any applicable ...
iOS Jenkins打包报错The stickers icon set or app icon set named "AppIcon" did not have any applicable ...
204 0
编译mate-control-center:error: required directory ./help does not exist
编译mate-control-center:error: required directory ./help does not exist
81 0
|
开发工具 Android开发
Appium问题解决方案(7)- Could not find 'adb.exe' in PATH. Please set the ANDROID_HOME environment variable with the Android SDK root directory path
Appium问题解决方案(7)- Could not find 'adb.exe' in PATH. Please set the ANDROID_HOME environment variable with the Android SDK root directory path
439 0
Appium问题解决方案(7)- Could not find 'adb.exe' in PATH. Please set the ANDROID_HOME environment variable with the Android SDK root directory path
Access context of data source and work center view do not match
这个错误消息提示我们,data source的access context和待分配到工作中心的access context必须匹配:
Access context of data source and work center view do not match
|
Web App开发
How to find root cause of creation navigation failur
Created by Jerry Wang, last modified on Dec 09, 2014
108 0
How to find root cause of creation navigation failur