以编程方式设计目标视图 - C
Posted
技术标签:
【中文标题】以编程方式设计目标视图 - C【英文标题】:programmatically Design a View in objective - C 【发布时间】:2015-06-21 20:07:43 【问题描述】:我的项目是设计一个没有故事板或 Nib 的带有大量标签、图像、文本字段的视图。我是否需要手动分配并将每一件事添加到视图中?我认为这太过分了,但我不知道如何以其他方式做到这一点。示例:
UILabel *firstLabel =[UILabel alloc] init];
firstLabel.frame = (0,x,20,10) ;
firstLabel.text = ...;
firstLabel.font = ...;
firstLabel.textColor = ...;
.................
[self.view addSubView:firstLabel];
UILabel *secondLabel =[UIlabel alloc] init];
secondLabel.frame = (0,y,20,10);
secondLabel.text = ...;
secondLabel.font = ...;
secondLabel.textColor = ...;
.................
[self.view addSubView:secondLabel];
UILabel *thirdLabel =[UIlabel alloc] init];
thirdLabel.frame = (0,z,20,10);
thirdLabel.text = ...;
thirdLabel.font = ...;
thirdLabel.textColor = ...;
.................
[self.view addSubView:thirdLabel];
我应该把它们都放在viewDidLoad
或loadView
或init
方法中吗?
或者我只需要为CreatLabel
制作一个方法并一次又一次地使用它?怎么做?
【问题讨论】:
【参考方案1】:如果我对您的理解正确,您会问如何将 DRY(不要重复自己)应用于此代码。
«Two of more — use a for» Edsger W. Dijkstra
或
«两个以上 - 使用枚举» vikingosegundo
- (void)viewDidLoad // or loadView, see Rob's answer
[super viewDidLoad];
NSArray *properties= @[@@"color": [UIColor orangeColor], @"text": @"Ceterum censeo",
@@"color": [UIColor cyanColor], @"text": @"Carthaginem esse",
@@"color": [UIColor purpleColor], @"text": @"delendam"];
[properties enumerateObjectsUsingBlock:^(NSDictionary *properties, NSUInteger idx, BOOL *stop)
UILabel *l = [[UILabel alloc] initWithFrame:CGRectMake(0, (idx + 1) * 20, 200, 20)];
l.backgroundColor = properties[@"color"];
l.text = properties[@"text"];
l.font= [UIFont italicSystemFontOfSize:12];
[self.view addSubview:l];
];
好的,为什么我更喜欢这里基于块的枚举? 因为它有一个突变保护,并免费为我提供了框架所需的正确索引。
A C for
-loop for (int idx = 0; idx < [properties count]; ++idx)
给了我正确的索引,但我必须包含一个额外的语句来获取对象 NSDictionary *property = properties[idx];
并且因为它没有突变保护:它可以在迭代期间更改,这可能会导致错误东西。
快速枚举for(NSDictionary *property in properties)
具有这样的突变保护,甚至比块枚举更快。但它有一个很大的缺点,如果我需要索引,我必须调用NSUIndex idx = [properties indexForObject:property];
导致二次运行时性能而不是线性:再见,速度优势。更糟糕的是:如果一个数组包含相同的对象,它只会重复找到第一个对象——很可能会创建错误数据。
根据代码的数量,将其移入辅助方法可能会很有用——但这更多是为了品味。
由于你最后的问题是关于可读性的,我想分享另一个品味问题:我喜欢将对象创建封装到一个不同的范围内:
通过使用隐式块
UILabel *label = ^
UILabel *l =[[UILabel alloc] initWithFrame:CGRectMake(0, (idx + 1) * 20, 200, 20)];
l.backgroundColor = properties[@"color"];
l.text = properties[@"text"];
l.font= [UIFont italicSystemFontOfSize:12];
return l;
();
[self.view addSubview:label];
或语句表达式
UILabel *label = (
UILabel *l =[[UILabel alloc] initWithFrame:CGRectMake(0, (idx + 1) * 20, 200, 20)];
l.backgroundColor = properties[@"color"];
l.text = properties[@"text"];
l.font= [UIFont italicSystemFontOfSize:12];
l;
);
[self.view addSubview:label];
【讨论】:
【参考方案2】:如果您以编程方式从头开始创建视图,您可以在 loadView
中执行此操作。 (参见Creating a View Programmatically。)但是,如果您有***视图的NIB/故事板并且您只是添加子视图,那么您可以在viewDidLoad
中执行此操作。
关于创建一堆标签,是的,你可以使用子程序。或者,假设有一个规则模式指示它们的位置,您甚至可以使用for
循环,在其中增加y
坐标或构建约束。 (您可以将这些视图的引用保存在一个数组中,或者使用 tag
值来跟踪它们。)但是无论您怎么做,是的,您都希望尽量减少您编写的重复代码的数量(从维护的角度,如果没有别的)。
【讨论】:
请注意,自从 WWDC2015 以来,Apple(终于!!!)不鼓励使用tag
来跟踪观看次数。见Cocoa Touch Best Practices【参考方案3】:
可以放入ViewDidLoad(),但如果标签数量较多,请使用自定义方法。
【讨论】:
以上是关于以编程方式设计目标视图 - C的主要内容,如果未能解决你的问题,请参考以下文章