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 @   wjwdive  阅读(617)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示