xcode 5现在有什么警告错误 – 控件可能会到达非void函数的末尾

所以我一直在Xcode4中为有多个集合视图的应用程序(准确地说是4)

我有两个视图,一个底部“主”视图,其中包含一个大屏幕集合视图,一个较小的“抽屉”视图,可以从侧面拉出并包含三个窄的水平滚动的集合视图堆叠在一起其他的顶部。

我一直使用cellforitematpath方法使用标记和if语句来填充单元格。 在xcode 4中,和我在xcode 4中创build的项目,现在在xcode 5中打开,这个工程。 我得到一个警告(而不是错误)在底部说, control may reach end of non void function ,但我仍然能够build立和运行,它的工作原理。

在xcode 5中的一个新项目中,相同的代码表示“控制可能会达到非void函数的末尾”,因为这是一个错误,不允许构build和运行。 这是无止境的令人沮丧。 除非有一个数组要填充单元格,否则我不想返回一个单元格。 我甚至不知道“返回零”是什么意思。 有没有人有任何build议如何把这个closures?

以下绝对不漂亮,请自行承担风险:

 - (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { if (collectionView.tag == 0){ static NSString *CellIdentifier = @"subjectCell"; SubjectCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath]; AHSubject *cellSubject = [self.subjectsArray objectAtIndex:indexPath.row]; [[cell subjectLabel]setText:cellSubject.name]; return cell; } else if (collectionView.tag == 1){ if ([categoryArray count] > 0) { static NSString *CellIdentifier = @"categoryCell"; CategoryCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath]; AHCategory *cellCategory = [categoryArray objectAtIndex:indexPath.row]; [[cell categoryLabel]setText:cellCategory.name]; return cell; } } else if (collectionView.tag == 2){ if ([subcategoryArray count] > 0) { static NSString *CellIdentifier = @"subcategoryCell"; GroupCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath]; AHCardGroup *cellSubcategory = [subcategoryArray objectAtIndex:indexPath.row]; [[cell subcategoryLabel]setText:cellSubcategory.name]; return cell; } } else { if ([cardArray count] > 0) { static NSString *CellIdentifier = @"cardCell"; CardCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath]; AHCard *cellCard = [cardArray objectAtIndex:indexPath.row]; [[cell frontLabel]setText:cellCard.front]; return cell; } } // return nil; } 

只要取消注销return nil ,就可以了。 因为你最后的else处理所有的情况,所以代码将永远不会return nil ,但是Xcode的分析器显然不够聪明。

编辑:这个设置可以在生成设置,苹果LLVM 5.0 – 警告 – 所有语言。 它属于“不匹配的返回types”,默认为Yes,现在默认为Yes(视为错误)。 您可以更改此设置以将其更改回警告。 但我不会这样做的。 只是取消注销你的return nil ,这很好。

我会指出,在不返回值的情况下达到非void函数的结尾是一个错误,并且很可能导致崩溃,而返回nil(例如)可能不会。 考虑以下简单的例子:

 - (NSString*) someString { return nil; } // ... someplace elsewhere in the code: NSString* aString = [self someString]; NSLog( @"aString = %@", aString ); 

这很好,你的输出将是这样的:

aThing返回(null)

现在,如果你评论这个回报,那么:

 - (NSString*) someString { // return nil; } // ... someplace elsewhere in the code: NSString* aString = [self someString]; NSLog( @"aString = %@", aString ); 

NSLog调用将取消引用一些随机内存位置(无论发生在堆栈上,我认为),你的应用程序几乎肯定会崩溃。

如果你有一个函数返回某个types的值,它必须总是返回一个该types的值。

Edit2(回复@Dave DeLong的评论):好点,从collectionView:cellForItemAtIndexPath:返回nil 一个错误,但我可能会争辩说,这是一个不是简单地让函数结束没有返回值的错误。 事实certificate,这是有点学术的,因为OP的代码是这样的,最终return nil将永远不会执行,无论如何。

可以用这样的方法来重写函数,以避免警告并键入“return nil”,因此:

 - (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { id cell = nil; if (collectionView.tag == 0) { // Make a Subject cell } else if (collectionView.tag == 1) { // Make a Category cell. } else { // Make a Card cell. } return cell; } 

…但最终结果与OP的原始代码相同( return nil注释):该函数可以但不会返回nil。

Xcode是正确的抱怨在这里。 在代码中没有任何内容表明你的返回语句肯定会被调用。

  1. 如果你认为你的代码永远不会到达最后一行,或者它会在你的程序的其他地方显示一个bug,并且你不想试图优雅地退化,你应该在这里放置一个断言(例如assert(false); ),这个会使你的程序崩溃,而不是试图做一些你可能没有计划的事情。 assert被标记为无返回函数,编译器知道你的代码在这行之后不需要返回值。

  2. 如果你认为你的代码可能会到达最后一行(取决于潜在的错误传入数据),或者如果你想在代码中的其他地方出现错误,你应该优雅地退化,你应该决定在这里返回什么。 返回nil可能不是最好的主意,因为UICollectionView不会像这样的单元格(来自文档:“你不能从这个方法返回nil”),并会引发exception,最终导致崩溃(所以更好的崩溃你自己,因为它会更容易跟踪崩溃日志)。 当然,这种方法需要一些思考。

所以你只需要一个默认值。 这个方法实际上是基于表示对象中某些状态的样式。

只需使一个标签不被选中或select一个默认视图来返回没有标签匹配你的值的东西。