iOS 用宏定义写一个单例(Singleton)

用如下方法定义单例

@interface

singleton_interface(ClassName);

@end

实现单例在

@implemention

singleton_implemention(ClassName);

@end

 1 #define singleton_interface(class) + (instancetype)shared##class;
 2 #define singleton_implementation(class)\
 3 static class *_instance;\
 4 \
 5 + (id)allocWithZone:(struct _NSZone *)zone \
 6 {\
 7     static dispatch_once_t onceToken;\
 8     dispatch_once(&onceToken, ^{\
 9         _instance = [[super allocWithZone:NULL] init];\
10     });\
11 \
12     return _instance;\
13 }\
14 \
15 + (instancetype)shared##class \
16 {\
17     if(_instance == nil){\
18         _instance = [[class alloc] init];\
19     }\
20 \
21     return _instance;\
22 }\
23 \
24 - (id)copyWithZone:(struct _NSZone *)zone\
25 {\
26     return [class shared##class];\
27 }
 

但是 有时编译会出现错误:

duplicate symbol __instance in:

......class1.o

......class2.o

ld: 1 duplicate symbol for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

解决方法:

点击项目:

TARGETS-->Build Setting-->Apple LLVM 7.0 Code Generation -->No Common Blocks -->No

 

原因:我的理解,相同的代码块被两个类同时应用,commond + B build 时,编译器有时会误认为生成两个 目标文件是完全相同的。故而,要设置允许编译器识别有相同的代码块。实验:新建一个类 Director.h & Director.m,在 Director.h里导入Singleton.h

1 #import <UIKit/UIKit.h>
2 #import "Singleton.h"
3 @interface Director : UIViewController
4 singleton_interface(Director);
5 @end

在Director.m里:

1 #import "Director.h"
2 
3 @implementation Director
4 singleton_implementation(Director);
5 @end

再随便在新建一个类ViewController,在 viewController.h里导入Director.h

ViewController.h:

1 #import "Director.h"
2 
3 @interface ViewController : UIViewController
4 
5 
6 @end

ViewController.m

 1 #import "ViewController.h"
 2 
 3 @interface ViewController ()
 4 
 5 @end
 6 
 7 @implementation ViewController
 8 
 9 - (void)viewDidLoad {
10     [super viewDidLoad];
11 
12     Director *d1 = [[Director alloc]init];
13     Director *d2 = [Director sharedDirector];
14     Director *d3 = [d1 copy];
15     
16     NSLog(@"d1:%p\n,d2:%p\n,d3:%p",d1,d2,d3);
17 }

打印结果:地址完全一样

补充:

void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);其中第一个参数predicate函数,

dispatch_once_t 是一个predicate谓词,他约束后面的代码快在整个APP 里只被执行一次。而且该函数是GCD提供的线程安全的函数。 

posted @ 2016-06-24 15:06  wjwdive  阅读(614)  评论(0编辑  收藏  举报