博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Objective-C的+(void)initialize初始化static变量
阅读量:5329 次
发布时间:2019-06-14

本文共 2887 字,大约阅读时间需要 9 分钟。


在《》一文中,我介绍了Objective-C对待+(void)initialize+(void)load两个方法在编译和执行时出现的不同。而这些不同也是在使用时应该非常注意的地方。不过文章里面我没有讲这两个方法在Objective-C中究竟有什么实用价值。

其实+(void)initialize可以视为C#,Java中的静态构造函数。有了这个方法,我们就不用像C++自己另找途径来了。不过Objective-C中又有一些很不同的地方,因为Objective-C里不能把数据成员限定为static或者const。也就是说,虽然Objective-C可以定义类方法,但是类不能有数据成员。所以也不存在静态数据成员初始化的问题。

不过作为C语言的超集,Objective-C依然可以沿用C的一些特点了定义的全局变量来作为类静态成员。

举个简单的例子:

//header file@interface Printer : NSObject-(void)print:(NSString *)content;@end//implementation filestatic int available;@implementation Printer+ (void)initialize {    available = 1;}- (id)init {    if (available <= 0) {        NSLog(@"No available printer");        return nil;    }        if (self = [super init]) {        available--;    }    return self;}-(void)print:(NSString *)content {    NSLog(@"%@", content);}-(void)dealloc {    available++;    [super dealloc];}@end

在我们的程序,我们有一个Printer类可以构造对象来打印一些内容,但是Printer不是无限,比如我们这里只有一个,于是我们就能构造出一个Printer来,如果该对象没有被释放,那么我们就无法构造出另一个来进行打印。

int main(int argc, const char * argv[]){    @autoreleasepool {                Printer *printer = [[Printer alloc] init];        [printer print:@"Print..."];        Printer *printer2 = [[Printer alloc] init];        NSLog(@"%@",printer2);        [printer release];        printer2 = [[Printer alloc] init];        NSLog(@"%@",printer2);    }    return 0;}

 

Print...No available printer(null)

从上边的例子,我们看出+(void)initialize方法正确的为available变量进行了初始化。

其实,static变量也可以定义在类方法的里面,这也是个实现的方法。

 

@implementation Printer+ (int)available {    static int available = 1;    return available;}//other methods@end

 

只是这样做有几个不便利的地方。第一,在我们的其它方法中如果想要使用available变量的时候,就不能直接写变量名,而要写成
Printer::available();

这样字代码就不那么简洁了。

第二,因为Objective-C的方法是没有访问域的约束的,所有方法实际上都是public的。虽然,如果我们不在@interface中声明+ (int)available方法,编译器会在该方法被调用时给出警告,但是因为@implementation中定义了+ (int)available方法,运行时依然可以执行并得到正确的返回结果。而且还可以 NSObject的- (id)performSelector:(SEL)aSelector方法来规避警告。因此我们也就失去了静态变量的对外部的隐藏性。另一方面,因为我们还察觉到我们无法对方法内静态变量进行修改,于是又失去了类内部的共享性。

Objective-C中对于static变量,使用最多的地方,应该还是在。比如上边Printer类我们实际只有一个,就可以定义单例方法。

@implementation Printer+ (Printer *)instance {    static Printer *instance = nil;    if (!instance) {        instance = [[Printer alloc] init];    }        return instance;}//other methods@end

 

不过个人认为将static Printer *instance = nil;定义在方法外边作为全局变量,然后用+(void)initialize进行初始化,+ (Printer *)instance方法只返回变量会更好了。

static Printer *instance = nil;@implementation Printer+ (void)initialize {    if (!instance) {        instance = [[Printer alloc] init];    }}+ (Printer *)instance {        return instance;}//other methods@end
因为对于单例的初始化有线程安全的问题,而Apple的文档中明确指出
+(void)initialize
调用是
“in a thread-safe manner”
。我们就不需要在
+ (Printer *)instance
考虑线程安全性问题了。

另外,如果static变量是方法外部作为全局变量的话,那么它放在@implementaion内还是外并没有关系,编译器都把它当做C的语法进行编译,并限定该变量是该文件内可访问。所以即使把static变量定义放在某个类的@implementaion里面,假如该文件里还其他类的@implementaion,依然可以访问到该static变量。

 

References:

转载于:https://www.cnblogs.com/zsw-1993/p/4879504.html

你可能感兴趣的文章
js 页面定时刷新
查看>>
win7 jenkins 修改主目录
查看>>
Git学习笔记--日常基本使用
查看>>
nuget使用
查看>>
关于一类最小割图的建法
查看>>
Django---自定义admin组件思维导图
查看>>
输入一个链表,反转链表后,输出链表的所有元素。
查看>>
转如何用九条命令在一分钟内检查Linux服务器性能?
查看>>
win7下 go语言开发环境搭建(64bit)
查看>>
JavaScript权威指南--客户端存储
查看>>
leetcode Group Anagrams
查看>>
关于set和setsecure方法
查看>>
Django:(博客系统)使用使用mysql数据&创建post/category/tag实体,并同步到数据中...
查看>>
前端常用CSS小技巧
查看>>
LCT
查看>>
[POJ2406&POJ1961]用KMP解决字符串的循环问题两例
查看>>
传值调用与引用调用
查看>>
JZOJ 5922. sequence
查看>>
Object-C Xcode 编译提示 note: please rebuild precompiled header ZWYLPrefixHeader
查看>>
使用InternetGetConnectedState判断本地网络状态(C#举例)
查看>>