尝试强制转换为NSInteger *和NSMutableArray *时出错

时间:2013-03-08 19:44:26

标签: objective-c arrays cocoa-touch cocoa

我是对象中的新手。所以我有一个简单的问题。 我有一个NSInteger值的矩阵。它被称为“curBoard”。我想用值“curStep”更新(x,y)坐标处的值。我有一个恐怖的“操作数类型为void where arithmetic ...”

我做错了什么?

[curBoard replaceObjectAtIndex:x withObject:(NSMutableArray *)[[curBoard objectAtIndex:x] replaceObjectAtIndex:y withObject:(NSInteger *)[NSNumber numberWithInt:curStep]]];

更新

NSMutableArray *board; 
board = [NSMutableArray new]; 
for(NSInteger i = 0; i<boardSize; i++) { 
    NSMutableArray *row = [NSMutableArray new]; 

    for(NSInteger j = 0; j < boardSize; j++) 
        [row addObject:(NSInteger *)[NSNumber numberWithInt:0]]; 
        [board addObject:row]; 
    } 

2 个答案:

答案 0 :(得分:3)

withObject:(NSInteger *)[NSNumber numberWithInt:curStep]]部分是造成问题的原因。如果要存储为NSNumber对象,则应使用:

... withObject:[NSNumber numberWithInt:curStep]]

修改 从上面发布的代码中,您应该将其添加为:

[row addObject:[NSNumber numberWithInt:0]]; 

NSInteger不是指针类型,您应该使用NSNumber本身添加到数组。

答案 1 :(得分:2)

Objective-C基本上只是一堆绑在C上的对象语法。整体效果就像是将一个喷气背包捆绑在马上:有时两个部分并没有真正协同工作。在这种情况下,当你应该真正打开油门时,你会试图通过告诉马眩晕来加快速度。

NSMutableArray是jetpack的一部分 - 它是一个Objective-C对象,只能处理Objective-C对象的数组。但是NSInteger是马的一部分 - 它是一个原始的C整数类型,而不是一个真实的对象。*

我知道NSInteger像一个类一样大写,并且像类一样有NS前缀,但它实际上是C的生物。你可以在Xcode中自己确认类型Cmd-O并输入弹出“快速打开”对话框中的“NSInteger”,您将能够跳转到其定义。在我目前的Mac项目中,那是typedef long NSInteger;; long是原始C类型之一。

NSNumber存在以弥合这两者。它是专门用于在其中保存C数字类型的对象。由于NSNumber是一个对象,NSMutableArray和其他Objective-C事物可以处理它。

但你不能只在NSNumberNSInteger之间施放。 NSNumber在其中包含NSInteger,但这并不意味着它本身就是NSInteger。如果你把三明治放在塑料袋里,你就不能吃掉它。

相反,您必须使用NSNumber的{​​{1}}方法来构建+numberWithInteger:,并使用NSNumber来获取整数。 (-integerValue+numberWithInt:通常会有效,但根据您的应用是在32位还是64位处理器上运行,它们可能会因非常大的值而表现不同。)实际上,现在您可以请将-intValue改为[NSNumber numberWithInteger:foo],这要短得多。**

所以当你添加一个数字时,你应该说:

@(foo)

当你以后想要这个号码时,你会想要说:

[row addObject:@(0)];

n = [[row objectAtIndex:y] integerValue]; 错误是另一回事。 -replaceObjectAtIndex:withObject:根本不返回任何内容,因此您不能将其用作参数。幸运的是,在这种情况下你不需要。 -replaceObjectAtIndex:withObject:不会创建新数组;它会改变已在-replaceObjectAtIndex:withObject:内的数组,因此您无需对[curBoard objectAtIndex:x]执行任何操作。相反,你可以写:

curBoard

*您实际使用的是[[curBoard objectAtIndex:x] replaceObjectAtIndex:y withObject:@(curStep)]; ,这略有不同。 NSInteger *表示“指向”,因此*是指向原始整数的指针。这有点像NSInteger *,指向NSNumber *对象的指针,因此编译器允许您投射它。

请注意,转换指针不会转换指针另一端的数据;它只是让编译器以不同的方式解释相同的数据。如果您实际上尝试使用NSNumber指针来获取数据,那么您将获得垃圾数据或(因为太大而无法适应此边距的原因)崩溃。

但是,在这种情况下,一旦你让Jedi哄骗编译器认为值是指向NSInteger *的指针,你就会尝试将其传递给NSInteger-addObject:需要一个指向对象的指针,因此编译器会将指针传递给-addObject:

**只要你使用 iOS 6 SDK Xcode 4.4或更高版本,即使你真的在较旧的iOS上运行应用程序,这种语法也会有效。它还会自动为您使用正确的NSInteger方法,因此您无需担心选择最佳方法。当您使用像+numberWithWhatever:这样的数字文字时,括号是可选的,但在使用变量或常量时它们是必需的。当然,如果你愿意,你仍然可以采用罗嗦的方式,但现在没有什么意义。