在《Objective C类方法load和initialize的区别》一文中,我介绍了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的一些特点了定义static的全局变量来作为类静态成员。

举个简单的例子:

//header file
@interface Printer : NSObject
-(void)print:(NSString *)content;
@end//implementation file
static 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变量,使用最多的地方,应该还是在单例模式(Singleton Patten)。比如上边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:

  1. Static variable – Wikipedia
  2. What does “static” mean in a C program? – stackoverflow
  3. Class variable for Objective-C and C++ – JongAm’s blog
  4. Objective C Static Class Level variables – stackoverflow
  5. + (void)initialize – NSObject Class Reference

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

使用Objective-C的+(void)initialize初始化static变量相关推荐

  1. Java Static 变量初始化

    目录 Java Static 变量初始化 直接赋值 static块初始化 实例方法初始化 解决方案 Java Static 变量初始化 static变量初始化方式 直接赋值 static块初始化 实例 ...

  2. C++ static 变量和线程安全和单例模式

    static变量初始化顺序 1.1 全局变量.文件域的static变量和类的static成员变量在main函数执行之前初始化 1.2 局部静态变量在第一次被使用时初始化 static变量的线程安全 2 ...

  3. static 变量初始化顺序的问题和解决方案

    http://www.cppblog.com/yindf/archive/2009/03/20/77304.aspx 最近在coding的时候,写了这么一段代码: A.h 1// A.h 2#incl ...

  4. static变量初始化

    1.在C++中,全局static变量和class的static成员变量在main函数之前初始化,main函数之后销毁 2. 函数内部的局部static变量在该函数第一次被调用时初始化,在main函数之 ...

  5. java static 变量 初始化一次_关于java static变量初始化的疑问

    java中,类的static变量作为类变量,只需要被一次初始化,就可使用,但是,我在程序中遇到一个问题: 在web.xml中配置listener,服务器启动时,ServletContextListen ...

  6. 【通俗易懂学JAVA】——public void与public static void的区别

    通俗易懂学JAVA public void与public static void的区别 public void与public static void的区别 ●区别: 这两句的区别就在于,能不能直接用类 ...

  7. java static变量何时初始化_Java 静态变量何时初始化?

    小编典典 从请参阅Java静态变量方法: 它是一个属于类而不属于对象(实例)的变量 静态变量在执行开始时仅初始化一次.在初始化任何实例变量之前,将首先初始化这些变量 该类的所有实例共享一个副本 静态变 ...

  8. java中的static变量初始化_Java初始化静态变量的时间顺序

    1. 开始吧! 今天,我们来探讨交流下静态变量初始化过程.Java虚拟机在类加载期间也同样遵循这个过程. 2. 初始化过程 在较高的层次上,JVM执行以下步骤: 首先,加载并链接类.然后,这个过程的& ...

  9. C++中static变量的初始化

    作者:billy 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 前言 在C语言中,static变量如果初始化,那么初始化发生在任何代码执行之前,属于编译期初始化.全局变 ...

  10. (转)static 变量

    一. static 变量 static变量大致分为三种用法 1. 用于局部变量中,成为静态局部变量. 静态局部变量有两个用法,记忆功能和全局生存期. 2. 用于全局变量,主要作用是限制此全局变量被其他 ...

最新文章

  1. 说说对npm的开发模式和生产模式的理解
  2. java开发环境及数据类型实验_实验项目1 Java开发环境与语言基础
  3. caffe官网的部分翻译及NG的教程
  4. 为一路通(16tone)开博
  5. 最小化安装的redhat/centos安装gnome桌面
  6. js字体溢出字体变小_可变字体:它们是什么,以及如何使用它们
  7. word——VBA编程
  8. 互联网协议理解(入门)
  9. android 6.0 oem分区,android系统的分区结构
  10. 低通滤波器计算截止评率_了解奈奎斯特图中的截止频率
  11. 带自动还原魔方游戏源码
  12. C语言程序设计——从入门到进阶,C语言程序设计——从入门到进阶-巨同升主编.pdf(3)...
  13. C#反编译工具:.NET Reflector导出代码
  14. MATLAB | solve函数求解析解时不支持分段函数的解决方案
  15. 关于travis scott的网名_文案| 关于【太阳】的惊艳句子
  16. vs code修改代码后再次运行,报错:file“<stdin>“,line 1
  17. vue利用 vue-animate-number插件动态展示数字(从0动态滚动到指定数字)
  18. 1366 mysql_Mysql错误1366 - Incorrect integer value解决方法
  19. Listary中使用Everything搜索
  20. centos8.1安装amd显卡驱动操作记录

热门文章

  1. 翻译: 如何使用 Xcode 的内存图调试器检测 iOS 内存泄漏并保留周期
  2. 解决XCode运行app在模拟器上,提示模拟器不存在
  3. SSH免密码登录,搭建Flink standalone集群
  4. hadoop2.8配置_hadoop2.8安装教程
  5. opengl es坐标变换2
  6. 强化学习各概念整理(value/policy-based、on/off-policy、model-based/free、offline)
  7. 使用SecretScanner发现容器镜像和文件系统中的敏感数据
  8. Hvv近期0day总结一
  9. Modbus安全:M340停启和流量分析
  10. python测试开发工程师前景_对未来测试开发工程师的前景你怎么看?