在Switch Case中声明UI对象 [英] Declaring UI Objects in Switch Cases

查看:148
本文介绍了在Switch Case中声明UI对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经了解了切换案例的范围,跳转标签等等,但是这里提出的建议解决方案似乎意味着添加大括号会绕过这个问题。但是,这似乎仍然不起作用:

I've read about the scope of switch cases, being jump labels and all, but the suggested solutions here at SO seem to imply that adding curly braces would circumvent the issue. However, this still doesn't seem to work:

switch (objectType) {

  case label:   //label is an integer constant
    NSLog(@"statement before declaration");
    UILabel *control = [[UILabel alloc] init];       //no error
    break;

  case button:  //button is an integer constant
    {
      UIButton *control = [[UIButton alloc] init];   //no error
    }
    break;    

  default:
    break;
}

// error when trying to use the *control* variable,
// Use of undeclared identifier 'control'

有没有办法用switch语句来完成这个?

Is there any way to accomplish this with switch statements?

2015年5月23日:尝试了许多不同的方法,但没有成功。

23rd May 2015: been trying many different approaches to no success.

编辑:实施Cyrille建议时的错误解决方案:

UIView *control = nil;
switch (objectType)
{
  case label:  //button is an integer constant
    {
      control = [[UILabel alloc] init];   //no error

      //error: property 'text' not found on object of type 'UIView *'
      control.text = @"Something...";     
    }
    break; 

  default:
    break;
}

显然,即使从 UIView 重铸后也是如此 UILabel ,该对象未继承 UILabel 的所有属性,因此错误:

Apparently, even after being recast from UIView to UILabel, the object did not inherit all the properties of UILabel, and thus the error:

在'UIView *'类型的对象上找不到属性'text'

甚至Zil建议在类型前加上(UILabel *) [[UILabel alloc] init]; 不起作用。

Even Zil's suggestion to prefix the type (UILabel*)[[UILabel alloc]init]; did not work.

有没有人让这个工作?

DUNCAN C的解决方案。 (见下面接受的答案)

    UIView *control = nil;
    switch (objectType)
    {
        case label:  
            control = [[UILabel alloc] init];
            ((UILabel *)control).text = @"Something...";     
            break; 

        default:
            break;
    }

    // UI object instantiated inside switch case recognised!
    ((UILabel *)control).textColor = [UIColor redColor];

谢谢Duncan C.

推荐答案

Objective-C中的范围规则非常简单。每次输入一对花括号时,都会输入一个新的范围。在该范围内声明的任何变量仅存在于该范围内。退出大括号时,变量不再存在。

The rules for scope in Objective-C are pretty simple. Any time you enter a pair of curly braces, you enter a new level of scope. Any variable declared inside that scope only exists inside that scope. When you exit the braces, the variable ceases to exist.

交换机内的各个案例不需要大括号,因此它们不定义本地范围的范围,但整个switch语句确实使用大括号,因此它确实定义了一个本地范围。在switch语句的大括号内声明的任何变量都不存在于大括号外。

The individual cases inside a switch don't need braces, so they don't define a local level of scope, but the entire switch statement does use braces, and so it does define a local scope. Any variable declared inside the switch statement's braces doesn't exist outside the braces.

当您输入新的作用域级别时,您可以访问父作用域中声明的所有内容。

When you enter a new level of scope you have access to everything declared in your parent scope.

你没有完全清楚你想做什么。我 THINK 你想要做的是拥有一个父类的变量,然后在其中放入来自子类的新对象,并且仍然可以访问它们的唯一属性子类。

You don't make it completely clear what it is you want to do. I THINK what you want to do is have a variable of a parent class, and then put new objects in it that are from subclasses, and still have access to the unique properties of the child class.

如果声明基类的变量,则可以将任何属于该类型子类的对象分配给变量。

If you declare a variable of a base class, you can assign any object that is a subclass of that type to the variable.

如果要访问子类的属性,则必须将变量强制转换为适当的类型:

If you want access to the properties of the subclass, through, you have to cast the variable to the appropriate type:

UIView *control = nil;
switch (objectType)
{
  case label:  
    control = [[UILabel alloc] init];   //no error

    ((UILabel *)control).text = @"Something...";     
    break; 
  case button: 
    control = [UIButton buttonWithType: UIButtonTypeSystem];
    [((UIButton *)control) setTitle: "Foo" forState: UIControlStateNormal];
  default:
    break;
}



编辑



我发现转换语法很难打字,而且会让人感到困惑。有时创建对象实际类型的新临时变量更清楚,做你需要做的任何事情,然后将它分配给目标变量,如下所示:

EDIT

I find the casting syntax to be a pain to type, and it can get confusing. Sometimes it's clearer to create a new temporary variable of the object's actual type, do whatever you need to do, and then assign it to the target variable, like this:

UIView *control = nil;
switch (objectType)
{
  case label:  
    UILabel *aLabel = [[UILabel alloc] init];   //no error

    aLabel.text = @"Something...";   
    aLabel.someOtherProperty = someOtherValue;
    control = aLabel;  
    break; 
  case button: 
    UIButton aButton = [UIButton buttonWithType: UIButtonTypeSystem];
    [aButton setTitle: "Foo" forState: UIControlStateNormal];
    control = aButton
  default:
    break;
}

在switch语句之外,你不会知道控件的对象类型变量包含,因此您只能访问UIView基类的属性,除非将变量转换为特定类型,如上所示。

Outside the switch statement, you won't know which type of object the control variable contains, so you will only be able to access the properties of the UIView base class, unless you cast the variable to the specific type, as shown above.

(请注意,上面的名称control是一个糟糕的选择,因为标签不是控件。最好使用像aView这样的名称,它暗示了变量中可能包含的所有对象的公共类。)

(Note that the name "control" above is a bad choice, since a label is not a control. Better to use a name like "aView" that implies the common class of all objects that might be in the variable.)

这篇关于在Switch Case中声明UI对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