单例定义宏
#define SINGLETON_H +(instancetype)sharedInstance;
#define SINGLETON_M \
+ (instancetype)sharedInstance {\
static id instance = nil;\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{instance = [[super allocWithZone:nil] init];});\
return instance;\
}\
+ (instancetype)allocWithZone:(NSZone *)zone {return [self sharedInstance];}\
- (instancetype)copyWithZone:(NSZone *)zone {return self;}
其中SINGLETON_H用于sharedInstance的声明,放在头文件
SINGLETON_M用于sharedInstance的实现,放在m文件
类swift的 var let宏
我们可以在OC中也是用var let来定义变量,跟swift一样也可以类型推断:
#define let __auto_type const
#define var __auto_type
为分类添加属性
我们可以用 addPropertyForCatagory 这个宏,给分类增加属性。
大概原理:用关联对象增加实例变量,用runtime方法增加setter和getter方法
#define addPropertyForCatagory(CLASS, PROPERTY) \
dynamic PROPERTY; \
\
static void *theDistinctKey_ ## CLASS ## _ ## PROPERTY = &theDistinctKey_ ## CLASS ## _ ## PROPERTY; \
\
__attribute__((constructor)) \
static void ext_ ## CLASS ## _ ## PROPERTY ## _implement (void) { \
Class cls = objc_getClass(# CLASS); \
objc_property_t property = class_getProperty(cls, # PROPERTY); \
NSCAssert(property, @"类%@中找不到%s属性", cls, # PROPERTY); \
\
ext_propertyAttributes *attributes = ext_copyPropertyAttributes(property); \
if (!attributes) { \
NSLog(@"拷贝%@.%s属性失败", cls, # PROPERTY); \
return; \
} \
\
NSCAssert(!attributes->weak, @"不支持weak属性(%@.%s)", cls, # PROPERTY); \
\
objc_AssociationPolicy policy = OBJC_ASSOCIATION_ASSIGN; \
switch (attributes->memoryManagementPolicy) { \
case ext_propertyMemoryManagementPolicyRetain: \
policy = attributes->nonatomic ? OBJC_ASSOCIATION_RETAIN_NONATOMIC : OBJC_ASSOCIATION_RETAIN; \
break; \
\
case ext_propertyMemoryManagementPolicyCopy: \
policy = attributes->nonatomic ? OBJC_ASSOCIATION_COPY_NONATOMIC : OBJC_ASSOCIATION_COPY; \
break; \
\
case ext_propertyMemoryManagementPolicyAssign: \
break; \
\
default: \
NSCAssert(NO, @"错误的修饰符 %i", (int)attributes->memoryManagementPolicy); \
} \
\
id getter = ^(id self){ \
return objc_getAssociatedObject(self, theDistinctKey_ ## CLASS ## _ ## PROPERTY); \
}; \
\
id setter = ^(id self, id value){ \
objc_setAssociatedObject(self, theDistinctKey_ ## CLASS ## _ ## PROPERTY, value, policy); \
}; \
\
if (!class_addMethod(cls, attributes->getter, imp_implementationWithBlock(getter), "@@:")) { \
NSCAssert(NO, @"给属性 %@.%s 增加 getter方法 %s 失败", cls, # PROPERTY, sel_getName(attributes->getter)); \
} \
\
if (!class_addMethod(cls, attributes->setter, imp_implementationWithBlock(setter), "v@:@")) { \
NSCAssert(NO, @"给属性 %@.%s 增加 getter方法 %s 失败", cls, # PROPERTY, sel_getName(attributes->setter)); \
} \
\
free(attributes); \
}
WEAK和STRONG宏
#define WEAK( x ) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
__weak __typeof__(x) __weak_##x##__ = x; \
_Pragma("clang diagnostic pop")
#define STRONG( x ) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
if (__weak_##x##__ == nil) return;\
__typeof__(x) x = __weak_##x##__; \
_Pragma("clang diagnostic pop")
主要用于解决escaping类型的Block容易引起循环引用的问题。
用这两个宏定义self后,可以直接用self关键字访问成员变量,不必使用weakSelf,避免了开发人员误用self的情况。使用了这两个宏之后,在Block里面self是局部变量,可以直接使用,不必使用weakSelf
GCD宏
#define EXECUTE_BLOCK_IN_MAIN_BEGIN dispatch_async(dispatch_get_main_queue(), ^{
#define EXECUTE_BLOCK_IN_BKGND_BEGIN dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
#define EXECUTE_BLOCK_END });
我们用 EXECUTE_BLOCK_IN_MAIN_BEGIN 和 EXECUTE_BLOCK_END宏包裹一段代码,可以实现让包裹代码加入主队列执行
我们用 EXECUTE_BLOCK_IN_BKGND_BEGIN 和 EXECUTE_BLOCK_END宏包裹一段代码,可以实现让包裹代码加入系统默认的后台队列执行
比自己默写dispatch函数省力多了