使用Objective-C的+(void)initialize初始化static变量
2016-06-02 09:47
507 查看
在《Objective C类方法load和initialize的区别》一文中,我介绍了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
在我们的程序,我们有一个
#import <Foundation/Foundation.h>
#import "Printer.h"
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;
}
从上边的例子,我们看出
其实,static变量也可以定义在类方法的里面,这也是个实现的方法。
@implementation Printer
+ (int)available {
static int available = 1;
return available;
}
//other methods
@end
只是这样做有几个不便利的地方。第一,在我们的其它方法中如果想要使用available变量的时候,就不能直接写变量名,而要写成
这样字代码就不那么简洁了。
第二,因为Objective-C的方法是没有访问域的约束的,所有方法实际上都是public的。虽然,如果我们不在
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;
@implementation Printer
+ (void)initialize {
if (!instance) {
instance = [[Printer alloc] init];
}
}
+ (Printer *)instance {
return instance;
}
//other methods
@end
因为对于单例的初始化有线程安全的问题,而Apple的文档中明确指出
manner”。我们就不需要在
另外,如果static变量是方法外部作为全局变量的话,那么它放在
(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来,如果该对象没有被释放,那么我们就无法构造出另一个来进行打印。
#import <Foundation/Foundation.h>
#import "Printer.h"
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变量。
相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- 讲解iOS开发中基本的定位功能实现
- iOS中定位当前位置坐标及转换为火星坐标的方法
- js判断客户端是iOS还是Android等移动终端的方法
- iOS应用开发中AFNetworking库的常用HTTP操作方法小结
- iOS应用中UISearchDisplayController搜索效果的用法
- IOS开发环境windows化攻略
- iOS应用中UITableView左滑自定义选项及批量删除的实现
- iOS中UIAlertView警告框组件的使用教程
- iOS开发之路--微博“更多”页面
- 浅析iOS应用开发中线程间的通信与线程安全问题
- 检测iOS设备是否越狱的方法
- Objective-C的内省(Introspection)用法小结
- .net平台推送ios消息的实现方法