3D-TOUCH实践-学习

3DTouch是啥

这是苹果2015年推出的 IOS9上的一个新特性:在屏幕上增加了一个压力的感触,通过区分轻按和重按来进行不同的用户交互,有Peek/Pop两种新手势.也就是Apple Watch上采用的Force Touch的升级版.

how to start

首先,苹果说:

With Xcode 7.0 you must develop on a device that supports 3D Touch. Simulator in Xcode 7.0 does not support 3D Touch.

也就是 Xcode7可以搞,但是模拟器器不支持.
没关系,N 早就有牛人解决了这个问题.

git地址:https://github.com/DeskConnect/SBShortcutMenuSimulator。

clone

进入Termnial执行

1
2
3
4
5
git clone https://github.com/DeskConnect/SBShortcutMenuSimulator.git
cd SBShortcutMenuSimulator
make

切换模拟器 (电脑上只有 X7的可以跳过这一步)

如果电脑里有多个 Xcode(比如我自己目前有 X6,X7两个版本),则需要先进行Xcode 路径设置,如下:

1
sudo xcode-select -switch /Applications/Xcode2.app/Contents/Developer/

PS:上面命令中,Xcode2.app是你电脑中Xcode的名字,这里如要特别注意,如果名字中有空格,需要修改一下,把空格去掉,否则会影响命令的执行。

执行模拟器翻新(^_^)

之后在SBShortcutMenuSimulator的目录中执行如下操作

1
2
3
xcrun simctl spawn booted launchctl debug system/com.apple.SpringBoard --environment DYLD_INSERT_LIBRARIES=$PWD/SBShortcutMenuSimulator.dylib
xcrun simctl spawn booted launchctl stop com.apple.SpringBoard

测试一下

我们可以通过向指定端口发送消息的方法来在模拟器上模拟3D Touch的效果(此处用的是日历 App, 自己的 App 记得改 BundleID)

PS: 如果失效了,重置模拟器–>重复翻新步骤–> 接着 echo 就好了

1
echo 'com.apple.mobilecal' | nc 127.0.0.1 8000

进行自定义3DTouch相关开发

Quick Actions

staticquick actions

直接在 info.plist 里添加字段即可.

  • UIApplicationShortcutItems,数组key 值
  • 每一个 item 内部如下:

下面的是必选的

  1. UIApplicationShortcutItemTitle - [string],quick actions名称(显示在手机桌面)
  2. UIApplicationShortcutItemType - [string],quick actions类型(开发用)

下面的是可选的

  1. UIApplicationShortcutItemSubtitle - [string],quick actions副标题(显示在上面的标题下)
  2. UIApplicationShortcutItemIconFile - [string],quick actions自定义图标,有尺寸要求,如果设置的话,就忽略UIApplicationShortcutItemIconType选项的内容
  3. UIApplicationShortcutItemIconType - [string],quick actions系统图标类型,有一堆预设的
  4. UIApplicationShortcutItemUserInfo - [array] ,quick actions自定义信息(开发用)

API 介绍如下:

PS:quick actions系统图标的枚举如下.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
typedef enum UIApplicationShortcutIconType : NSInteger {
UIApplicationShortcutIconTypeCompose,
UIApplicationShortcutIconTypePlay,
UIApplicationShortcutIconTypePause,
UIApplicationShortcutIconTypeAdd,
UIApplicationShortcutIconTypeLocation,
UIApplicationShortcutIconTypeSearch,
UIApplicationShortcutIconTypeShare,
//此处截断,上面的9.0+可用,下面的9.1+可用
UIApplicationShortcutIconTypeProhibit,
UIApplicationShortcutIconTypeContact,
UIApplicationShortcutIconTypeHome,
UIApplicationShortcutIconTypeMarkLocation,
UIApplicationShortcutIconTypeFavorite,
UIApplicationShortcutIconTypeLove,
UIApplicationShortcutIconTypeCloud,
UIApplicationShortcutIconTypeInvitation,
UIApplicationShortcutIconTypeConfirmation,
UIApplicationShortcutIconTypeMail,
UIApplicationShortcutIconTypeMessage,
UIApplicationShortcutIconTypeDate,
UIApplicationShortcutIconTypeTime,
UIApplicationShortcutIconTypeCapturePhoto,
UIApplicationShortcutIconTypeCaptureVideo,
UIApplicationShortcutIconTypeTask,
UIApplicationShortcutIconTypeTaskCompleted,
UIApplicationShortcutIconTypeAlarm,
UIApplicationShortcutIconTypeBookmark,
UIApplicationShortcutIconTypeShuffle,
UIApplicationShortcutIconTypeAudio,
UIApplicationShortcutIconTypeUpdate
} UIApplicationShortcutIconType;

设置好以后,直接运行,退回到模拟器桌面,在命令行工具重复 echo 那句代码,可以看到效果

要实现进入 App 后的操作,实现下面方法

1
2
3
4
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler NS_AVAILABLE_IOS(9_0)
{
NSLog(@"%@",shortcutItem);
}

dynamic quick actions

