You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

首次通过UICollectionView Cell push视图失败,UINavigationController对象变更问题

问题原因

你遇到的问题核心是自定义UICollectionViewCell持有的父Controller引用失效,具体触发逻辑如下:

  1. UICollectionView存在Cell复用机制,首次渲染Cell时你给Cell赋值了父Controller引用,此时点击跳转正常
  2. push新页面后返回列表,已经渲染完成的Cell没有触发复用逻辑,持有的旧Controller引用可能因为导航栈状态变化变为非活动状态/无效引用,导致NavigationController.PushViewController调用不生效
  3. 滚动列表时不可见的Cell会触发复用,你在GetCell方法里重新给Cell的Controller属性赋值了最新的实例,所以滚动后功能恢复

解决方案

最优方案(推荐):调整架构,把跳转逻辑移到父Controller处理

Cell属于视图层,不应该持有Controller引用也不应该处理页面跳转逻辑,改用回调机制把点击事件抛给父Controller处理,从根源避免引用失效问题:

  1. 给自定义Cell定义点击回调
public class CustomCollectionViewCell : UICollectionViewCell
{
    // 声明点击回调,参数可以按你的需要传
    public Action<string> OnCellTapped;

    private void TapDetected()
    {
        var username = this.username.Text;
        OnCellTapped?.Invoke(username);
    }
    // 其他原有逻辑保留
}
  1. 在父ViewController的GetCell复用方法里绑定回调
public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
{
    var cell = collectionView.DequeueReusableCell("你的Cell复用ID", indexPath) as CustomCollectionViewCell;
    // 原有给Cell赋值数据的逻辑保留
    // 绑定点击回调,跳转逻辑直接在父Controller里执行
    cell.OnCellTapped = (username) => {
        var profileViewController = new ProfileViewController(username);
        profileViewController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
        this.NavigationController.PushViewController(profileViewController, true);
    };
    return cell;
}
  1. 删掉Cell里所有和持有、调用父Controller相关的代码即可。

临时修复方案(不推荐,仅适配现有逻辑)

如果你不想改动现有架构,只需要在每次Cell复用时(也就是GetCell方法给Cell赋值的阶段),都重新给Cell的controller属性赋值当前父ViewController的最新实例,保证Cell持有的引用永远有效。

冗余代码清理

删掉你TapDetected方法里的controller.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;这行代码,你要push的是ProfileViewController,修改父Controller的模态展示风格完全没有作用,反而可能引发导航栈状态异常。

内容的提问来源于stack exchange,提问作者Blackie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 13:42:01