View代码结构的规定

iOS应用架构谈 view层的组织和调用方案

架构师不是写SDK出来交付业务方使用就没事儿了的,每家公司一定都有一套代码规范,架构师的职责也包括定义代码规范。按照道理来讲,定代码规范应该是属于通识,放在这里讲的原因只是因为我这边需要为View添加一个规范。

制定代码规范严格来讲不属于View层架构的事情,但它对View层架构未来的影响会比较大,也是属于架构师在设计View层架构时需要考虑的事情。制定View层规范的重要性在于:

提高业务方View层的可读性可维护性

防止业务代码对架构产生腐蚀

确保传承

保持架构发展的方向不轻易被不合理的意见所左右

在这一节里面我不打算从头开始定义一套规范,苹果有一套Coding Guidelines,当我们定代码结构或规范的时候,首先一定要符合这个规范。

然后,相信大家各自公司里面也都有一套自己的规范,具体怎么个规范法其实也是根据各位架构师的经验而定,我这边只是建议各位在各自规范的基础上再加上下面这一点。

viewController的代码应该差不多是这样:


View代码结构的规定_第1张图片

要点如下:

所有的属性都使用getter和setter

不要在viewDidLoad里面初始化你的view然后再add,这样代码就很难看。在viewDidload里面只做addSubview的事情,然后在viewWillAppear里面做布局的事情(勘误1),最后在viewDidAppear里面做Notification的监听之类的事情。至于属性的初始化,则交给getter去做。

比如这样:

#pragma mark - life cycle

- (void)viewDidLoad

{

[super viewDidLoad];

self.view.backgroundColor = [UIColor whiteColor];

[self.view addSubview:self.firstTableView];

[self.view addSubview:self.secondTableView];

[self.view addSubview:self.firstFilterLabel];

[self.view addSubview:self.secondFilterLabel];

[self.view addSubview:self.cleanButton];

[self.view addSubview:self.originImageView];

[self.view addSubview:self.processedImageView];

[self.view addSubview:self.activityIndicator];

[self.view addSubview:self.takeImageButton];

}

- (void)viewWillAppear:(BOOL)animated

{

[super viewWillAppear:animated];

CGFloat width = (self.view.width - 30) / 2.0f;

self.originImageView.size = CGSizeMake(width, width);

[self.originImageView topInContainer:70 shouldResize:NO];

[self.originImageView leftInContainer:10 shouldResize:NO];

self.processedImageView.size = CGSizeMake(width, width);

[self.processedImageView right:10 FromView:self.originImageView];

[self.processedImageView topEqualToView:self.originImageView];

CGFloat labelWidth = self.view.width - 100;

self.firstFilterLabel.size = CGSizeMake(labelWidth, 20);

[self.firstFilterLabel leftInContainer:10 shouldResize:NO];

[self.firstFilterLabel top:10 FromView:self.originImageView];

... ...

}

这样即便在属性非常多的情况下,还是能够保持代码整齐,view的初始化都交给getter去做了。总之就是尽量不要出现以下的情况:

- (void)viewDidLoad

{

[super viewDidLoad];

self.textLabel = [[UILabel alloc] init];

self.textLabel.textColor = [UIColor blackColor];

self.textLabel ... ...

self.textLabel ... ...

self.textLabel ... ...

[self.view addSubview:self.textLabel];

}

这种做法就不够干净,都扔到getter里面去就好了。关于这个做法,在唐巧的技术博客里面有一篇文章和我所提倡的做法不同,这个我会放在后面详细论述。

getter和setter全部都放在最后

因为一个ViewController很有可能会有非常多的view,就像上面给出的代码样例一样,如果getter和setter写在前面,就会把主要逻辑扯到后面去,其他人看的时候就要先划过一长串getter和setter,这样不太好。然后要求业务工程师写代码的时候按照顺序来分配代码块的位置,先是life cycle,然后是Delegate方法实现,然后是event response,然后才是getters and setters。这样后来者阅读代码时就能省力很多。

每一个delegate都把对应的protocol名字带上,delegate方法不要到处乱写,写到一块区域里面去

比如UITableViewDelegate的方法集就老老实实写上#pragma mark - UITableViewDelegate。这样有个好处就是,当其他人阅读一个他并不熟悉的Delegate实现方法时,他只要按住command然后去点这个protocol名字,Xcode就能够立刻跳转到对应这个Delegate的protocol定义的那部分代码去,就省得他到处找了。

event response专门开一个代码区域

所有button、gestureRecognizer的响应事件都放在这个区域里面,不要到处乱放。

关于private methods,正常情况下ViewController里面不应该写

不是delegate方法的,不是event response方法的,不是life cycle方法的,就是private method了。对的,正常情况下ViewController里面一般是不会存在private methods的,这个private methods一般是用于日期换算、图片裁剪啥的这种小功能。这种小功能要么把它写成一个category,要么把他做成一个模块,哪怕这个模块只有一个函数也行。

ViewController基本上是大部分业务的载体,本身代码已经相当复杂,所以跟业务关联不大的东西能不放在ViewController里面就不要放。另外一点,这个private method的功能这时候只是你用得到,但是将来说不定别的地方也会用到,一开始就独立出来,有利于将来的代码复用。



勘误1:其实在viewWillAppear这里改变UI元素不是很可靠,Autolayout发生在viewWillAppear之后,严格来说这里通常不做视图位置的修改,而用来更新Form数据。改变位置可以放在viewWilllayoutSubview或者didLayoutSubview里,而且在viewDidLayoutSubview确定UI位置关系之后设置autoLayout比较稳妥。另外,viewWillAppear在每次页面即将显示都会调用,viewWillLayoutSubviews虽然在lifeCycle里调用顺序在viewWillAppear之后,但是只有在页面元素需要调整时才会调用,避免了Constraints的重复添加。

你可能感兴趣的:(View代码结构的规定)