美文网首页iOS New TimeOC进化iOS知识总结
iOS:学会使用宏,让工程更加高大上

iOS:学会使用宏,让工程更加高大上

作者: 被帅醒的小吴同志 | 来源:发表于2017-02-06 23:07 被阅读599次
    调用起来

    就像上面MJExtensionDeprecated实际上是一个用来提示已废弃

    我们来剖析一下上面定义宏的形式,很基础,希望帮助那些还在进步的coder们大神现在可以撤退啦

    #define MJExtensionDeprecated(instead)  NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead)
    

    我们发现除了可以定义一些静态的常量外,也是可以传参的,在上面instead就被作为参数传到了后面,NS_DEPRECATED是系统宏 :

    系统宏

    NS_DEPRECATEDNS_AVAILABLE这两个宏很常见,NS_DEPRECATED表示在什么版本以后被废除,其中四个参数分别表示mac os的版本以后废除的描述iOS版本以后废除的描述NS_AVAILABLE宏则表示什么版本以后可用。
    想必看到这就已经知道不再畏惧成堆的系统宏了,奥,原来MJExtensionDeprecated只是为了方便调用又重新定义了一遍,原来完全可以用:

    说到这里既然也可以传参去使用,那么我们是不是一下子想到了很多?
    譬如:

    //对于frame的定义
    #define Frame(x, y, width, height) CGRectMake((x),(y),(width),(height))
    
    //对于size的定义
    #define Size(width, height) CGSizeMake((width), (height))
    
    //针对于iphone6尺寸的实际高度和宽度
    #define HeightScale_IOS6(height) ((height/667.0) * Screen_height)
    #define WidthScale_IOS6(width) ((width/375.0) * Screen_width)
    
    //对于字体的定义:
    #define font(size) [UIFont systemFontOfSize:(size)]
    

    等等,只要你觉得方便的都可以去定义,甚至于我们还可以利用的特性去将一大串代码缩减至一句话(敲黑板了):
    譬如MJ的状态检查,当需要在很多方法内调用相同的代码时大可以去宏定义一个:

    // 状态检查
    #define MJRefreshCheckState \
    MJRefreshState oldState = self.state; \
    if (state == oldState) return; \
    [super setState:state];
    
    调用demo

    调用起来就一句话,如果这里有萌新,提示一下'\' 是换行符 不加入宏定义逻辑内。

    我们甚至可以去定义一些烦恼的长代码段,例如定义一个单例(这里的##双井号是连接符,意思是将class类名与shared进行拼接,比如当classCat时,wyh_singleton_interface(Cat)定义的就是+(instancetype)sharedCat):

    //.h
    #define wyh_singleton_interface(class) + (instancetype)shared##class;
    
    //.m
    #define wyh_singleton_implementation(class) \
    static class *_instance; \
    \
    + (id)allocWithZone:(struct _NSZone *)zone \
    { \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
    _instance = [super allocWithZone:zone]; \
    }); \
    \
    return _instance; \
    } \
    \
    + (instancetype)shared##class \
    { \
    if (_instance == nil) { \
    _instance = [[class alloc] init]; \
    } \
    \
    return _instance; \
    }
    

    在类的.h中就一行代码搞定~:

    
    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject
    
    wyh_singleton_interface(Person)
    
    
    @end
    
    
    #import "Person.h"
    
    @implementation Person
    
    wyh_singleton_implementation(Person)
    
    
    @end
    
    

    这样写完后,你便可以这样去创建一个Person的单例类:

    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        Person *per = [Person sharedPerson];
    }
    

    是不是很简单,很神奇,很高大上,,我们再举几个例子:

    NSAssert一般大神们都习惯去用的debug模式断言宏,这个宏是系统宏与NSCAssert差不多只不过一个OC用一个C用,想进一步了解一下这个宏的放传送门

    戳死我呀~

    示例

    经过上面的介绍想必我们已经可以看懂上面的系统宏定义,NSAssert(condition, desc, ...)需要传入两个参数conditiondesc,其中condition是条件判断,desc是如果不成立的描述。

    我们分析一下,当!(condition)也就是condition == NO的时候(即不成立的时候),NSAssertionHandler这个类的实例一般由系统自动创建,用于评估处理错误断言,如果NSAssert条件评估为NO,会向这个NSAssertionHandler实例发送一个错误描述desc,并且执行handleFailureInMethod:方法。

    简单的来讲,就是当condition == NO时,程序会抛出异常,并在控制台打印错误信息。
    好了到这就明白了,为什么大神都喜欢用NSAssert去断言,下面放个例子:

    - (void)viewDidLoad {
    
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        NSString *str = @"我是梁朝伟";
        
        NSAssert([str isEqualToString:@"我是刘德华"], @"当str是刘德华时才能享受待遇");
    
    }
    

    这时运行程序,我们会发现程序崩溃:

    示例2

    好了 现在是不是很清楚宏的作用了,那是不是我们项目中把所有常量都交给宏,定义一大堆宏就逼格够高啦?

    当然不是,因为如果一个项目过多的使用宏定义会增加程序预编译的时间,(因为宏是每次初始化都执行一次)这对debug调试来说无疑是不想看到的,所以一些静态常量就交给const修饰的常量吧(const常量初始化后只执行一次) ,这样就节约了程序运行的时间,普及一下const常量定义方法。

    //.h中声明定义
    UIKIT_EXTERN NSString * const HWPayReqCode;       
    
    UIKIT_EXTERN NSString * const HWHttpRequestCache; 
    
    UIKIT_EXTERN NSString * const HWLogoIconUrl;
    
    //.m中实现定义
    
    NSString * const HWPayReqCode = @"HWPayReqCode"; 
    
    NSString * const HWHttpRequestCache = @"HWHttpRequestCache";
    
    NSString * const HWLogoIconUrl = @"https://baidu.com";
    

    最后,合理利用宏和静态常量使得项目中的全局调用变得更方便更有序,这篇文章就是抽空写一点无任何难度但容易被人忽略的问题,希望大家赶紧get起来去定义属于你自己项目里的高大上的吧。

    相关文章

      网友评论

        本文标题:iOS:学会使用宏,让工程更加高大上

        本文链接:https://www.haomeiwen.com/subject/izbuittx.html