以编程方式设计目标视图 - 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];

我应该把它们都放在viewDidLoadloadViewinit方法中吗?

或者我只需要为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的主要内容,如果未能解决你的问题,请参考以下文章

在目标 c 中以编程方式替换菜单视图

目标 c:iOS 13+ 以编程方式设置初始根视图控制器

如何在 ios 9 中以编程方式导航到另一个具有“当前上下文”表示的视图控制器,目标 C

从目标视图控制器推送新的视图控制器(swift)

C语言程序设计每日一题

以编程方式设置视图