UITableViewCell添加UIPreviewInteraction后代理方法未触发,求解决方案
嘿,我来帮你搞定这个3D Touch交互的问题,你的代码里有几个关键问题导致代理方法没被调用,咱们一步步来修复:
核心问题:UIPreviewInteraction 被提前释放
你在cellForRowAt方法里创建的planPreviewInteraction是局部变量,方法执行完毕后就会被ARC自动回收,这个交互对象根本存活不到用户触发3D Touch的时候,自然不会调用任何代理方法。
你需要把这个交互对象持久化存储,最好的方式是给自定义的UITableViewCell添加一个属性来持有它。
正确的实现步骤
1. 自定义UITableViewCell,添加交互属性
先创建一个自定义的cell类,把UIPreviewInteraction作为它的属性:
class CustomPreviewCell: UITableViewCell { // 持有预览交互对象,避免被提前释放 var previewInteraction: UIPreviewInteraction? override func awakeFromNib() { super.awakeFromNib() // 获取你要添加交互的视图(tag=1的那个) guard let interactionView = viewWithTag(1) else { return } if #available(iOS 10.0, *) { previewInteraction = UIPreviewInteraction(view: interactionView) } } }
2. 在cellForRowAt中设置代理
现在在表格数据源方法里,给cell的交互对象设置代理:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // 注意这里要转成自定义的cell类型 let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CustomPreviewCell if #available(iOS 10.0, *) { cell.previewInteraction?.delegate = self } return cell }
其他需要检查的细节
- 确保交互视图可响应触摸:检查tag=1的
interactionView的isUserInteractionEnabled属性是否为true(默认是true,但如果被手动设置为false,交互会失效)。 - 代理协议要正确遵守:你的ViewController必须明确声明遵守
UIPreviewInteractionDelegate协议,比如:class YourViewController: UIViewController, UIPreviewInteractionDelegate { // ... 你的其他代码 } - 初始化动画器对象:你的代理方法里用到了
animator,但看起来没有初始化它。建议在previewInteractionShouldBegin方法里创建动画器,比如:func previewInteractionShouldBegin(_ previewInteraction: UIPreviewInteraction) -> Bool { guard let view = previewInteraction.view, let touchPoint = view.superview?.convert(view.center, to: tableView), let indexPath = tableView.indexPathForRow(at: touchPoint) else { return false } // 创建属性动画器,处理预览过渡效果 animator = UIViewPropertyAnimator(duration: 0.3, curve: .easeInOut) { if let cell = tableView.cellForRow(at: indexPath) { cell.transform = CGAffineTransform(scaleX: 0.95, y: 0.95) cell.alpha = 0.8 } } return true } // 别忘了在取消交互时恢复cell状态 func previewInteractionDidCancel(_ previewInteraction: UIPreviewInteraction) { animator?.stopAnimation(true) // 恢复cell的原始状态 if let view = previewInteraction.view, let touchPoint = view.superview?.convert(view.center, to: tableView), let indexPath = tableView.indexPathForRow(at: touchPoint), let cell = tableView.cellForRow(at: indexPath) { cell.transform = .identity cell.alpha = 1.0 } }
这样调整后,你的UIPreviewInteraction应该就能正常触发代理方法,实现类似Apple Music的3D Touch预览效果了。
内容的提问来源于stack exchange,提问作者Jacob Cavin
相关产品推荐
相关产品推荐

