我正在设置自定义UIButton,并且只需要将一组视图添加为子视图一次。
为了保持我的实施文件变得苗条,并且不要在initWithFrame:
中设置所有视图,只是让某人做button = [[Button alloc] init]; button.frame = someFrame;
之类的事情,我正在做以下事情;
- (void)layoutSubviews
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self setupViews];
});
}
- (void)setupViews
{
// add all subviews here
}
这一切对我来说都很好;我只是想知道我是否正在做一些不推荐的事情?
为了进一步扩展这个问题,将dispatch_once
放在一个不断被调用的方法中是否安全? (例如,在viewDidAppear
)中查看设置代码。
答案 0 :(得分:4)
layoutSubviews
不应该用于添加子视图,因为它被多次调用(旋转,状态栏高度变化等)
相反,在UIView子类的init
方法中添加子视图,并在layoutSubviews
中设置其框架。
答案 1 :(得分:3)
这适用于按钮的第一个实例。任何其他实例都不会执行dispatch_once
阻止。
dispatch_once
,因此不会为对象的每个实例调用此对象,因为onceToken
在实例之间保持不变。
[object layoutSubviews]
调用块,但随后......
[object2 layoutSubviews]
不会调用该块。
@interface TestObject : NSObject
- (void)log;
@end
@implementation TestObject
- (void)log {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"Called once");
});
}
@end
TestObject *ob1 = [[TestObject alloc] init];
TestObject *ob2 = [[TestObject alloc] init];
[ob1 log];
[ob2 log];
2013-12-16 11:59:34.760 test[43445:70b] Called once
这就是你得到的所有输出。由于ob1
已经投放,obj2
看到onceToken
已经执行过,并且不会再次执行。
答案 2 :(得分:1)
您应该只使用layoutSubviews来设置视图框架。如果您打算添加子视图,那么执行此任务的好地方是viewDidLoad Method或awakeFromNib。