Ios 在布局子视图中使用dispatch_一次是否有任何问题?
我正在设置一个自定义UIButton,只需添加一次一组视图作为子视图。 使我的实现文件保持精简,避免在Ios 在布局子视图中使用dispatch_一次是否有任何问题?,ios,iphone,objective-c,ipad,Ios,Iphone,Objective C,Ipad,我正在设置一个自定义UIButton,只需添加一次一组视图作为子视图。 使我的实现文件保持精简,避免在initWithFrame:中设置所有视图,而只让某人执行类似button=[[button alloc]init]的操作;button.frame=someFrame,我正在执行以下操作: - (void)layoutSubviews { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{
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\u once
安全吗?(例如,视图中的视图设置代码显示为
)。布局子视图
不应用于添加子视图,因为它被多次调用(在旋转、状态栏高度更改等情况下)
相反,在UIView子类的
init
方法中添加子视图,并在layoutSubviews
中设置它们的帧,这将适用于按钮的第一个实例。任何其他实例都不会执行一次dispatch\u
块
仅当onceToken为NULL时才会调用,因此不会对对象的每个实例调用,因为onceToken
会跨实例持久化
[对象布局子视图]
调用块,但是
[object2布局子视图]
不调用块
2013-12-16 11:59:34.760测试[43445:70b]调用一次
这就是你得到的所有输出。由于
ob1
已经运行,obj2
会看到onceToken
已经执行,不会再次执行。您应该只使用布局子视图来设置视图框架。如果您计划添加子视图,执行此任务的好地方是viewDidLoad方法或awakeFromNib。为什么不使用viewDidLoad
进行此设置?您有多少个实例?@bdesham,无法使用viewDidLoad,因为它是一个子类UIButton。@Wain我计划有一个实例,但layoutSubviews将经常被调用。如果将来有多个实例,您可能会非常困惑。可能最好有一个BOOL
实例变量…嗨,亚伦,这是我过去常做的事,但我想摆脱对这个变量使用初始值设定项的习惯。在LayoutSubview中调度_是否应该类似于ARC下的单例模式?我们多次调用单例的共享实例初始值设定项,它包含一个dispatch\u once。。。我想对LayoutSubview做同样的事情也是一样的。因为所有的UI工作都应该在主线程上完成,所以你不需要一次dispatch\u
。如果(!someSubview),您可以使用。但是为什么要“放弃使用初始化器”而这正是初始化器的用途呢?我想对于UIButton,有些人可以使用initWithFrame、init和buttonWithTitle之外的任何一个。我正在尝试在init之外使用可行的替代方法,以避免定制所有三个。不幸的是,由于这是一个UIButton子类,并且我没有使用IB文件进行此操作,因此这两种方法都不适用。然而,我将尝试找出一种不同的方法来做到这一点。我唯一关心的是,我想在这个问题上摆脱自定义初始值设定项。这使得开发人员可以自由地为按钮使用任何他们想要的初始值设定项(initWithFrame、init、buttonWithTitle等)。如果是子类按钮,则只需在init方法上添加所有子视图。进一步考虑,我看得越多,就越觉得应该将此模式扔出窗口。如果我想给用户删除子视图的自由,就不可能再添加它们,因为只有一次dispatch_。然后在init中,您可以设置背景色或类似的内容。
@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];