我已经阅读了关于切换案例的范围,跳转标签以及所有这些,但是这里的建议解决方案似乎暗示添加花括号会绕过这个问题。但是,这似乎仍然不起作用:
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语句完成这个?
2015年5月23日:尝试了许多不同的方法,但没有成功。
编辑:实施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 的所有属性,因而错误:
在'UIView *'类型的对象上找不到属性'文字'
即使Zil建议使用(UILabel*)[[UILabel alloc]init];
类型作为前缀也不起作用。
有没有人让这个工作?
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.
答案 0 :(得分:2)
Objective-C中的范围规则非常简单。每次输入一对花括号时,都会输入一个新的范围。在该范围内声明的任何变量仅存在于该范围内。退出大括号时,变量不再存在。
交换机内的个别情况不需要支撑,因此它们不会定义本地范围的范围,但整个switch语句确实使用大括号,所以它确定了本地范围。在switch语句的括号内声明的任何变量都不存在于大括号之外。
当您输入新的范围级别时,您可以访问父范围中声明的所有内容。
你不能完全清楚自己想要做什么。我THINK
你想要做的是拥有一个父类的变量,然后在其中放入来自子类的新对象,并且仍然可以访问子类的唯一属性。
如果声明基类的变量,则可以将任何作为该类型子类的对象分配给变量。
如果要访问子类的属性,则必须将变量强制转换为适当的类型:
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;
}
我发现转换语法很难输入,而且会让人感到困惑。有时可以更清楚地创建对象的实际类型的新临时变量,做你需要做的任何事情,然后将它分配给目标变量,如下所示:
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基类的属性,除非你强制转换变量到特定类型,如上所示。
(注意名称" control"上面是一个糟糕的选择,因为标签不是一个控件。最好使用类似" aView"这意味着共同的类可能在变量中的所有对象。)
答案 1 :(得分:1)
是的,只需在切换前声明通用control
:
UIView *control = nil;
switch (objectType) {
case label: //label is an integer constant
NSLog(@"statement before declaration");
control = [[UILabel alloc] init]; //no error
break;
case button: //button is an integer constant
{
control = [[UIButton alloc] init]; //no error
}
break;
case other:
control = [[UIView alloc] init]; // works too
default:
break;
}
NSLog(@"Control frame is %@", NSStringFromCGRect(control.frame));
答案 2 :(得分:1)
将控件声明为UIView *
后,如果您尝试访问UIView上不存在的属性,则会出现错误。
然而,正如Duncan C所说,你总是可以使用点表示法强制转换和访问该属性,例如:
((UILabel *)control).text = @"This Works";
然后访问值
NSLog(@"Control text: %@", ((UILabel *)control).text);
我的目的是使用不同的方法,将控件声明为id
并使用Objective-C方法调用。您需要确保控件响应您尝试调用的选择器。如果您想在尝试访问选择器时保护应用程序崩溃,可以使用respondsToSelector:
方法。
我的建议的一个例子:
unsigned objectType = 1;
id control = nil;
switch (objectType) {
case 1: //label is an integer constant
NSLog(@"statement before declaration");
control = [[UILabel alloc] init]; //no error
[control setText:@"a"];
break;
case 2: //button is an integer constant
{
control = [[UIButton alloc] init]; //no error
}
break;
default:
break;
}
NSLog(@"Control text %@", [control text]);
结果是:
2015-05-23 13:12:06.840 test2[46589:12231454] statement before declaration
2015-05-23 13:12:06.841 test2[46589:12231454] Control text `a`
希望有所帮助:)
答案 3 :(得分:0)
问题是你的control
变量是在switch语句的范围内声明的,然后你试图在外面使用它:
UILabel *controlLabel = nil;
UIButton *controlButton = nil;
/*
I've defined two variables but you could do the same with one like so
id control = nil;
or
UIControl *control = nil;
*/
switch (objectType) {
case label: //label is an integer constant
NSLog(@"statement before declaration");
controlLabel = [[UILabel alloc] init]; //no error
break;
case button: //button is an integer constant
{
controlButton = [[UIButton alloc] init]; //no error
}
break;
default:
break;
}
if (controlLabel) {
} else if (controlButton) {
}