由于我的应用程序有多个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
中调用完全相同的代码,情况会怎样?我怀疑它是因为sharedInstance是一个静态方法,并且UIViewController没有initWithNibName:bundle
的静态方法。
仍然,我想知道是否有办法绕过它,因为我不想每次需要使用它时都不必创建一个LoginViewController。
我也希望防止调用LoginViewController initWithNibName:bundle:
并获取单独的实例。
答案 0 :(得分:4)
+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]
并不一定要总是返回一个新对象,因为不需要区分两个不同的对象。
因此,您有两种选择:1)如果有人尝试创建其他LoginViewController
或2)允许创建其他LoginViewController
,则引发异常。第三个选项(3)只是返回sharedInstance,如果有人试图创建一个新的LoginViewController)打破了初始化的契约,这意味着它会向调用者返回一些他没想到的东西!如果调用者知道LoginViewController是单例,他应该使用+sharedInstance
。如果调用者不知道它,他应该获得异常或获得一个新的LoginViewController。