NSIndexPath的row属性为什么是有符号整数?
它是否会取到“有效”的负值?
编辑
直到我将LLVM设置为检查符号比较时,我才想到这个问题。这使得编译器在indexPath.row <= [someArray count]
或类似语句中发出警告。
NSIndexPath的row属性为什么是有符号整数?
它是否会取到“有效”的负值?
编辑
直到我将LLVM设置为检查符号比较时,我才想到这个问题。这使得编译器在indexPath.row <= [someArray count]
或类似语句中发出警告。
使用负值并不明智,如果使用,您将得到疯狂的结果。
NSIndexPath* path = [NSIndexPath indexPathForRow:-2 inSection:0];
上述结果中,一个部分的值为0,另一个行的值为4294967294(对我来说看起来像是NSUInteger
下溢!)请放心,这仅在UIKit增加类别中发生,而不是在NSIndexPath本身中发生。从NSIndexPath
背后的概念来看,保留负值真的没有意义。那么为什么会这样呢?
来自OS X的核心对象NSIndexPath
使用NSUInteger
作为其索引,但是UIKit Additions使用NSInteger
。该类别仅在基础对象之上构建,但是使用NSInteger
而不是NSUInteger
并没有提供任何额外的功能。
为什么要这样工作,我不知道。我猜测(并且我强调只是猜测),这是在首次发布iOS时一个天真的API失误。当UITableView
在iOS 2中发布时,它使用NSInteger
进行各种事情(例如numberOfSections
)。想想看:这在概念上是不合理的,你不能有负数个部分。即使在iOS 6中,它仍然使用NSInteger
,以便不破坏与表视图之前的应用程序兼容性。
除了UITableView
之外,我们还有对NSIndexPath
的增加,它与表视图一起用于访问其行等。因为它们必须共同工作,所以它们需要兼容类型(在这种情况下是NSInteger
)。
要在全局范围内更改类型为NSUInteger
会破坏很多东西,并且为了安全的API设计,每个东西都需要重命名,以便NSInteger和NSUInteger的对应物可以安全地并排工作。苹果可能不想要这种麻烦(开发者也不想!),因此他们将其保留为NSInteger
。
numberOfSections
返回有符号整数是疯狂的。 - WDUK一个可能的原因是无符号类型很容易下溢。例如,在我的代码中,我使用了一个NSUInteger
变量来表示笔画宽度。我需要在这个笔画周围创建一个“包络”,因此编写了以下代码:
NSUInteger width = 3;
CGRect envelope = CGRectInset(CGRectZero, -width, -width);
NSLog(@"%@", NSStringFromCGRect(envelope));
使用无符号类型将输出{{inf,inf},{0,0}}
,使用有符号整数将得到{{-3,-3},{6,6}}
。原因是在width
变量之前的一元减号创建了下溢。这对某些人来说可能很明显,但会让很多程序员感到惊讶:
NSUInteger a = -1;
NSUInteger b = 1;
NSLog(@"a: %u, b: %u", a, -b); // a: 4294967295, b: 4294967295
因此,即使在不应使用负值的情况下(描边宽度不能为负),在负上下文中使用该值也是有意义的,从而导致下溢。切换到有符号类型可以减少惊喜,同时仍然保持范围相当高。听起来像是一个不错的妥协。
UITableView
返回 NSInteger
类型的方法,例如 (NSInteger)numberOfSections
,对您来说是有意义的吗?如果需要进行算术运算,请自行将 NSUInteger
转换为 NSInteger
。表格(及其相应的 NSIndexPath
)不必关心用户级别的算术运算。 - WDUKNSArray count
会返回NSUInteger
呢?这可能是算术中更常用的值。 - WDUK我认为NSIndexPath
上的UIKit附加功能故意使用NSInteger
类型。如果由于某种原因将负行作为parameter
传递给任何方法(尽管我目前没有看到任何方法...),则不会自动转换为NSIntegerMax + parameter
值,并且任何可能的对象都不会寻找不存在的荒谬大参数。尽管还有其他方法可以防止这种情况发生,但这可能只是一种口味问题。
例如,我不会在NSIndexPath
类中使用NSUInteger
作为参数,而是使用NSInteger
并检查符号,如果任何参数为负,则根本不会创建NSIndexPath
。
initWithRow:section:
采用NSInteger
. - WDUK