由於種種原因,所以到目前為止,我在公司的專案還是沒有用 Interface Builder,所有的 UI 完全用程式碼一行一行刻出來,當然這也包含 auto layout 相關的程式碼,那這些程式碼應該要放哪裡呢?
如果是一個 UIViewController
的話,程式碼架構大概長這樣:
- (void)viewDidLoad {
[super viewDidLoad];
[self setupConstraints];
}
- (void)setupConstraints {
// Create and add layout constraints to view and subviews.
}
如果是 UIView
的話,大概是這樣:
@interface CustomView()
@property (nonatomic, assign) BOOL didSetupConstraints;
@end
@implementation CustomView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Do something....
[self setNeedsUpdateConstraints];
[self updateConstraintsIfNeeded];
}
return self;
}
- (void)updateConstraints {
if (!self.didSetupConstraints) {
// Create and add constraints to self and subviews.
self.didSetupConstraints = YES;
}
[super updateConstraints];
}
@end
我在網路上看到的作法也都是這樣。UIViewController
還沒什麼問題,只是 UIView
還要多一個 BOOL 來判斷要不要加入 constraints,讓我感到很不自然,全身不舒服。
最近在爬文的時候,看到這一篇文章,裡頭提到了一段來自 Apple 工程師的回應:
In general, if the constraints will only be created once, it should be done in an initialization method (such as -init or -viewDidLoad, and so forth). Save -updateConstraints for things that are expected to change over the course of running the App.
如果你不會在程式運行途中去新增或移除 constraints,那就把建立 constraints 的工作放在 init
或 viewDidLoad
階段。中途會新增或移除的動作才放到 updateConstraints
。你可以建立 constraint 之後再修改它的 constant
屬性,這不算是新增或移除 constraint。
嗯,所以之後我可以開心的寫 auto layout 了:)
Update:
今天看到這一篇文章還有 WWDC 2015 的影片,覺得應該要更新一下我的結論:updateConstraints
因為會一次處理所有的 constraint,所以它的效能比較好,適合在需要「大量的新增、修改、刪除 constraints」的時候使用。如果你沒有遇到效能問題,那可以不用它。