为啥我的 UICollectionView 支持方法仅在我的 ViewController 设置为初始视图控制器时调用?

Posted

技术标签:

【中文标题】为啥我的 UICollectionView 支持方法仅在我的 ViewController 设置为初始视图控制器时调用?【英文标题】:Why do my UICollectionView support methods only invoke when my ViewController is set as Initial View Controller?为什么我的 UICollectionView 支持方法仅在我的 ViewController 设置为初始视图控制器时调用? 【发布时间】:2014-11-20 02:50:40 【问题描述】:

我有一个非常简单的 ViewController,叫做 CViewController,里面有一个基本的 UICollectionView

当我将 CViewController 设为 Initial View Controller 时,一切正常,我的 UICollectionView 会按计划自行填充。 一点问题都没有。

当我尝试从任何其他 ViewController模态呈现 CViewController 时,UICollectionViewDataSource、UICollectionViewDelegate 和 UICollectionViewDelegateFlow 协议从不调用

我只是得到了 UICollectionView 从未填充数据时出现的经典“黑洞”。根据我的日志,没有调用任何预期的委托方法,但 CViewController 肯定会根据我的日志进行分配、初始化和加载。

什么可能导致这个错误?看起来很奇怪,我可以简单地在 Storyboard 上翻转 CViewController 的 "Is Initial View Controller" 属性并突然调用支持的方法。

这是我用来从单独的 VC 启动 segue 的方法:

-(void)initCustomSegue

CViewController *newvc = [[CViewController alloc] init];
newvc.images = arrayOfImages;
newvc.distances = arrayOfDistances;
newvc.usernames = arrayOfUsers;
[self presentViewController:newvc animated:YES completion:nil];

我相信我的班级声明格式正确:

@interface CViewController : UIViewController<UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>

(注意:不需要重新声明 UICollectionViewDelegate,因为它是 UICollectionDelegateFlowLayout 的子代理)

而且我相信我在 ViewDidLoad 中的所有设置都是正确的:

- (void)viewDidLoad 

NSLog(@"loaded cviewcontroller");
[super viewDidLoad];
[self.myCollectionView setDataSource:self];
[self.myCollectionView setDelegate:self];
[self.myCollectionView registerClass:[CollectionViewCell class] forCellWithReuseIdentifier:identifier];
[self.myCollectionView registerNib:[UINib nibWithNibName:@"CollectionViewCell" bundle:[NSBundle mainBundle]]
        forCellWithReuseIdentifier:identifier];

由于此代码在某些情况下确实有效,因此您可以放心地假设我的所有变量都已正确实例化并且我的所有数据都是合法的。

知道我哪里出错了吗?我被难住了。

编辑:

我目前的解决方法是将原始 VC 嵌入到导航控制器中,然后在情节提要中创建一个从原始 VC 到情节提要上 CViewController 实例的推送序列。

然后我调整了我的数据传递实现和 segue 调用,以便我只需调用 performSegueWithIdentifier: 然后使用 prepareForSegue: 方法传递所有变量。

这可行,但我仍然很好奇我原来的问题到底是什么。

【问题讨论】:

你得到了“黑洞”,因为你没有通过使用 alloc init 来实例化你在情节提要中创建的控制器来创建它。您应该阅读“ios 视图控制器编程指南”,以便了解 Apple 的范例。 @rdelmar 我从 UICollectionView 得到了一个黑洞,而不是 CViewController 本身的实例。我知道如何实例化视图,并且我的控制台正在记录正在调用 viewDidLoad。 【参考方案1】:

似乎当您展示 ViewController 时,您并没有使用 Storyboard 进行实例化,因此插座和视图都没有连接。

在 Storyboard 中,为您的 ViewController 提供一个标识符,然后使用它从您的 Storyboard 中实例化 ViewController。像这样的:

-(void)initCustomSegue

   CViewController *newvc = [[UIStoryboard storyboardWithName:storyboardName bundle:nil] instantiateViewControllerWithIdentifier:@"Identifier"];
   newvc.images = arrayOfImages;
   newvc.distances = arrayOfDistances;
   newvc.usernames = arrayOfUsers;
   [self presentViewController:newvc animated:YES completion:nil];

但是,如果您知道您的 ViewController 是并且将永远是该 Storyboard 的首字母,则无需执行上述操作,只需使用:

CViewController *newvc = [[UIStoryboard storyboardWithName:storyboardName bundle:nil] instantiateInitialViewController];

【讨论】:

我相信这会解决问题。明天我会试试这个,让你知道它是否有效。所以你认为即使我在 Storyboard 中的 VC 是 CViewController 类型,我仍然不能简单地在呈现的 VC 中初始化 + 分配 CViewController 的实例,我实际上必须通过它在 Storyboard 中的标识符来获取视图控制器?有趣的。我什至没有想到这一点。 是的,因为有问题的情节提要包含您设置的视图层次结构和出口。此外,当从 Storyboard 实例化 ViewController 时,initWithCoder: 方法是被调用的初始化程序。 是的!有效!当大量使用故事板时,很容易在概念上误解事物,这太有趣了。非常感谢您的回答,现在我实际上可以使用 Modal segue 而不是 Push。这也很有意义,即使 CViewController 类有 IBOutlets 和 Storyboard 没有设置的东西,我想实例化的是 CViewController 的 Storyboard 版本,而不是原始类的版本。 是的!很高兴听到您理解这个概念,而不是像其他人那样只是复制粘贴代码。您介意将此答案标记为正确吗? :)

以上是关于为啥我的 UICollectionView 支持方法仅在我的 ViewController 设置为初始视图控制器时调用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 uicollectionview 不随底层 uiscrollview 一起移动?

为啥我的 UICollectionView 单元格在我的 swift ios 应用程序中不可点击?

为啥我不能从我的 UICollectionView 中删除图像?

为啥我的 UICollectionView 无法访问我在 for 循环中创建的数组 - 致命错误:索引超出范围

为啥 UICollectionView didSelect 方法不起作用?

为啥我们需要 visibleCells 函数(UICollectionView)