一、屏幕图标使用3D Touch创建快速进入入口:
1、与之相关的类:
(1)、 UIApplicationShortcutIcon:快捷方式的图标
-
+ (instancetype)iconWithType:(UIApplicationShortcutIconType)type;
:使用系统图标创建对象。
typedef NS_ENUM(NSInteger, UIApplicationShortcutIconType) {
UIApplicationShortcutIconTypeCompose,
UIApplicationShortcutIconTypePlay,
UIApplicationShortcutIconTypePause,
UIApplicationShortcutIconTypeAdd,
UIApplicationShortcutIconTypeLocation,
UIApplicationShortcutIconTypeSearch,
UIApplicationShortcutIconTypeShare,
// pragma -------------------- 以下类型只能在9.1及以上系统使用
UIApplicationShortcutIconTypeProhibit,
UIApplicationShortcutIconTypeContact,
UIApplicationShortcutIconTypeHome,
UIApplicationShortcutIconTypeMarkLocation,
UIApplicationShortcutIconTypeFavorite,
UIApplicationShortcutIconTypeLove,
UIApplicationShortcutIconTypeCloud,
UIApplicationShortcutIconTypeInvitation,
UIApplicationShortcutIconTypeConfirmation,
UIApplicationShortcutIconTypeMail,
UIApplicationShortcutIconTypeMessage,
UIApplicationShortcutIconTypeDate,
UIApplicationShortcutIconTypeTime,
UIApplicationShortcutIconTypeCapturePhoto,
UIApplicationShortcutIconTypeCaptureVideo,
UIApplicationShortcutIconTypeTask,
UIApplicationShortcutIconTypeTaskCompleted,
UIApplicationShortcutIconTypeAlarm,
UIApplicationShortcutIconTypeBookmark,
UIApplicationShortcutIconTypeShuffle,
UIApplicationShortcutIconTypeAudio,
UIApplicationShortcutIconTypeUpdate
} NS_ENUM_AVAILABLE_IOS(9_0)
+ (instancetype)iconWithTemplateImageName:(NSString *)templateImageName;
:自定义图标样式创建对象。+ (instancetype)iconWithContact:(CNContact *)contact;
:使用代表用户通讯簿中的联系人的图标,可以通过ContactsUI框架访问,需要导入ContactsUI头文件 ---#import
。
(2)、 UIApplicationShortcutItem:不可变快捷方式项
必须在初始化期间指定实例的特征,然后才能将其注册到应用对象。即:直接的init方法不可用。
- (instancetype)initWithType:(NSString *)type localizedTitle:(NSString *)localizedTitle localizedSubtitle:(nullable NSString *)localizedSubtitle icon:(nullable UIApplicationShortcutIcon *)icon userInfo:(nullable NSDictionary *)userInfo NS_DESIGNATED_INITIALIZER;
:指定的创建方法。其中参数:type -- 自定义的的字符串标识;localizedTitle -- 快速操作标题;localizedSubtitle -- 快速操作副标题;icon -- 图标;userInfo -- 携带的信息,如果NSDictionary不是plist-encoding会抛出异常。- (instancetype)initWithType:(NSString *)type localizedTitle:(NSString *)localizedTitle;
:只有标识和主标题的创建方法。@property (nonatomic, copy, readonly) NSString *type;
:获取一个应用程序特定的字符串,用于标识要执行的操作的类型。@property (nonatomic, copy, readonly) NSString *localizedTitle;
:获取主标题@property (nullable, nonatomic, copy, readonly) NSString *localizedSubtitle;
:获取副标题@property (nullable, nonatomic, copy, readonly) UIApplicationShortcutIcon *icon;
:获取快捷图标@property (nullable, nonatomic, copy, readonly) NSDictionary
:获取操作所需的应用程序特定信息。> *userInfo;
(3)、 UIMutableApplicationShortcutItem:可变快捷方式项
继承于UIApplicationShortcutItem,属性与之一样但是其属性性质是copy属性。如下所示:
@property (nonatomic, copy) NSString *type;
@property (nonatomic, copy) NSString *localizedTitle;
@property (nullable, nonatomic, copy) NSString *localizedSubtitle;
@property (nullable, nonatomic, copy) UIApplicationShortcutIcon *icon;
@property (nullable, nonatomic, copy) NSDictionary> *userInfo;
2、静态设置方式:在Info.plist设置
(1)、首先在Info.plist
-->Information Property List
下添加array属性的键栏目:UIApplicationShortcutItems
(该字段系统未定义需要全程手写~),用于指定应用程序的静态主屏幕快速操作。该键包含一系列 字典。每个字典包含有关单个快速操作及其使用方法的详细信息。
(2)、在UIApplicationShortcutItems
键栏目下添加dictionary属性的键,然后再在dictionary属性的键栏目下再添加3D Touch相关键。
(3)、3D Touch 相关键:
UIApplicationShortcutItemType
: 必须的!相当于添加一个标识。UIApplicationShortcutItemTitle
:必须的!主标题,如果标题符合一行,则系统将其显示为单行快速操作项。如果标题对于一行而言太长,并且没有指定UIApplicationShortcutItemSubtitle字符串,系统将在两行显示标题。UIApplicationShortcutItemSubtitle
:可选的,副标题。UIApplicationShortcutItemIconType
:可选的,指定系统提供的库中图标类型的可选字符串,参照上面UIApplicationShortcutIconType枚举类。UIApplicationShortcutItemIconFile
:可选的,使用自定义图标,如果指定此键,系统将忽略该UIApplicationShortcutItemIconType键。UIApplicationShortcutItemUserInfo
:可选的,此字典的一个用途是可以提供应用程序版本信息。
如下图设置所示:
(4)、值得注意的是:
- 1、键的前后不能有空格!这个可以将plist文件以Source Code 的形式打开查看一下;
- 2、若设置了UIApplicationShortcutItemIconFile但是文件路径错误或者为空则会显示小黑点图标;
- 3、最多只会有四个快捷入口生效,依次按从上到下的顺序显示。
PS: 附上关于 "键" 的文档地址 -- > UIApplicationShortcutItems
3、代码设置快捷入口项:
代码设置时需要检查设备是否支持3D Touch,即读取任意遵循特征环境协议(UITraitEnvironment)的特征集合类型(UITraitCollection类型)属性的触摸力能力(UIForceTouchCapability类型)属性,以达到判断设备是否支持3D Touch:
typedef NS_ENUM(NSInteger, UIForceTouchCapability) {
UIForceTouchCapabilityUnknown = 0,
UIForceTouchCapabilityUnavailable = 1,
UIForceTouchCapabilityAvailable = 2
};
一般直接在didFinishLaunchingWithOptions:
方法中操作,也可以在根视图控制器中进行操作,这里示例是第一种:
if ([self.window.rootViewController respondsToSelector:@selector(traitCollection)]){
if ([self.window.rootViewController.traitCollection respondsToSelector:@selector(forceTouchCapability)]){
if (self.window.rootViewController.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable){
// 支持3D Touch
UIApplicationShortcutIcon * icon_one = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypePlay];
UIApplicationShortcutIcon * icon_two = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeAdd];
UIApplicationShortcutItem * item_one = [[UIApplicationShortcutItem alloc] initWithType:@"com.test.one" localizedTitle:@"第一标题" localizedSubtitle:@"第一副标题" icon:icon_one userInfo:nil];
UIApplicationShortcutItem * item_two = [[UIApplicationShortcutItem alloc] initWithType:@"com.test.two" localizedTitle:@"第二标题" localizedSubtitle:@"第二副标题" icon:icon_two userInfo:nil];
application.shortcutItems = @[item_one, item_two];
}else{
// 不支持3D Touch
}
}
}
以上就将外部显示项设置完成了,但是这样是不够的,当你没有其他设置后通过快捷方式进入程序永远是首页没方法到你想到的界面,所以这不是结束,而是开始~
4、通过快捷方式进入程序目的界面:
在iOS9时,UIApplicationDelegate添加了如下关于快捷方式进入应用程序的方法:
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler;
当应用程序通过该方法启动或者激活时会走此方法,当然会有例外(下面会介绍),参数shortcutItem是用户选择的那个shortcutItem,可以依次做判断跳转到不同界面;参数completionHandler,是在快速执行完成后调用此block块,根据实施代码的成功或失败返回YES或NO。该方法与
didFinishLaunchingWithOptions
方法存在一定的关系,根据官方文档描述:通常需要在didFinishLaunchingWithOptions
方法中获取launchOptions
的键UIApplicationLaunchOptionsShortcutItemKey
所对应的对象来做检查是否是通过使用快速操作启动程序的。该对象是UIApplicationShortcutItem
类型的对象,如果应用程序是通过快速操作 启动(而不是激活)的,则该对象是代表用户选择的ShortcutItem,否者为null。通过该方式可以区分是否是通过快速操作启动程序的,然后以此进行不同的操作。当用户t通过选择快速操作启动应用程序时,系统将在调用
performActionForShortcutItem:
方法之前先调用启动方法didFinishLaunchingWithOptions
。-
如果
didFinishLaunchingWithOptions
方法返回NO时,系统将不调用performActionForShortcutItem:
方法!到这里第一部分结束,这里放上一个示例,仅供参考!
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UINavigationController * navigationController = [[UINavigationController alloc] initWithRootViewController: [[ViewController alloc] init]];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
if ([self.window.rootViewController respondsToSelector:@selector(traitCollection)]){
if ([self.window.rootViewController.traitCollection respondsToSelector:@selector(forceTouchCapability)]){
if (self.window.rootViewController.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable){
// 支持3D Touch
UIApplicationShortcutIcon * icon_one = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypePlay];
UIApplicationShortcutIcon * icon_two = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeAdd];
UIApplicationShortcutItem * item_one = [[UIApplicationShortcutItem alloc] initWithType:@"com.test.one" localizedTitle:@"第一标题" localizedSubtitle:@"第一副标题" icon:icon_one userInfo:nil];
UIApplicationShortcutItem * item_two = [[UIApplicationShortcutItem alloc] initWithType:@"com.test.two" localizedTitle:@"第二标题" localizedSubtitle:@"第二副标题" icon:icon_two userInfo:nil];
application.shortcutItems = @[item_one, item_two];
}else{
// 不支持3D Touch
}
}
}
// 通常不会写这一段,它和完全没有效果一样~
#ifdef __IPHONE_9_0
if ([launchOptions objectForKey:UIApplicationLaunchOptionsShortcutItemKey]) {
UIApplicationShortcutItem * item = [launchOptions objectForKey:UIApplicationLaunchOptionsShortcutItemKey];
[self application:application performActionForShortcutItem:item completionHandler:^(BOOL succeeded) {
}];
return NO;
}
#endif
return YES;
}
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler
{
UINavigationController * navicattionC = (UINavigationController *)self.window.rootViewController;
ViewController * VC = (ViewController *)navicattionC.topViewController;
if (shortcutItem) {
if ([shortcutItem.type isEqualToString:@"com.test.one"]) {
TextViewController * textVC = [[TextViewController alloc] init];
[VC.navigationController pushViewController:textVC animated:YES];
}
if ([shortcutItem.type isEqualToString:@"com.test.two"]) {
AffineTransformViewController * AffineTransformVC = [[AffineTransformViewController alloc] init];
[VC.navigationController pushViewController:AffineTransformVC animated:YES];
}
}
}
二、程序内使用3D Touch预览和进入下一界面,即(Peek and Pop):
1、与之相关的类与协议及方法与属性:
(1、)试图控制器新增分类方法与属性:
- (id
:UIViewController用于注册视图控制器参与3D Touch的方法。delegate -- 代理;sourceView -- 响应Peek & Pop的视图。)registerForPreviewingWithDelegate:(id )delegate sourceView:(UIView *)sourceView ; - (void)unregisterForPreviewingWithContext:(id
:UIViewController用于销毁视图控制器参与3D Touch的方法。)previewing; - (NSArray
:在Peek时希望提供一些快捷选项,需要重写该方法用于设置快捷选项。该方法需要在目标控制器重写,即你想push或present到的那个控制器!> *)previewActionItems;
(2、)支持3D Touch的视图控制器协议:UIViewControllerPreviewingDelegate
- (nullable UIViewController *)previewingContext:(id
:当用户在预览视图控制器中按下源视图时调用。previewingContext:预览视图控制器的上下文对象。location:在源视图的坐标系中触摸的位置。返回希望提供预览的视图控制器。如果返回nil则没有peek效果。)previewingContext viewControllerForLocation:(CGPoint)location; - (void)previewingContext:(id
:当进入Pop状态时,系统会调用此方法。viewControllerToCommit -- 提供预览的试图控制器。)previewingContext commitViewController:(UIViewController *)viewControllerToCommit;
(3、)预览视图控制器的上下文对象协议类:UIViewControllerPreviewing
(不要在自定义类中使用此协议!!!)
@property (nonatomic, readonly) UIGestureRecognizer *previewingGestureRecognizerForFailureRelationship;
:可以同时识别其他手势。@property (nonatomic, readonly) id
:代理delegate; @property (nonatomic, readonly) UIView *sourceView
:响应用户触摸的视图。@property (nonatomic) CGRect sourceRect;
设置sourceView响应区域的范围,在对象的方法previewingContext: viewControllerForLocation:
中设置此属性的值。如果源视图是自定义的TableView视图,则可以将属性设置为用户触摸的行的frame。
(4、)预览行为快捷项 协议类:UIPreviewActionItem
该协议只有一个只读属性:
-
@property(nonatomic, copy, readonly) NSString *title;
:获取标题。
(5、)预览行为类:UIPreviewAction
:服从协议 -- UIPreviewActionItem
@property(nonatomic, copy, readonly) void (^handler)(id
:block 属性,包含一个快捷项和预览控制器。action, UIViewController *previewViewController); + (instancetype)actionWithTitle:(NSString *)title style:(UIPreviewActionStyle)style handler:(void (^)(UIPreviewAction *action, UIViewController *previewViewController))handler;
:使用指定的标题,样式和处理程序创建一个快速行动。
其中style是枚举类:
typedef NS_ENUM(NSInteger,UIPreviewActionStyle) {
UIPreviewActionStyleDefault=0,
UIPreviewActionStyleSelected,
UIPreviewActionStyleDestructive,
} NS_ENUM_AVAILABLE_IOS(9_0);
(5、)预览行为组类:UIPreviewActionGroup
:服从协议 -- UIPreviewActionItem
-
+ (instancetype)actionGroupWithTitle:(NSString *)title style:(UIPreviewActionStyle)style actions:(NSArray
:使用指定的标题,样式和数组的快速行动创建一个快速行动组。*)actions;
2、具体使用:以在tableView中使用为例
(1、)首先要遵循UIPreviewInteractionDelegate协议,然后在需要支持3D Touch的视图上注册,注意:注册前最好检验一下是否支持3D Touch
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == headerTitleArray.count-1) {
NewestDataTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:NewestDataTableViewCellID forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.model = self.totalArray[indexPath.section][indexPath.row];
cell.wordFont = wordFont;
//注册支持 3D Touch
[self registerPreviewingWithDelegate:self sourceView:cell];
return cell;
}else{
NewestMajorityTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:NewestMajorityTableViewCellID forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.model = self.totalArray[indexPath.section][indexPath.row];
cell.wordFont = wordFont;
//注册支持 3D Touch
[self registerPreviewingWithDelegate:self sourceView:cell];
return cell;
}
}
- (void)registerPreviewingWithDelegate:(id)delegate sourceView:(UITableViewCell *)cell{
if ([self respondsToSelector:@selector(traitCollection)]) {
if ([self.traitCollection respondsToSelector:@selector(forceTouchCapability)]) {
if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
// 注册
[self registerForPreviewingWithDelegate:delegate sourceView:cell];
}
}
}
}
(2、)实现两个协议方法:
#pragma 3D Touch Method
- (nullable UIViewController *)previewingContext:(id )previewingContext viewControllerForLocation:(CGPoint)location{
NSIndexPath * indexPath = [self.newestTableView indexPathForCell:(UITableViewCell *)[previewingContext sourceView]];
NewestContentDetailViewController * contentDetailVC = [[NewestContentDetailViewController alloc] init];
// 自定义的方法,因为这里会和点击方法中代码重复,所以这里处理了一下,抽成了一个方法
[self setModelWithViewController:contentDetailVC withIndexPath:indexPath];
// 设置响应区域
CGRect rect = CGRectMake(0, 0, previewingContext.sourceView.kWidth, previewingContext.sourceView.kHeight);
previewingContext.sourceRect = rect;
return contentDetailVC;
}
- (void)previewingContext:(id )previewingContext commitViewController:(UIViewController *)viewControllerToCommit{
[self.navigationController pushViewController:viewControllerToCommit animated:YES];
}
- (void)setModelWithViewController:(NewestContentDetailViewController * )viewController withIndexPath:(NSIndexPath *)indexPath
{
NewestDataModel * model = self.totalArray[indexPath.section][indexPath.row];
viewController.model = model;
..... //此处省略部分代码!
}
这样基本的pop和peek就完成了,如果还要做更多的操作 --- 在Peek时希望提供一些快捷选项,需要进行第三步:
(3、)在Peek时提供一些快捷选项:重写-previewActionItems
方法。该项操作需要在目标控制器,即将要跳转到的那个控制器里进行!!!
- (NSArray> *)previewActionItems
{
UIPreviewAction * collectAction = [UIPreviewAction actionWithTitle:@"收藏" style:(UIPreviewActionStyleDefault) handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
// 做后续操作
}];
UIPreviewAction * shareAction = [UIPreviewAction actionWithTitle:@"分享" style:(UIPreviewActionStyleSelected) handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
// 做后续操作
}];
UIPreviewAction * cancelAction = [UIPreviewAction actionWithTitle:@"取消" style:(UIPreviewActionStyleDestructive) handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
// 做后续操作
}];
UIPreviewActionGroup * cancelGroup = [UIPreviewActionGroup actionGroupWithTitle:@"更多" style:UIPreviewActionStyleDestructive actions:@[shareAction, cancelAction]];
return @[collectAction, cancelGroup];
}
三、在UIWebView和:WKWebView中启用3D Touch功能:
这个只需要设置9.0后UIWebView或WKWebView新增的属性allowsLinkPreview
为YES即可。该功能主要针对打开的webView中存在其他链接,可以对这些跳转其他链接的入口出使用3D Touch功能。
all are over~