初始化是两段式构造的第二步,对象实例只有经过该步骤之后,才是一个干净可以使用的对象。这种思想在很多编程语言中我们可以看到,比如C++。当然也有很多一段式构造的例子比如C语言。
而在OC中,初始化使我们进行对象自定义操作的开始。这里我们需要初始化一些当前类特有的属性的值,以保证后续业务逻辑能够够正常。比如当我们从xib文件中加载VC的使用我们会使用到函数:
1
|
- (instancetype _Nonnull)initWithNibName:(NSString * _Nullable)nibName bundle:(NSBundle * _Nullable)nibBundle
|
该函数将会通过传入的xib文件名和bundle来加载界面,并且初始化相关的数据。当然这是系统的函数。而我们更关注的是我们在这里应该做什么和可以做什么。
说句废话:要做对象实例的初始化。主要是变量的赋值操作。
For Exmaple:
1
2
3
4
5
6
7
8
9
10
11
|
- (instancetype) initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
{
self = [
super
initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if
(!self) {
return
self;
}
_payHandler = [BDWalletPayWebHandler
new
];
_payHandler.enviromentWebViewController = self;
return
self;
}
|
上面的例子中我们在该函数中初始化了一个_payHandler的变量。而且细心的读者可能发现,我们用于初始化这个变量的值还不是外部传进来的,而是内部新生成的。这种方式我们称之为内部初始化。自然也会有外部初始化。
-
内部初始化:变量的值在内部生成。
-
外部初始化:用于初始化成员变量的值是在外部生成,然后传给。
而在实际的初始化场景中我们经常会发现这样的情况:在进行类的设计的时候,遇到传值的问题的时候,比如下述问题,我们通过VC1获取了用户的姓名,要向VC2进行传递。现在的一般做法是在定义VC2的时候,在头文件中暴漏name变量。
1
2
3
|
@interface B : UIViewController
@property (strong) NSString* name;
@end
|
然后使用的时候这个样子:
1
2
3
|
B* vc = [B
new
];
vc.name = @
"xx"
;
[self.navigationController push:vc];
|
这种做法,封装性很差,任何持有VC2实例的地方都能够修改这个name值,导致一些很奇怪的逻辑。而且往往是那种不可预期的变动。一旦出现bug查找起来极其困难。
其实这种情况应当属于外部初始化的典型应用。更好的方式就是我们就把name当成对象初始化必须的一个变量,需要对其进行初始化,那么就应当提供相应的函数来进行初始化。这样可以保持比较好的封装性。
建议以后采取这样的方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// .h
@interface VC2 : UIViewController
- (instancetype) init UNAVAILABLE;
- (instancetype)initWithName:(NSString*)name;
@end
//.m
@interface VC2 : UIViewController ()
{
NSString* _name;
}
@end
@implatation VC2: UIViewController
- (instancetype)initWithName:(NSString*)name
{
self = [
super
init];
if
(!self)
return
self;
_name = name;
return
self;
}
@end
|
在.h文件中进行变量声明的时候,如果不需要外部多次修改的变量,就不要暴漏了,做成私有变量,如果该变量初始化时所需的,那么就写成初始化函数哈。因为@property这种语法的存在,削弱了OC中作用域的概念,从而导致了大家对于publick,private,protected等概念不是很清晰,从初始化这个事情上可见一斑。然,这些概念对于程序的健壮性又是多么的至关重要。还是应该拾起来的。
常用的函数
1
2
3
|
- init;
- (instancetype _Nonnull)initWithNibName:(NSString * _Nullable)nibName bundle:(NSBundle * _Nullable)nibBundle
- (instancetype _Nonnull) initWith****
|
其中init函数为所有OC对象都有的