由于我的应用程序有多个LoginViewController
没有意义,我尝试将单例模式与 initWithNibName 相结合,如下所示:
+ (instancetype)sharedInstance {
static id sharedInstance;
static dispatch_once_t once;
dispatch_once(&once, ^{
sharedInstance = [super initWithNibName:@"LoginViewController" bundle:nil];
});
return sharedInstance;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
NSLog(@"ignoring initWithNibName and calling sharedInstance");
// self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
// if (self) {
//
// }
return [LoginViewController sharedInstance];
}
问题是该行:
sharedInstance = [super initWithNibName:@"LoginViewController" bundle:nil];
给我这个错误:
No known class method for selector 'initWithNibName:bundle:'
那么,如果通常在initWithNibName:bundle
中调用完全相同的代码,情况如何呢?我怀疑这是因为共享实例是一个静态方法,而 UIViewController 没有用于initWithNibName:bundle
的静态方法。
不过,我想知道是否有办法解决它,因为我不想每次需要使用它时都创建 LoginViewController。
我还想防止调用LoginViewController initWithNibName:bundle:
并获得单独的实例。
+sharedInstance
是一个类方法,因此self
内部计算类LoginViewController
,super
引用类UIViewController。 -initWithNibNamed:bundle:
是一个实例方法。
static LoginViewController *sharedInstance;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if(sharedInstance) {
// avoid creating more than one instance
[NSException raise:@"bug" format:@"tried to create more than one instance"];
}
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self) {
// own initialization code here
}
return self;
}
+ (LoginViewController *)sharedInstance
{
static dispatch_once_t once;
dispatch_once(&once, ^{
sharedInstance = [[LoginViewController alloc] initWithNibName:@"LoginViewController" bundle:nil];
});
return sharedInstance;
}
与 -init
方法族有一个隐式契约,表示 alloc+init 应始终返回一个新对象或语义上与新对象无法区分的对象。 例如 [NSNumber numberWithInt:2]
不一定总是返回一个新对象,因为不需要区分两个不同的 2。
因此,您有两种选择:1( 如果有人尝试创建其他LoginViewController
,则引发异常,或 2( 允许创建其他LoginViewController
。第三个选项 ( 3( 如果有人尝试创建新的 LoginViewController ,则返回共享实例(破坏了初始化的约定,这意味着它将向调用者返回一些他没有预料到的东西!如果调用方知道 LoginViewController 是单例,则应使用 +sharedInstance
。如果调用方不知道这一点,他应该得到一个异常或一个新的 LoginViewController。