iOS 3D Touch

3D Touch功能主要分为以下三个模块:

  • 1、Home Screen Quick Actions

通过主屏幕的应用Icon,我们可以用3D Touch呼出一个菜单,进行快速定位应用功能模块相关功能的开发。

  • 2、peek and pop

这个功能是一套全新的用户交互机制,在使用3D Touch时,ViewController中会有如下三个交互阶段:

3DTouch有两种体现方式,第一种是通过Peek 轻按App icon弹出选项菜单,第二种是在App内的界面上通过Peek 轻按,弹出的预览界面

3、Force Properties

iOS9为我们提供了一个新的交互参数:力度。我们可以检测某一交互的力度值,来做相应的交互处理。例如,我们可以通过力度来控制快进的快慢,音量增加的快慢等。

  1. 轻按app icon弹出选项菜单 代码实现

在app启动时配置application.shortcutItems,注意版本适配

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    [self setupShortcutItems:application];
    
    return YES;
}

- (void)setupShortcutItems:(UIApplication *)application {
    
    // 通过Peek 用力按app icon 弹出
#ifdef __IPHONE_9_0
    // 判断该版本xcode的API是否可用,编译时是否需要生成这段代码
    // 创建标签中的icon
    // 自定义图片的icon
    UIApplicationShortcutIcon *icon1 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"fts_search_wechat_icon_46x46_"];
    UIApplicationShortcutIcon *icon2 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"fts_websearch_icon_46x46_"];
    // 使用系统风格的icon
    UIApplicationShortcutIcon *icon3 = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeShare];
    
    UIMutableApplicationShortcutItem *item1 = [[UIMutableApplicationShortcutItem alloc] initWithType:shortcutItemType1Key localizedTitle:@"添加到通讯录" localizedSubtitle:@"点击即可添加到通讯录" icon:icon1 userInfo:nil];
    UIMutableApplicationShortcutItem *item2 = [[UIMutableApplicationShortcutItem alloc] initWithType:shortcutItemType2Key localizedTitle:@"搜索" localizedSubtitle:@"在微信中搜索你想要查找的" icon:icon2 userInfo:nil];
    UIMutableApplicationShortcutItem *item3 = [[UIMutableApplicationShortcutItem alloc] initWithType:shortcutItemType3Key localizedTitle:@"分享" localizedSubtitle:@"分享此app" icon:icon3 userInfo:nil];
    
    application.shortcutItems = @[item1, item2, item3];;
#endif
}

轻按app icon弹出的菜单,点击菜单的item的回调, 通过shortcutItem的type判断不同的item,处理不同的逻辑


#ifdef __IPHONE_9_0
/// 点击app上标签item后,进入时对应事件的处理,
-(void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
    UINavigationController *nav = (UINavigationController *)self.window.rootViewController;
    if([shortcutItem.type isEqualToString:shortcutItemType1Key]){
        NSLog(@"点击了添加到通讯录");
        UIViewController *vc = [[UIViewController alloc] init];
        vc.title = @"通讯录";
        vc.view.backgroundColor = [UIColor yellowColor];
        [nav pushViewController:vc animated:YES];
    }
    if ([shortcutItem.type isEqualToString:shortcutItemType2Key]){
        NSLog(@"点击了搜索");
        UIViewController *vc = [[UIViewController alloc] init];
        vc.title = @"搜索";
        vc.view.backgroundColor = [UIColor redColor];
        [nav pushViewController:vc animated:YES];
    }
    
    if ([shortcutItem.type isEqualToString:shortcutItemType3Key]) {
        NSLog(@"点击了分享");
        UIViewController *vc = [[UIViewController alloc] init];
        vc.title = @"分享";
        vc.view.backgroundColor = [UIColor blueColor];
        [nav pushViewController:vc animated:YES];
    }
}
#endif

2.App内界面上通过Peek 用户按弹出的预览界面
首先在需要弹出预览的控制器中检测设备是否支持3d touch 功能, 并注册预览代理,实现UIViewControllerPreviewingDelegate方法

@implementation ViewController
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    /// 检测是否有3d touch 功能
    if ([self respondsToSelector:@selector(traitCollection)]) {
        if ([self.traitCollection respondsToSelector:@selector(forceTouchCapability)]) {
            if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
                // 支持3D Touch
                if ([self respondsToSelector:@selector(registerForPreviewingWithDelegate:sourceView:)]) {
                    [self registerForPreviewingWithDelegate:self sourceView:self.view];
                }
            } else {
                // 不支持3D Touch
            }
        }
    }
}

#pragma mark - UIViewControllerPreviewingDelegate

#ifdef __IPHONE_9_0

