以编程方式创建 UILabel、UITextField 等时的图形错误

Posted

技术标签:

【中文标题】以编程方式创建 UILabel、UITextField 等时的图形错误【英文标题】:Graphical Bugs while programmatically creating UILabel, UITextField, etc 【发布时间】:2009-11-03 09:44:54 【问题描述】:

我以编程方式创建了一个登录视图和一个表格视图。

在某些我无法重现的情况下,会出现一些奇怪的视觉错误:

文本中某些字母的字体大小与其他字母不同 最初不显示边框但仅在您单击它时才显示的按钮。在同样的情况下,按钮的边框可以显示在 UITextField 中,而不是占位符(见截图) 一个标签出现在不正确的位置,而是在上面提到的文本字段中,倒置(我还没有设法截取这个)

下面,我添加了两张截图,大部分应用都黑屏了,只显示了错误:

http://uppix.net/b/c/4/dd1e41acb94b7d0ad8eb173772e97.png http://uppix.net/b/f/2/a5993440c07753b851701068330be.png

在这里您可以看到文本与不同的字体大小混合在一起。

此错误不会定期发生或无法重现。

我在下面添加了登录屏幕的代码:

 // Implement loadView to create a view hierarchy programmatically, without 
 // using a nib.
     - (void)loadView 
     UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
     UIFont* font = [UIFont systemFontOfSize:14];

 float midLine = 100.0;
 float height = 30.0;
 float borderY = 70.0;
 float borderX = 10.0;
 float width = 320.0 - borderX * 2.0;
 float paddingX = 10.0;
 float paddingY = 5.0;

 CGRect usernameLabelRect = CGRectMake(borderX, borderY, midLine, height);
 CGRect usernameFieldRect = CGRectMake(borderX + midLine + paddingX, borderY, 
                               width - midLine - paddingX - 40 , height);

 CGRect passwordLabelRect = CGRectMake(borderX, borderY + height + paddingY,
                               midLine, height);
 CGRect passwordFieldRect = CGRectMake(borderX + midLine + paddingX, 
                               borderY + height + paddingY, 
                               width - midLine - paddingX - 40, height);

 CGRect loginButtonRect = CGRectMake(borderX + 40, 
                               borderY + height*2 + paddingY*2, width - 80, 
                               height);

 //CGRect warningRect =  CGRectMake(borderX,
 //                         borderY * height * 3.0 + paddingY *3.0, 
 //                         width, height);
 CGRect warningRect =  CGRectMake(borderX, 175, width, 40);

 UILabel* usernameLabel = [[UILabel alloc] initWithFrame:usernameLabelRect];

 usernameLabel.textAlignment = UITextAlignmentRight;
 usernameLabel.font = font;
 usernameLabel.text = @"Username:";

 UILabel* passwordLabel = [[UILabel alloc] initWithFrame:passwordLabelRect];
 passwordLabel.textAlignment = UITextAlignmentRight;
 passwordLabel.font = font;
 passwordLabel.text = @"Password:";


 usernameField = [[UITextField alloc] initWithFrame:usernameFieldRect];
 [usernameField setBorderStyle:UITextBorderStyleRoundedRect];
 //[usernameField setPlaceholder:@"<Username>"];
 usernameField.font = font;
 usernameField.autocapitalizationType = UITextAutocapitalizationTypeNone;
 usernameField.autocorrectionType = UITextAutocorrectionTypeNo;

 passwordField = [[UITextField alloc] initWithFrame:passwordFieldRect];
 passwordField.font = font;
 [passwordField setBorderStyle:UITextBorderStyleRoundedRect];
 //[passwordField setPlaceholder:@"<Password>"];
 passwordField.autocapitalizationType = UITextAutocapitalizationTypeNone;
 passwordField.autocorrectionType = UITextAutocorrectionTypeNo;
 passwordField.secureTextEntry = YES;

 loginButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
 loginButton.frame = loginButtonRect;
 [loginButton setTitle: @"Einloggen" forState:UIControlStateNormal];
 [loginButton setTitleColor:[UIColor blackColor]
                                    forState:UIControlEventTouchDown];
 loginButton.contentVerticalAlignment =
                                    UIControlContentVerticalAlignmentCenter;
 loginButton.contentHorizontalAlignment =
                                    UIControlContentHorizontalAlignmentCenter;
 [loginButton addTarget:self action:@selector(OnLoginClicked:)
                          forControlEvents:UIControlEventTouchUpInside];
 [loginButton setBackgroundColor:[UIColor clearColor]];

 warningLabel = [[UILabel alloc] initWithFrame:warningRect];
 warningLabel.font = font;
 warningLabel.numberOfLines = 3;
 warningLabel.text =
 @"Wenn Sie die Applikation jetzt schließen, so werden Ihre Logindaten verworfen.";

 [myView addSubview:usernameLabel];
 [myView addSubview:passwordLabel];
 [myView addSubview:usernameField];
 [myView addSubview:passwordField];
 [myView addSubview:loginButton];
 [myView addSubview:warningLabel];
 /*
 [usernameLabel release];
 [passwordLabel release];
 [usernameField release];
 [passwordField release];
 [loginButton release];
 [warningLabel release];
 */
 self.view = myView;
 [myView release];

【问题讨论】:

这里是另一个屏幕截图:uppix.net/b/f/2/a5993440c07753b851701068330be.png 如您所见,在这种情况下,“Einloggen”按钮没有显示任何按钮。通常它有。您还可以看到用户名标签的占位符显示“边框”而不是其实际占位符 您发布的登录屏幕是使用 Interface Builder 的主要示例。您基本上只是放置一些控件并设置许多可以由 Interface Builder 处理的属性。为登录视图制作单独的 Xib 并在需要时加载它是可行的方法。自己在代码中设置视图很容易出错,而且更直观。由于重叠控件等,更容易提前发现问题。为什么需要在代码中进行设置? 【参考方案1】:

我无法在脑海中处理所有屏幕定位,但在我看来,您的许多字段都重叠:这是故意的吗?也许这就是原因?我通常在代码中创建视图,但这可能是 IB 的一种情况!

您没有显示表格视图的任何代码,但是在将子视图添加到单元格之前,我似乎遇到了类似的问题,然后下次使用 DequeueReusableCell 将单元格排入队列时,您再次添加子视图而不检查它们是否存在或清除它们。这会导致各种重叠,就像第一个屏幕截图一样。

【讨论】:

【参考方案2】:

问题是我从 Not-The-Main-Thread 调用 UIKit 消息,这会导致各种图形问题。通过使用 performSelectorOnMainThread: 在我的代码中的几个地方解决它=)

【讨论】:

以上是关于以编程方式创建 UILabel、UITextField 等时的图形错误的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Swift 以编程方式创建 UILabel?

以编程方式创建UILabel

以编程方式创建的 UILabel 未在旋转时调整大小

UIAppearance 未对以编程方式创建的 UILabel 生效

添加填充到以编程方式创建的UILabel

在 UIView 中以编程方式创建的 UILabel 未更新