需要在代码里运行代码来添加到桌面上

假设场景为:当用户进入过某页面后,更新3DTouch 中得某一个quick actions

1.下面是生成dynamic quick actions的代码:

1
2
3
4
5
//简单版
UIApplicationShortcutItem *item =[[UIApplicationShortcutItem alloc] initWithType:@"test" localizedTitle:@"你点我试试"];
//复杂版
UIApplicationShortcutItem *item2 = [[UIApplicationShortcutItem alloc] initWithType:@"test2" localizedTitle:@"大哥,我错了,你别点我" localizedSubtitle:@"上有老,下有小..." icon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeLocation] userInfo:nil];

记得添加到quick actions数组

1
[UIApplication sharedApplication].shortcutItems = @[item,item2];

2.注意一个地方,正常启动 App 的时候,launchOptions为 nil, 从3DTouch 启动的时候launchOptions为一个包含有 UIApplicationShortcutItem 对象的字典,我们应在合适的时候,此方法返回 NO 来避免重复调用

1
2
3
4
5
6
7
8
9
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSLog(@"%@",launchOptions);
return YES;
}

3.在 Appdelegate 文件里,实现下面方法来处理通过 qucikActions 进入 App 的情况:
(注意, static quick actions也是这个方法)
(注意2:这个方法会在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions调用完毕之后调用)

1
2
3
4
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler NS_AVAILABLE_IOS(9_0)
{
NSLog(@"%@",shortcutItem);
}

dynamic quick actions的更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//1. 获取当前App 的所有quick actions
NSANSArray *existingShortcutItems = [[UIApplication sharedApplication] shortcutItems];
//2. 获取quick actions数组中某一个
//3. 由于quick actions也分可变/不可变,所以我们要改变的时候,先 mutable 一下
UIMutableApplicationShortcutItem *curItem = [[existingShortcutItems objectAtIndex: 0] mutableCopy];
//4. 更新数据
[curItem setLocalizedTitle: @"你再打我试试!"];
//5. 更新quick actions数组
NSMutableArray *newShortcutItems = [existingShortcutItems mutableCopy];
[newShortcutItems replaceObjectAtIndex:0 withObject:curItem];
[UIApplication sharedApplication].shortcutItems = newShortcutItems;

效果如下

dynamic/staticquick actions区别

  1. staticquick actions:就算程序从没有启动过,也可以正常使用(当然逻辑业务数据需要自己弄)
  2. dynamic quick actions:程序启动过一次以后就配置成功了.以后就可以正常使用了
  3. dynamic/staticquick actions主/副标题最多2行字,超出部分…
  4. dynamic/staticquick actions一共最多4个
  5. staticquick actions排序在dynamic quick actions上

—-分割线,下面的就没办法用模拟器了,必须6S 走起—-

Peek & Pop

peek&pop 是敲击预览

在App 内部,随着用户按压力量的增加,交互会出现三个阶段:

  1. 暗示内容预览是可使用的

  2. 展示预览(peek),和快捷选项菜单(peek quick actions)

  3. 可选的跳转到预览中的视图(pop)

当你使用 peek 和 pop 时,系统通过压力决定从哪个阶段过度至下一个。

说了这么多,其实就是一个字:用力按屏幕!

效果




code

场景:界面 A 有一堆 cell, 用户可以通过 peek&pop 弹出预览视图界面 B,并且有一些自定义选项给用户选择

  1. 界面 A 遵循协议UIViewControllerPreviewingDelegate

  2. 界面 A 实现2个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit {
//显示目前 VC
[self showViewController:viewControllerToCommit sender:self];
}
- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location {
// 从 storyboard 创建的 VC
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
TableSonViewController *previewController = [sb instantiateViewControllerWithIdentifier:@"TableSonViewController"];
//实际显示的预览 view 的尺寸,注意,会从目前 VC 的中心朝四周截取对应的尺寸
previewController.preferredContentSize = CGSizeMake(400,600);
previewingContext.sourceRect = previewController.view.bounds;
return previewController;
}
  1. 上面2个方法,就可以让界面 A 通过强力指压,出现预览页面了.注意,预览页面的数据也在此处进行设置.
  2. 界面 B 如果需要在预览的时候提供自定义按钮,则需要实现一个方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- (NSArray<id<UIPreviewActionItem>> *)previewActionItems{
UIPreviewAction *itemShare = [UIPreviewAction actionWithTitle:@"分享" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"分享" message:@"分享内容" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil];
[alertView show];
}];
UIPreviewAction *itemDelete = [UIPreviewAction actionWithTitle:@"删除" style:UIPreviewActionStyleDestructive handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"删除了");
}];
UIPreviewAction *itemSelect = [UIPreviewAction actionWithTitle:@"选择" style:UIPreviewActionStyleSelected handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"我的选择");
}];
return @[itemShare,itemDelete,itemSelect];
}
  1. 最后一个,当出现预览界面 B 的时候, B 的viewDidLoad方法也会正常执行,销毁的时候dealloc也会执行

have fun


原创文章,转载请注明地址: https://kevinmky.github.io