Obj-C内省:如何一直避免施法?

时间:2013-04-25 13:52:11

标签: objective-c casting enumeration introspection

大家好, 我一直在Objective-C中处理一些执行对象内省的枚举例程。特别是,在调整属性和/或调用方法之前,我正在快速枚举NSSet并确保其中的对象属于类BBBallView(一个相当不幸的名称,我同意)。 / p>

然而,为了使解析器和编译器满意,我最终将对象转换为每一行的类;此外,为了访问其属性,对象的强制转换必须在括号中,否则点符号将不起作用。这导致代码有些混乱:

for (id otherBall in self.gameField.subviews) {
    if ([otherBall isKindOfClass:[BBBallView class]]) {
        if ( !((BBBallView *)otherBall).isEnlarged ) {
            CGRect otherFrame = ((BBBallView *)otherBall).frame;
            /* ... */
        }
    }
}

有没有办法告诉编译器类似“此时我知道otherBallBBBallView,所以停止告诉我它不响应这些选择器和属性”?这样,人们可以写:

for (id otherBall in self.gameField.subviews) {
    if ([otherBall isKindOfClass:[BBBallView class]]) {
        if ( !otherBall.isEnlarged ) {
            CGRect otherFrame = otherBall.frame;
            /* ... */
        }
    }
}

等等。

我尝试otherBall = (BBBallView *)otherBall但是“默认情况下无法在ARC中修改快速枚举变量”。将枚举变量更改为__strong id会修复它,但无法帮助任何后续行都会发出错误,例如“const isEnlarged在类型为'const __strong id'”的对象上找不到的错误,所以我回到原点。

我甚至不确定为什么会发生这种情况:当变量属于id类型时,编译器是否应该避开?在任何情况下,对于需要对对象属性执行多次计算的方法,整个考验特别麻烦,因为所有这些括号很快就会变得不可读。

有什么方法吗?

提前致谢!

2 个答案:

答案 0 :(得分:4)

您可以使用正确的类型创建本地temp,也可以不使用点表示法。

  1. 本地临时

    for (UIView *view in self.gameField.subviews) {
      if ([view isKindOfClass:[BBBallView class]]) {
        BBBallView *ballView = view;
        if (!ballView.isEnlarged) {
          CGRect otherFrame = ballView.frame;
          /* ... */
        }
      }
    }
    
  2. 不要使用点符号

    for (id otherBall in self.gameField.subviews) {
      if ([otherBall isKindOfClass:[BBBallView class]]) {
        if ( ![otherBall isEnlarged]) {
          CGRect otherFrame = [otherBall frame];
          /* ... */
        }
      }
    }
    
  3. 如果我只做了几件事,我很想不使用点符号。如果它变得难以阅读并且有很多访问,那么我会考虑本地临时

答案 1 :(得分:1)

我认为你正在努力,因为逻辑似乎错位了。由于你的程序结构,语言正在打击你,而不是因为语言不足。

子视图的父类型是否真的合适?或者你是否通过在方形类型中填充圆形物体来违反Liskov替换原则?

您还可以询问从外部检查BBBallView逻辑的内部是否真的合适?你能把逻辑移到适当的班级吗?