我正在尝试以编程方式在我的应用程序中为我的故事板上的每个UILabels
生成两个UIImageView
。代码运行并正常工作,但是,首先在主视图的(0.0)坐标中加载两个UILabel表单,而不是UIImageView框架origin.x,origin.y。我不明白为什么会这样。
如果我然后单击其他选项卡并返回页面,标签将生成在正确的位置。
这是为什么?如何让它最初在正确的位置生成标签?
-(void) viewWillAppear:(BOOL)animated
{
//removed unneccessary code above...
int i = 0;
for (UIImageView *plantScreen in self.view.subviews)
{
if ([plantScreen isMemberOfClass:[Plant class]])
{
@try
{
//the label which will hold the name
UILabel *plantName = [[UILabel alloc] initWithFrame:CGRectMake((plantScreen.frame.origin.x), (plantScreen.frame.origin.y+ plantScreen.frame.size.height), 160, 30.0)];
plantName.numberOfLines = 1;
plantName.minimumScaleFactor = .5;
plantName.adjustsFontSizeToFitWidth = YES;
[plantName setTextAlignment:NSTextAlignmentCenter];
[plantName setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:plantName];
plantName.hidden = false;
[self.view bringSubviewToFront:plantName];
//create the label which will hold the quantity
UILabel *quantity = [[UILabel alloc] initWithFrame:CGRectMake((plantScreen.frame.origin.x), (plantScreen.frame.origin.y+ plantScreen.frame.size.height + 20), 160, 30.0)];
[quantity setTextAlignment:NSTextAlignmentCenter];
[quantity setBackgroundColor:[UIColor clearColor]];
quantity.text = [NSString stringWithFormat:@"%d",plant.quantity];
[self.view addSubview:quantity];
quantity.hidden = false;
[self.view bringSubviewToFront:quantity];
i++;
}
@catch (NSException *exception)
{
NSLog(@"An exception occured: %@", [exception reason]);
}
@finally
{
}
}
}
}
答案 0 :(得分:0)
首先,您错过了对[super viewWillAppear:animated]
的调用。你需要给超类(包括UIViewController
基类)一个“发挥其魔力”的机会。
永远不要忘记让父母有机会施展魔法,除非你真的非常清楚你正在做什么。
其次,UI创建应该在-loadView
中完成,而不是在viewWillAppear:
。
首先尝试这两件事。
好的。现在我很好奇 你把事情移到了-loadView
。您添加了[super loadView];
吗?
事实上,现在我考虑一下,在这种情况下转移到-loadView
是错误的;你显然通过笔尖实例化一些视图。 UIViewController
-loadView
的实现通常只会加载nib文件。完成后,UIViewController
-loadView
调用-viewDidLoad
。
因此,如果您没有以编程方式创建所有UI,而是允许UIViewController
从nib加载它,您实际上可能希望将代码移动到-viewDidLoad
。 (当您告诉它创建一个新的UIViewController
子类时,请参阅Xcode生成的模板。)
继续,让我们考虑一下框架所依赖的内容。这取决于您调用Plant
的某个视图类。
请不要这样称呼它;这令人困惑。称之为PlantView
,因此您的代码的随意读者会知道该类应该做什么。同样,您可能希望调用变量plantView
而不是plantScreen
和plantNameLabel
而不是plantName
。 plantScreen
表示包含UIScreen
的变量,而plantName
表示NSString
比隐含UILabel
更多。同样适用于quantity
;调用此变量quantityLabel
。
接下来,让我们考虑变量的依赖性 - 它们的原点x
和y
不会根据计数器变量i
而变化。也许你打算写:
UILabel *plantName = [[UILabel alloc] initWithFrame:CGRectMake((plantScreen.frame.origin.x), (plantScreen.frame.origin.y+ plantScreen.frame.size.height * i), 160, 30.0)];
以及后来:
UILabel *quantity = [[UILabel alloc] initWithFrame:CGRectMake((plantScreen.frame.origin.x), (plantScreen.frame.origin.y+ plantScreen.frame.size.height*i + 20), 160, 30.0)];
接下来,避免异常和异常处理。确保通过其他形式的检查不会发生异常; Apple highly recommends您在编写应用程序时修复异常,并在运行时不处理它们:
重要提示:您应该保留使用例外编程或 意外的运行时错误,例如越界集合访问, 试图改变不可变对象,发送无效消息,以及 失去与窗口服务器的连接。你经常照顾 当应用程序存在时,这些类型的错误和异常 创建而不是在运行时。
接下来,一个小风格的评论(不是很重要):你通过属性混合调用setter并直接调用setter。没有错(他们最终完全一样),但在风格上并不是很好。
接下来,除非您使用ARC(自动引用计数),否则不要忘记在将视图添加为子视图后将其释放。
接下来,plantScreen
(我将其命名为plantView
)在循环内声明时,可以将类型设置为Plant
(我将其命名为PlantView
。) p>
最后但非常重要且非常容易错过:您调用函数isMemberOfClass:
而不是isKindOfClass:
。
您的代码的重写版本(未经测试):
-(void)viewDidLoad
{
[super viewDidLoad];
int i = 0;
for (PlantView *plantView in self.view.subviews)
{
if ([plantView isKindOfClass:[PlantView class]])
{
//the label which will hold the name
CGRect plantNameLabelFrame = CGRectMake((plantScreenView.frame.origin.x),
(plantScreenView.frame.origin.y + plantScreen.frame.size.height*i),
160,
30.0);
UILabel *plantNameLabel = [[UILabel alloc] initWithFrame: plantNameLabelFrame];
plantNameLabel.numberOfLines = 1;
plantNameLabel.minimumScaleFactor = .5;
plantNameLabel.adjustsFontSizeToFitWidth = YES;
plantNameLabel.textAlignment = NSTextAlignmentCenter;
plantNameLabel.backgroundColor:[UIColor clearColor];
[self.view addSubview:plantNameLabel];
[plantNameLabel release];
//create the label which will hold the quantity
CGRect quantityLabelFrame = CGRectMake((plantScreenView.frame.origin.x),
(plantScreenView.frame.origin.y + plantScreen.frame.size.height*i + 20),
160,
30.0);
UILabel *quantityLabel = [[UILabel alloc] initWithFrame: quantityLabelFrame];
quantityLabel.textAlignment = NSTextAlignmentCenter;
quantityLabel.backgroundColor = [UIColor clearColor];
quantityLabel.text = [NSString stringWithFormat:@"%d", plant.quantity]; // NB: what's "plant"?
[self.view addSubview:quantityLabel];
i++;
}
}
}
我还删除了.hidden = false
(实际应该是.hidden = NO
;这是Objective-C,而不是C ++)和bringSubviewToFront:
(它已经在前面,刚刚由addSubview:
)添加。
答案 1 :(得分:0)
UIImageView
的框架取决于正在绘制的图像及其contentMode
属性。您可以尝试将contentMode
设置为UIViewContentModeScaleAspectFill
以查看它是否强制保留其指定的框架。