我有时喜欢将IB元素组织到NSArray
中,主要是为了帮助我组织元素。通常,不同类别的对象使它们彼此成为相同的数组。虽然这个 是一种方便的组织方式,但我似乎无法理解为什么如果我有这样的数组:
NSArray *array = [NSArray arrayWithObjects:((UITextField *)textField), ((UISegmentedController *)segmentedController), nil];
当我像这样放置for
循环时,为什么会出现“不响应选择器”消息:
for (UITextField *text in array) {
[text setText:@""];
}
for
循环似乎传递的是不属于UITextField
类的对象。
如果指定数组中的所有对象都通过循环传递,则声明对象类的重点是什么?
编辑仅供参考,这就是我现在处理它的方式:
for (id *object in array) {
if ([object isMemberOfClass:[UITextField class]]) {
foo();
} else if ([object isMemberOfClass:[UISegmentedController class]) {
bar();
}
}
答案 0 :(得分:10)
当你这样做时
for (UITextField *text in...
数组中的对象指针被强制转换为UITextField *类型 - 所以如果对象实际上不是UITextField,如果你试图调用UITextField方法,可能会发生各种奇怪的事情。
所以改为使用id类型(no * needed,btw):
for (id obj in array)
然后检查类型并调用相应的方法。或者,过滤数组以仅获取特定类型的对象,然后仅使用该类型:
for (UITextField* text in [array filteredArrayUsingPredicate:...])
编辑:这是如何构建类过滤谓词:
答案 1 :(得分:5)
如果指定数组中的所有对象都通过循环传递,则声明对象类的重点是什么?
类名就是让编译器知道它应该找到什么。这允许它试图找出它应该让你调用的方法以及如何处理对象。这与将int
传递给采用float
的方法的想法相同。该方法不会忽略整数 - 它假设您传递的是正确的类型。你只是给这个结构一点点的信用额度:
for (UITextField *text in array)
它没有那个功能。你现在如何处理它是正确的方法。
答案 2 :(得分:0)
当您 运行 该代码时,您确定没有收到错误消息吗? “不响应选择器”消息是运行时错误,而不是编译时错误。编译器不知道数组中的对象是否实现-setText:
,但当您实际将该消息发送到UISegmentedControl
的实例时,您肯定会收到错误。
另一种可能性是你有一个名为UISegmentedController
的类,它有一个-setText:
方法。实现多部分条形图用户界面窗口小部件的类的名称是UISegmentedControl
。因此,您要显示的代码不是真实的,经过测试的代码,或者您有一个我们不了解的类。