美文网首页iOS常用优化
iOS 高性能OC一:tips

iOS 高性能OC一:tips

作者: Trigger_o | 来源:发表于2020-08-10 15:03 被阅读0次

    1.OC使用消息结构而非函数调用:
    运行时执行的代码由运行时环境决定,而非编译器,总是在运行时才会去查找所要执行的方法.编译器甚至不关心接收消息的对象的类型.
    OC的重要工作都由运行期组件完成,也就是Runtime component,而非编译器,对于OC对象所需要的数据结构和函数都在Runtime组件中,比如内存管理的方法就在其中,Runtime组件本质就是一个动态链接库.
    只需要更新运行时组件,就可以提升程序性能,或者修改一些特性,如果这些工作是编译器完成的,就需要重新打包编译了.

    2.关于头文件降低耦合:
    import会编译.h文件的全部内容,向前声明(@class)可以解决多余编译,也可以解决互相import的问题,但是当需要指定.h文件的内容的时候,比如协议中的方法,这时候必须import,因此可以把协议专门放在一个.h文件中(代理的协议除外).
    同理,遵循协议也不要放在.h文件中,而是应该创建分类,比如常在.m文件创建无名的分类,然后遵循<协议>.

    3.选择是否抛出异常:
    字面量创建,遇到nil会直接抛出异常,arrayWithObjects:则不会抛出异常,遇到nil的时候提前结束,可以根据业务逻辑进行选择,多数情况下,如果没有按照意愿创建数组,后面的逻辑基本是有问题的,因此没有特殊需要的话,还是字面量创建更好,便于定位问题.

        NSString *str = @"aaa";
        NSString *str2 = nil;
        NSString *str3 = @"bbb";
        NSArray *arr = [NSArray arrayWithObjects:str,str2,str3,nil];
    //    NSArray *arr2 = @[str,str2,str3];
        NSLog(@"arr=%@",arr);
        NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:str,@"1",str2,@"2",str3,@"3", nil];
    //    NSDictionary *dic = @[@"1":str,@"2":str2,@"3":str3];
        NSLog(@"dic=%@",dic);
    

    4.类型常量和预处理指令定义常量:

    define无法指定类型,语义不清晰,且只是简单替换,有出现错误替换的可能,使用静态变量更好.

    static const NSTimeInterval TRAnimationDuration = .3; //只在.m中使用
    
    //全局使用
    //声明
    extern NSString *const TRNotificationLoginSuccess;
    extern const NSTimeInterval TRAnimationDuration;
    //实现
    NSString *const TRNotificationLoginSuccess = @"TRNotificationLoginSuccess";
    NSTimeInterval const TRAnimationDuration = .3;
    

    5.关于enum:
    系统库常使用二进制表示枚举值左边的数字R是十进制,右边的数字n是左移位数,结果是左边数字的二进制进行左移,也就是R乘上n的二次方;
    使用时通过按位或进行赋值,通过按位与来判断是否包含.这样可以达到多项匹配的目的.

    typedef NS_OPTIONS(NSUInteger,TRenum){
        TRenumone   = 0,
        TRenumtwo   = 1 << 0,
        TRenumthree = 1 << 1,
        TRenumfour  = 1 << 2,
        TRenumfive  = 1 << 3
    };
    
    TRenum e = TRenumtwo | TRenumthree | TRenumfour;
        if(e & TRenumtwo){
            NSLog(@"TRenumtwo");
        }
        if(e & TRenumthree){
            NSLog(@"TRenumthree");
        }
        if(e & TRenumfour){
            NSLog(@"TRenumfour");
        }
    

    在C++11标准中,枚举增加了新特性,因此系统库通过宏编译来决定使用旧版还是新版来定义枚举.如下面的宏定义所示
    上面的例子中,使用的是NS_OPTIONS而非NS_ENUM,C++编译模式和非C++编译模式不一样,在用位运算操作两个枚举值时,C++认为结果的类型是一个无符号整数,也就是NSUInteger,并且C++是不能将这个值转换为枚举类型的,因此C++模式下使用另一个定义模式,NS_OPTIONS,省去了转换.

    #if (__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) || __has_feature(objc_fixed_enum))) || (!__cplusplus && __has_feature(objc_fixed_enum))
    #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
    #if (__cplusplus)
    #define NS_OPTIONS(_type, _name) _type _name; enum : _type
    #else
    #define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type
    #endif
    #else
    #define NS_ENUM(_type, _name) _type _name; enum
    #define NS_OPTIONS(_type, _name) _type _name; enum
    #endif
    

    但是我发现现在的iOSSDK的这一段宏是如下面所示.但,没有NS_OPTIONS的特别处理了.不过NS_OPTIONS鉴于依然是保留的,在定义需要组合的枚枚举是=时,依然使用NS_OPTIONS,类型是NSUInteger.

    #if ((__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) || __has_feature(objc_fixed_enum))) || (!__cplusplus && __has_feature(objc_fixed_enum))) && __has_attribute(ns_error_domain)
    #define __NS_NAMED_ERROR_ENUM(_domain, _name)     enum _name : NSInteger _name; enum __attribute__((ns_error_domain(_domain))) _name : NSInteger
    #define __NS_ANON_ERROR_ENUM(_domain)             enum __attribute__((ns_error_domain(_domain))) : NSInteger
    #else
    #define __NS_NAMED_ERROR_ENUM(_domain, _name) NS_ENUM(NSInteger, _name)
    #define __NS_ANON_ERROR_ENUM(_domain) NS_ENUM(NSInteger)
    #endif
    

    相关文章

      网友评论

        本文标题:iOS 高性能OC一:tips

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