iOS 3D Touch 简述

本文详细介绍了如何在iOS应用内利用3DTouch实现自定义快捷操作,包括创建图标、长按触发自定义ViewController、通过触摸事件进行Action选择等核心功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


首先 有几个要知道的手势

第一, 在点击app icon 的手长按 并且用力一点(用点力不然没效果,不会弄坏手机,坏了也不是我的,哈哈!) 就会出现 几个Item。

第二,(1)在app 里面 长按 也要用力往下压 跟着就会可以弹出 自定义的 ViewController。这个时候如果你放手了那么就会消失。

           (2)如果  长按 往下压 弹出了自定义的ViewController 之后跟着网上移动,就可以出现 选择Action。

第三如果 长按 往下压 弹出了自定义的ViewController,然后更加 用力一点 比 弹出的ViewController的力度 更加大一点 那么  自定义的这个ViewController 就会 相当于push 进来了。

首先来一个获取版本号,因为3D Touch 只有在iOS9 才会有,在后面演示的代码就不上这个判断。

#define IOS_VERSION [[[UIDevice currentDevice] systemVersion] floatValue]

1、首先在 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  去创建 item ,这几个item 就是在点击icon 的时候出现的.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    BOOL result = YES;
    
    //系统版本适配
    if (IOS_VERSION < 9.0) return result;
    
    NSArray *items = [UIApplication sharedApplication].shortcutItems;
    if (items.count == 0) {
        //也可以在info.plist 中创建
        [self createShortIcon];
    }
    //判断是否是从shortitem 启动的程序
    if (launchOptions[@"UIApplicationLaunchOptionsShortcutItemKey"]) {
        _currentShortItem = launchOptions[@"UIApplicationLaunchOptionsShortcutItemKey"];
        //这里返回值很重要、返回no,不会再调用performActionForShortcutItem这个回调方法
//        result = NO;
    }
    
        
    return result;
}


- (void)createShortIcon {

    UIApplicationShortcutIcon *shortIcon1 = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeHome];
    UIApplicationShortcutItem *shortItem1 = [[UIApplicationShortcutItem alloc] initWithType:[NSString stringWithFormat:@"%@.First",BundleId] localizedTitle:@"FistItem" localizedSubtitle:@"subtitle" icon:shortIcon1 userInfo:nil];
    
    UIApplicationShortcutIcon *shortIcon2 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"home@2x.png"];
    UIApplicationShortcutItem *shortItem2 = [[UIApplicationShortcutItem alloc] initWithType:[NSString stringWithFormat:@"%@.Second",BundleId] localizedTitle:@"SecondItem" localizedSubtitle:nil icon:shortIcon2 userInfo:nil];
    
    [[UIApplication sharedApplication] setShortcutItems:@[shortItem1,shortItem2]];
}

/**
    处理shortcotItem
 */
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {

    [self handleItem:shortcutItem];
}

- (void)handleItem:(UIApplicationShortcutItem *)shortItem {

    //处理shortitem事件
    if ([shortItem.type isEqualToString:[NSString stringWithFormat:@"%@.First",BundleId]]) {
        NSLog(@"First Item-----%@>>>>>>%@",[NSBundle mainBundle],[NSBundle mainBundle].bundleIdentifier);
    }else if ([shortItem.type isEqualToString:[NSString stringWithFormat:@"%@.Second",BundleId]]) {
        NSLog(@"Second Item-----%@>>>>>>%@",[NSBundle mainBundle],[NSBundle mainBundle].bundleIdentifier);
    }

    [self showAlert];
}

- (void)showAlert {

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"aaa" message:[NSString stringWithFormat:@"%d",22] delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil, nil];
    [alertView show];
}



//在每次激活程序时先置空一些设置

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    
    if (!_currentShortItem) return;
    
    [self handleItem:_currentShortItem];
    _currentShortItem = nil;
    
}

2、接着这里要说的是 在 长按touch ViewController  中tableView 对应Cell 添加Touch 事件

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellIdenfitier = @"CellId";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdenfitier];
    
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdenfitier];
    }
    [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
    
    cell.textLabel.text = _cellArr[indexPath.row];
    
    if (IOS_VERSION >= 9.0 && (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)) {
        
        [self registerForPreviewingWithDelegate:self sourceView:cell];
    }
    
    return cell;
}

在viewController 中实现 Touch 协议方法


#pragma mark - UIViewControllerPreviewingDelegate

