1

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

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

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

有没有办法告诉编译器“此时我知道这otherBall是 a BBBallView,所以不要再告诉我它不响应这些选择器和属性”?这样,一个人可以写:

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修复它,但没有帮助任何后续行给出错误,例如“isEnlarged在类型'const __strong id'的对象上找不到属性”,所以我回到第一方。

我什至不确定为什么会发生这种情况:当变量是 type 时,编译器不应该置身事外id吗?无论如何,在需要对对象的属性执行多次计算的方法中,整个考验尤其混乱,因为所有这些括号很快就会变得不可读。

有没有办法解决?

提前致谢!

4

2 回答 2

4

您可以创建具有正确类型的本地临时文件,也可以不使用点表示法。

  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];
          /* ... */
        }
      }
    }
    

如果我只做几件事,我会很想不使用点符号。如果阅读变得尴尬并且有很多访问权限,那么我会考虑本地临时

于 2013-04-25T14:05:47.490 回答
1

我认为您正在苦苦挣扎,因为逻辑似乎放错了地方。语言与你对抗是因为你的程序结构,而不是因为语言有缺陷。

子视图的父类型真的合适吗?或者您是否违反了 Liskov 替换原则,将圆形物体塞入方形中?

您还可以问,从外部检查 BBBallView 逻辑的内部是否真的合适?您可以将逻辑移动到适当的类中吗?

于 2013-04-25T14:05:03.723 回答