UITableViewCell 中的 3D Touch Peek 和 Pop 如何将数据移交给其他 UIViewController?

Posted

技术标签:

【中文标题】UITableViewCell 中的 3D Touch Peek 和 Pop 如何将数据移交给其他 UIViewController?【英文标题】:3D Touch Peek and Pop from UITableViewCell how to hand over data to other UIViewController? 【发布时间】:2015-10-07 21:22:19 【问题描述】:

我的应用程序在 Core Data 对象中存储了不同的属性。它们都显示在 UITableView 中,如果单击单元格,则会显示 DetailView。 Master-Detail-XCode-Template 中的常见内容。

现在我想用 peek and pop 实现 3D Touch。就像在邮件应用程序中一样,3D 触摸一个单元格,获得预览,按下更深,弹出细节。

到目前为止我已经完成了这项工作,但我无法弄清楚如何在

中传递相应的数据
- (nullable UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location

- (void)previewingContext:(id <UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit

到另一个 DetailViewController。

如果您只是单击单元格(没有 3D 触摸),我会在

中交出数据
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 

    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
    NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
    [[segue destinationViewController] setDetailItem:object];

我正在使用一个

id detailItem

在每个 ViewController 中,我都为它设置了相应的对象。

所以我尝试获得与工作类似的东西,所以在我的 DetailViewController 中,我的“detailItem”需要来自选定(3D 触摸)单元格的相应核心数据对象。

感谢您的帮助!

【问题讨论】:

【参考方案1】:

如果您使用从单元到新视图控制器的故事板转接,则发送方是表格视图单元。

所以你可以这样实现prepareForSegue:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 

    if ([sender isKindOfClass:[UITableViewCell class]]) 

        UITableViewCell *cell = sender;
        NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

        id viewController = segue.destinationViewController;

        // Get your data object
        // Pass it to the new view controller
    

【讨论】:

【参考方案2】:

使用故事板 ID 从故事板中获取目标视图控制器,并在 prepareForSegue 方法中传递您正在执行的对象。

下面是我用来传递数据的代码。它在 Swift 中,在 Objective C 中应该类似。如果你想要 Objective C 版本,请告诉我。

func previewingContext(previewingContext: UIViewControllerPreviewing,viewControllerForLocation location: CGPoint) -> UIViewController? method:

    // Obtain the index path and the cell that was pressed.
    guard let indexPath = tableView.indexPathForRowAtPoint(location),
              cell = tableView.cellForRowAtIndexPath(indexPath) else  return nil 

    // Create a destination view controller and set its properties.
    guard let destinationViewController = storyboard?.instantiateViewControllerWithIdentifier("DestinationViewController") as? DestinationViewController else  return nil 
    let object = fetchedResultController.objectAtIndexPath(indexPath)
    destinationViewController.detailItem = object

    /*
        Set the height of the preview by setting the preferred content size of the destination view controller. Height: 0.0 to get default height
    */
    destinationViewController.preferredContentSize = CGSize(width: 0.0, height: 0.0)

    previewingContext.sourceRect = cell.frame

    return destinationViewController

【讨论】:

谢谢,我真的很接近但搞砸了一些事情......;) @Dheeraj Dir 先生,您没有提到您从苹果那里获取了这段代码。 developer.apple.com/library/content/samplecode/… guard let indexPath = tableView.indexPathForRowAtPoint(location), cell = tableView.cellForRowAtIndexPath(indexPath) else return nil 这个方法给出了错误的索引。有什么方法可以使用 3D touch 获得点击视图?【参考方案3】:

根据 Dheeraj 的回复,调整一些代码以纠正 tableview 单元格的错误触摸位置。假设我们需要将名为 type 的值传递给目标控制器。

- (nullable UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
// check if we're not already displaying a preview controller
if ([self.presentedViewController isKindOfClass:[DetailViewController class]]) 
    return nil;


CGPoint cellPostion = [self.tableview convertPoint:location fromView:self.view];
NSIndexPath *path = [self.tableview indexPathForRowAtPoint:cellPostion];

if (path) 
    UITableViewCell *cell = [self.tableview cellForRowAtIndexPath:path];
    type = [[self.data objectAtIndex:path.row] integerValue];
    // shallow press: return the preview controller here (peek)
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    DetailViewController *previewController = [storyboard instantiateViewControllerWithIdentifier:@"DetailViewController"];
    previewController.type = type;
    previewingContext.sourceRect = [self.view convertRect:cell.frame fromView:self.tableview];
    return previewController;

return nil;

【讨论】:

只需在 viewDidLoad 之类的地方调用 [self registerForPreviewingWithDelegate:self sourceView:self.tableView] 即可无需调用 [self.tableview convertPoint:location fromView:self.view]。 UIKit 将为您完成转换。 使用[self registerForPreviewingWithDelegate:self sourceView:self.tableView]时出现问题。即 3d 触摸动画的快照不包括contentView.transform 状态。假设您为每个单元格设置了contentView.transform = TransformHelper.reverse(),那么在运行 3d 触摸动画时,您最终会得到颠倒的单元格。

以上是关于UITableViewCell 中的 3D Touch Peek 和 Pop 如何将数据移交给其他 UIViewController?的主要内容,如果未能解决你的问题,请参考以下文章

微信小程序用setData修改数组或对象中的一个属性值

python中的格式化

UITableViewCell 中的 UIDatePicker 更新 UITableViewCell 文本标签

更改 UITableViewCell 中的对象也更改了重用 UITableViewCell 的对象

确定 UITableViewCell 中的 UIButton

UITableViewCell 事件中的 UIButton 不起作用