- (nullable UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location {
//重按时显示的预览界面
    return self.vc;
}


- (void)previewingContext:(id <UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit {
    //继续用力按执行执行这个方法, 这里事件预览界面展示出来
    [self showViewController:self.vc sender:self];
}

//重按显示预览界面时,向上滑动出现的菜单选择、一定要在
//-(UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
//回调返回的UIViewController中实现这个方法,不然无法显示菜单选项
- (NSArray<id<UIPreviewActionItem>> *)previewActionItems {

    UIPreviewAction *action1 = [UIPreviewAction actionWithTitle:@"you" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
        UIViewController *vc = [UIViewController new];
        [vc.view setBackgroundColor:[UIColor greenColor]];
        [[self topViewController] presentViewController:vc animated:YES completion:nil];
        
    }];
    
    UIPreviewAction *action2 = [UIPreviewAction actionWithTitle:@"and" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
        UIViewController *vc = [UIViewController new];
        [vc.view setBackgroundColor:[UIColor greenColor]];
        [[self topViewController].navigationController pushViewController:vc animated:YES];
    }];
    
    UIPreviewAction *action3 = [UIPreviewAction actionWithTitle:@"I" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
        
    }];
    
    return @[action1, action2, action3];

}

- (UIViewController *)topViewController {

    return [self topviewControllerViewRootViewController:[UIApplication sharedApplication].delegate.window.rootViewController];
}

- (UIViewController *)topviewControllerViewRootViewController:(UIViewController *)rootViewController {

    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController *tabbarController = (UITabBarController *)rootViewController;
        
        return [self topviewControllerViewRootViewController:tabbarController.selectedViewController];
    }else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
    
        UINavigationController *navigationController = (UINavigationController *)rootViewController;
        return [self topviewControllerViewRootViewController:navigationController.visibleViewController];
        /**
         * topViewController代表当前navigation栈中最上层的VC,而visibleViewController代表当前可见的VC,它可能是topViewController,也可能是当前topViewController present出来的VC。因此UINavigationController的这两个属性通常情况下是一样,但也有可能不同。
         */
    }else if (rootViewController.presentedViewController){
    
        UIViewController *presentViewController = rootViewController.presentedViewController;
        return [self topviewControllerViewRootViewController:presentViewController];
        /**
         *  presentedViewController:The view controller that is presented by this view controlller(read-only),被本视图控制器present出来的的视图控制器(只读)
         
         presentingViewController:The view controller that presented this view controller. (read-only),present出来本视图控制器的视图控制器(只读)
         
         parentViewController:The parent view controller of the recipient(容器). (read-only)
         
         */
    }else {
    
        return rootViewController;
    }
}

3、在自定义的vc弹出时 然后我们往上移动那么就会出现Action

//重按显示预览界面时,向上滑动出现的菜单选择、一定要在
//-(UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
//回调返回的UIViewController中实现这个方法,不然无法显示菜单选项
- (NSArray<id<UIPreviewActionItem>> *)previewActionItems {

    UIPreviewAction *action1 = [UIPreviewAction actionWithTitle:@"you" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
        UIViewController *vc = [UIViewController new];
        [vc.view setBackgroundColor:[UIColor greenColor]];
        [[self topViewController] presentViewController:vc animated:YES completion:nil];
        
    }];
    
    UIPreviewAction *action2 = [UIPreviewAction actionWithTitle:@"and" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
        UIViewController *vc = [UIViewController new];
        [vc.view setBackgroundColor:[UIColor greenColor]];
        [[self topViewController].navigationController pushViewController:vc animated:YES];
    }];
    
    UIPreviewAction *action3 = [UIPreviewAction actionWithTitle:@"I" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
        
    }];
    
    return @[action1, action2, action3];

}

- (UIViewController *)topViewController {

    return [self topviewControllerViewRootViewController:[UIApplication sharedApplication].delegate.window.rootViewController];
}

- (UIViewController *)topviewControllerViewRootViewController:(UIViewController *)rootViewController {

    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController *tabbarController = (UITabBarController *)rootViewController;
        
        return [self topviewControllerViewRootViewController:tabbarController.selectedViewController];
    }else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
    
        UINavigationController *navigationController = (UINavigationController *)rootViewController;
        return [self topviewControllerViewRootViewController:navigationController.visibleViewController];
        /**
         * topViewController代表当前navigation栈中最上层的VC,而visibleViewController代表当前可见的VC,它可能是topViewController,也可能是当前topViewController present出来的VC。因此UINavigationController的这两个属性通常情况下是一样,但也有可能不同。
         */
    }else if (rootViewController.presentedViewController){
    
        UIViewController *presentViewController = rootViewController.presentedViewController;
        return [self topviewControllerViewRootViewController:presentViewController];
        /**
         *  presentedViewController:The view controller that is presented by this view controlller(read-only),被本视图控制器present出来的的视图控制器(只读)
         
         presentingViewController:The view controller that presented this view controller. (read-only),present出来本视图控制器的视图控制器(只读)
         
         parentViewController:The parent view controller of the recipient(容器). (read-only)
         
         */
    }else {
    
        return rootViewController;
    }
}












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值