美文网首页
iOS 3D Touch(二) peek and pop

iOS 3D Touch(二) peek and pop

作者: 可惜你不是我的双子座 | 来源:发表于2019-05-02 14:12 被阅读0次

作为3D Touch的一部分,peek and pop (预览和弹出)个人觉得还是很有意思的,今天就说说如何去实现这一小功能。

一、遵守协议

@interface ViewController ()<UIViewControllerPreviewingDelegate>

@end

二、注册代理,并传入响应3D Touch的视图,并实现三个通知中心(分别为删除、置顶、未读功能)。

注意:注册代理应该放在viewDidLoad里面,而看了很多文章都把registerForPreviewingWithDelegate方法放在tableViewcellForRowAtIndexPath代理方法中,这样写非常不好,因为注册只需要执行一次。

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deleteActionClick:) name:MessageDeleteNoti object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stickActionClick:) name:MessageStickNoti object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(noReadActionClick:) name:MessageNoReadNoti object:nil];
    
    if (@available(iOS 9.0, *)) {
        
        if ([self check3DTouchAvailable]) { // 判断3d touch是否可用
            
            [self registerForPreviewingWithDelegate:(id)self sourceView:self.tableView];
        }
    }
}

- (BOOL)check3DTouchAvailable {
    
    if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
        
        return YES;
    }
    return NO;
}

- (void)dealloc{
    
    [[NSNotificationCenter defaultCenter] removeObserver:self name:MessageDeleteNoti object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:MessageStickNoti object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:MessageNoReadNoti object:nil];
}

三、实现UIViewControllerPreviewingDelegate协议

可以看看官方API,只有需实现以下两个方法

NS_CLASS_AVAILABLE_IOS(9_0) @protocol UIViewControllerPreviewingDelegate <NSObject>

// If you return nil, a preview presentation will not be performed
- (nullable UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location NS_AVAILABLE_IOS(9_0);
- (void)previewingContext:(id <UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit NS_AVAILABLE_IOS(9_0);

@end
3.1 当系统察觉到足够的压力时,会调用previewingContext:commitViewController:代理方法:
- (void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit {
    
    // 将配置好的控制器推入导航栈
    [self.navigationController pushViewController:viewControllerToCommit animated:YES];
}
3.2 当用户重压区域的出现预览界面,其他区域则会变模糊,在此方法中我们可以把需要的数据传入到下一个界面。
- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location {
    
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
    if (!indexPath) {
        return nil;
    }
    //防止重复加入
    if ([self.presentedViewController isKindOfClass:[nextViewController class]]){
        return nil;
    }
    else {
        
        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
        listCell *cell = (listCell *)[self.tableView cellForRowAtIndexPath:indexPath];
        CGRect rect = cell.frame;
        previewingContext.sourceRect = rect;
        NIMRecentSession *recentSession = self.conversationArr[indexPath.row];
        if (recentSession.unreadCount > 0) {
            
            [recentSession setValue:@"0" forKey:@"unreadCount"];
        }
        
        [self sort];
        [self testDataIsNull];
        nextViewController *vc = [[nextViewController alloc] initWithSession:recentSession.session];
        vc.indexPath = indexPath;
        vc.isTop = [recentSession isTop];
        vc.isOfficeNotiAccount = recentSession.isOfficeNotiAccount;
        return vc;
    }
}

四、实现通知方法

- (void)deleteActionClick:(NSNotification *)noti {
    
    NSIndexPath *indexPath = noti.userInfo[@"index"];
    NIMRecentSession *recentSession = self.conversationArr[indexPath.row];
    [self onDeleteRecentAtIndexPath:recentSession atIndexPath:indexPath];
}

- (void)stickActionClick:(NSNotification *)noti {
    
    NSIndexPath *indexPath = noti.userInfo[@"index"];
    NSInteger isTop = [noti.userInfo[@"isTop"] integerValue];
    NIMRecentSession *recentSession = self.conversationArr[indexPath.row];

    if (isTop) { // 点击了取消置顶
        
        [recentSession setTopFlag:0];
        [self sort];
        [self testDataIsNull];
    }else { // 点击了置顶
        
        [recentSession setTopFlag:1];
        [self sort];
        [self testDataIsNull];
    }
}

- (void)noReadActionClick:(NSNotification *)noti {
    
    NSIndexPath *indexPath = noti.userInfo[@"index"];
    NIMRecentSession *recentSession = self.conversationArr[indexPath.row];
    
    [recentSession setValue:@"1" forKey:@"unreadCount"];
    [self testDataIsNull];
}

五、添加Peek状态下,上划时的快速操作,即在nextViewController重写方法,通过发送通知告诉上一个界面需要执行的操作。

#pragma mark - UIPreviewActionItem
- (NSArray<id<UIPreviewActionItem>> *)previewActionItems {
    
    UIPreviewAction *noReadAction = [UIPreviewAction actionWithTitle:@"标为未读" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
        
        NSLog(@"标为未读");
        [[NSNotificationCenter defaultCenter] postNotificationName:MessageNoReadNoti object:nil userInfo:@{@"index":self.indexPath}];
    }];
    
    UIPreviewAction *stickAction = [UIPreviewAction actionWithTitle:@"置顶" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
        
        NSLog(@"置顶");
        [[NSNotificationCenter defaultCenter] postNotificationName:MessageStickNoti object:nil userInfo:@{@"index":self.indexPath,@"isTop":@(self.isTop)}];
    }];
    
    UIPreviewAction *cancelStickAction = [UIPreviewAction actionWithTitle:@"取消置顶" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
        
        NSLog(@"取消置顶");
        [[NSNotificationCenter defaultCenter] postNotificationName:MessageStickNoti object:nil userInfo:@{@"index":self.indexPath,@"isTop":@(self.isTop)}];
    }];
    
    UIPreviewAction *deleteAction = [UIPreviewAction actionWithTitle:@"删除" style:UIPreviewActionStyleDestructive handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
        
        NSLog(@"删除");
        [[NSNotificationCenter defaultCenter] postNotificationName:MessageDeleteNoti object:nil userInfo:@{@"index":self.indexPath}];
    }];
    
    if (self.isOfficeNotiAccount) {
        return @[noReadAction, deleteAction];
    }
    
    return self.isTop ? @[noReadAction, cancelStickAction, deleteAction] : @[noReadAction, stickAction, deleteAction];
}

相关文章

网友评论

      本文标题:iOS 3D Touch(二) peek and pop

      本文链接:https://www.haomeiwen.com/subject/bljnnqtx.html