// 弹出预览页面
- (nullable UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location NS_AVAILABLE_IOS(9_0) {
    
    // previewingContext.sourceView: 触发Peek & Pop操作的视图
    // previewingContext.sourceRect: 设置触发操作的视图的不被虚化的区域
    
    MyViewController *myVc = [MyViewController new];
    // 预览区域大小(可不设置)
    myVc.preferredContentSize = CGSizeMake(0, 320);
    return myVc;
    
}



// 在弹出页面的基础上,再继续用力按下去,就会push预览界面了。(pop功能)
- (void)previewingContext:(id <UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit NS_AVAILABLE_IOS(9_0) {
    
    [self showViewController:viewControllerToCommit sender:self];
}

#endif

@end

如果想要在3D Touch 触发显示预览界面的情况下,设置向上滑动视图,下面出现的菜单,需要在预览视图的控制器中重写previewActionItems,添加UIPreviewAction(弹出的每个按钮)

@implementation MyViewController
// 实现这个方法之后, 3D Touch触发的情况下,向上滑动视图,下面会出现菜单
// 这个方法就是定义向上滑动的菜单的
#ifdef __IPHONE_9_0
- (NSArray<id<UIPreviewActionItem>> *)previewActionItems NS_AVAILABLE_IOS(9_0) {
    return @[
             [UIPreviewAction actionWithTitle:@"iTem1" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
                 NSLog(@"点击了iTem1,%@", action);
                 
             }],
             [UIPreviewAction actionWithTitle:@"iTem2" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
                 NSLog(@"点击了iTem2,%@", action);
             }],
             [UIPreviewAction actionWithTitle:@"iTem3" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
                 NSLog(@"点击了iTem3,%@", action);
             }]
             ];
}
#endif

@end

3.添加widget

WechatIMG11.jpeg
  • 1.如何为现有的工程添加widget;
    在现有的项目的中创建widget
    Xcode菜单 -> File -> New -> Target.. -> 选择Today Extension

新建一个target


屏幕快照 2017-04-29 下午10.56.12.png

选择Today Extension


Snip20170429_1.png

为你的target名称后创建完成,会出现5个文件, 下面也是添加Today Extension之后的项目

Snip20170429_3.png

如果你想使用存代码,不用storyboard搭建UI ,可以在Widget这个target中删除MainInterface.storyboard,并在info.plist中删除NSExtensionMainStoryboard,并添加NSExtensionPrincipalClass,设置其value为TodayViewController


Snip20170429_4.png
  • 2如何写UI界面
    在系统生成的TodayViewController中构建UI界面
- (void)viewDidLoad {
    [super viewDidLoad];
    // 设置widget展示的视图大小
    self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 100);
}
  • 3.点击widge处调用app
    点击Widget布局任何区域都能唤起主应用程序,常用的方式在整个TodayViewController的View增加Tap事件
    因为extension和app是两个完全独立的进程,所以它们之间不能直接通信(不能像应用内部点击按钮,跳转到指定页面)。为了实现widget调起app,这里通过openURL的方式来启动app。
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    
    // 设置widget展示的视图大小
    self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 100);
    
    // 如你所看当用户拉开Widget时,因为Widget是依赖于应用程序在分发时是跟应用程序一块打包的,希望点击Widget布局任何区域都能唤起主应用程序,常用的方式在整个View增加Tap事件订阅处理
    [self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(openApp:)]];
    
    // 但这种方式会额外产生一个问题,如果Widget空白区域没有任何UI元素则无法触发该事件,那这里有一个小技巧可以解决改问题,可以整个Widget增加一个透明的ImageView:
    // 创建一个透明的ImageView作为widge整个背景
    UIImageView *bgImageView = [UIImageView new];
    bgImageView.userInteractionEnabled = YES;
    bgImageView.alpha = 0.01;
    bgImageView.backgroundColor = [UIColor grayColor];
    [self.view addSubview:bgImageView];
    bgImageView.frame = self.view.bounds;
    
}

// 点击整个widget区域的事件
- (void)openApp:(UITapGestureRecognizer *)tap {
    [self.extensionContext openURL:[NSURL URLWithString:@"TodayDemo://action=jumpToHomePage"]
                 completionHandler:^(BOOL success) {
                NSLog(@"打开%@", success ? @"成功" : @"失败");
                 }];

}


如果要完成widget调用app,需要在info.plist中配置URL Types


屏幕快照 2017-04-30 上午9.10.40.png

app需要处理接收跳转,这个在AppDelegate的代理方法中设置

// 接收来自TodayViewController的跳转
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    
    NSString *prefix = @"TodayDemo://";
    if ([[url absoluteString] rangeOfString:prefix].location != NSNotFound) {
        NSString *func = [[url absoluteString] substringFromIndex:prefix.length];
        if ([func isEqualToString:@"jumpToHomePage"]) {
            
        }
        
        else if([func isEqualToString:@"jumpToOtherPage"]) {
            
        }
    }
    return YES;
}
  • 4.如何与host app共享数据。

Demo

在iOS10换出菜单都有分享这个事件,这个事件是系统自动添加的,并且apple在调试的时候不会出现这个分享的事件(不知道这个调试的时候好坑人啊,一直在纠结怎么弄不出来那个分享的事件)
在打包ipa时,可以发现有这个 分享Beta版反馈 的事件,appstore 的包出现 分享“app名称”

# define __IPHONE_9_2 90200
这些宏的作用是判断该版本的xcode是否具有这个宏所定义的系统的API,在xcode中有这个宏就代表有这个宏所定义的系统的API。

#define kCurrentSystemVersion ([[[UIDevice currentDevice] systemVersion] floatValue])
通常这个宏是用来区分手机不同版本的系统应该使用什么版本的API。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容