1

我觉得这很奇怪。所以我有一个UIView并且我想改变textcolor所有的UILabel。这是我所做的:

for (UILabel *label in [self subviews]) { // self is the UIView
    label.textColor = someColor;
}

当我运行代码时,它因错误而崩溃UIImageView: unrecognized selector setTextColor: sent to instance (some instance)

所以看起来label快速枚举中的UIImageView. 顺便说一句,我确实有两个UIImageView. UIView *self但是,快速枚举不应该UILabel只给出(因为我指定UILabel *label而不是UIView *label)?

我认为这是问题所在,因为当我编写以下代码时,它可以工作。

for (UILabel *label in [self subviews]) { // self is the UIView
    if ([label isKindOfClass:[UILabel class]]) {
        label.textColor = someColor;
    }
}

所以在这段代码中,当我检查以保证它label是 aUILabel然后设置它textcolor时,视图中的所有UILabels 都会正确地改变它们的颜色。

有人可以解释为什么我需要if-statement仔细检查实例类型吗?

4

6 回答 6

5

您的 2 个循环非常不同。第一个假设所有子视图都是标签,第二个检查每个子视图以确保它是一个标签。第一个也应该检查。

快速枚举基本上是语法糖,它只是一个正常的for循环。它不会神奇地过滤或操作您给它枚举的列表。

于 2013-08-04T14:24:52.733 回答
5

您将枚举读作“我的子视图中每个 UILabel 的循环”,但这并不是它真正的工作原理——快速枚举不会进行任何智能过滤​​,它只是一个捷径。你应该把它读作“我的子视图中的每个对象的循环,它们是 UILabels”。而且因为并非每个子视图实际上都是 UILabel,所以在尝试将它们全部视为一个时会遇到问题。

该数组中的每个对象都是一个UIView虽然,所以更有说服力的语法是:

for (UIView * view in self.subviews) {
    if ([view isKindOfClass:[UILabel class]]) {
        UILabel * label = (UILabel *)view;
        // do something with label...
    }
}
于 2013-08-04T14:32:31.000 回答
2

在第一个循环中,您正在迭代主视图的所有子视图,而在第二个 for 循环中,您仍在迭代所有对象,但只修改 UILabel 类型的元素。

您的主视图可以包含所有类型的视图,例如 UIImageView UILabel 等.....枚举 UIlabel 作为数据类型实际上并不会更改它的数据类型,也不会仅枚举该类型的元素。

于 2013-08-04T14:27:22.457 回答
0

更优雅:标记您的标签。

#define kLabelOffset 100;

for (int i=kLabelOffset +1; i < totalLabels; i+) {
   UILabel *label = (UILabel*) [self viewWithTag:i];
   label.textColor = someColor;
}
于 2013-08-04T14:32:19.767 回答
0

[self subviews] 返回一个 NSArray,其中包含指向 UIViews 的 (id) 指针。这些可以是任何类型的视图,包括 UILabel。因此,如果特定子视图不支持 setTextColor,您将收到无法识别的选择器消息。因此,您确实需要 isKindOfClass 测试,或者您可以使用更通用的 respondsToSelector 测试。

于 2013-08-04T14:34:48.013 回答
0

在目标 C 中,我们没有类型转换。仅仅通过使用快速枚举并将该变量分配给 UILabel 不会将其类型转换为 UILabel。这就是崩溃的原因。我们可以使用 respondsToSelector 或使用 isKindOfClass 来使代码按预期工作。

于 2013-08-05T05:06:12.480 回答