[英]programmatically Design a View in objective - C
我的项目是设计一个具有多个标签,图像,textField的视图,而没有故事板或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
创建一个方法,然后一次又一次地使用它? 怎么做?
如果我正确理解您的要求,请问如何将DRY(不要重复自己)应用于此代码。
«更多两个–使用一个» 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];
}];
}
好的,为什么我在这里更喜欢这种基于块的枚举?
因为它有一个变种保护器,可以免费为我提供框架所需的正确索引。
AC 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];
如果要以编程方式从头开始创建视图,则可以在loadView
。 (请参阅以编程方式创建视图 。)但是,如果您具有用于顶层视图的NIB / storyboard,而您仅添加了子视图,则可以在viewDidLoad
。
关于创建一堆标签,是的,您可以使用子例程。 或者,假设有一个规则的模式来指示这些位置,那么您甚至可以使用for
循环,在其中增加y
坐标或构建约束。 (您可以将对这些视图的引用保存在数组中,也可以使用tag
值来跟踪它们。)但是,您可以这样做,是的,您希望减少重复编写的代码量(从维护的角度简化工作寿命) ,如果没有别的)。
可以放入ViewDidLoad(),但如果标签数量很多,请使用自定义方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.