几个非常有用的宏

单例定义宏

#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函数省力多了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值