美文网首页
iOS - OC <<编写高质量iOS与OS X代码的多个有效方

iOS - OC <<编写高质量iOS与OS X代码的多个有效方

作者: 洧中苇_4187 | 来源:发表于2020-09-16 18:17 被阅读0次

    Objective-C语言有Smalltalk演化而来,是消息型语言.

    //Messaging (Objective-C)
    Object *obj = [Object new];
    [obj performWith:paramter1 and: paramter2];
    
    //Function calling (C++)
    Object *obj = new Object;
    obj->perform(paramter1, paramter2);
    

    区别

    消息结构语言: 其运行时所执行的代码由运行环境决定.
    函数调用语言: 由编译器决定.
    调用多态:
    1.函数通过虚方法表(virtual table)查找,到底该实行哪个函数;
    2.消息结构语言是在运行时才会查找所需执行的方法,这个过程叫动态绑定(dynamic binding),Objective-C 都是由运行期组建(runtime component)来完成的.

    1.在类的头文件中尽量少引入其他头文件

    这样做的好处就是,能够缩短编译时间,所以当你引入一个类,而不需要知道这个类的细节(比如:用到这个类的某些属性/方法),只是声明它,则只需@class PersonClass

    2.尽量多使用字面量语法,少用与之等价的方法
     NSArray *tmpArr = @[@1,@2,@"funking hard"];
        NSString *testStr = @"this is it";
        NSDictionary *tmpDic = @{
            @"last name" : @"Steve",
            @"hobtis" : @"see around",
            @"purpose" : @"making money"
        };
    这样的好处是一目了然,
    
    3.多用类型常量,少用#define 预处理指令
    static const NSTimeInterval kAnimationDuration = 0.3;
    

    3.1 >这样定义会确保常量值不变,不会无意中被人修改,从而导致应用程序各个部分所使用的值互不相同,因为试图修改都会编译器报错.
    3.2 >常量的命名习惯,建议以k字母开头,用类名区分,后面紧接着使用说明,比如kPersonClassAnimationDuration,就能很清楚的知道这是所属于PersonClass这个类,用作动画时长的常量
    3.3 >这样定义还可以标识类型,具有更多的参数信息.
    3.4> 如果你想对外界暴露一个常值变量,又不想他知道具体的字符串,可以这样

    //In the header file
    extern NSString *const kEOCNotificationConstant;
    
    //In the implementation file
    NSString *const kEOCNotificationConstant = @"kEOCNotificationConstant";
    
    4.用枚举表示状态,选项,状态码
    enum EOCConnectionStateConnettionState : NSInteger {
        EOCConnectionStateConnettionState_before,
        EOCConnectionStateConnettionState_replace,
        EOCConnectionStateConnettionState_after
    };
    

    你可以指定用什么类型存储该枚举类型,这样系统能更好的分配空间(默认系统的值是从 0 开始分配,)

    typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
        UIViewAutoresizingNone                 = 0,
        UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
        UIViewAutoresizingFlexibleWidth        = 1 << 1,
        UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
        UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
        UIViewAutoresizingFlexibleHeight       = 1 << 4,
        UIViewAutoresizingFlexibleBottomMargin = 1 << 5
    };
    

    这种枚举类型就可以进行 "或" 运算,

    如果需要按位或操作来组合的枚举都应该使用 NS_OPTIONS来定义
    不需要按位或 则 用enum ,NS_ENUM,(因为编译分为C++和非C++编译,底层会做判断,是否支持新枚举特性,即指派存储类型,所以在定义上会有差别)

    枚举使用:
    如果你指定了一个可选类型 NSComparisonResult,则前面要加上 typedef
    typedef NS_ENUM(NSInteger, NSComparisonResult) {
        ...
    };
     
     如果没有,就应该这样写...
    NS_ENUM(NSInteger) {
        ...
    };
    
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
        switch (orientation) {
            case UIInterfaceOrientationUnknown:
            {
                NSLog(@"位置状态");
            }
            break;
            case UIInterfaceOrientationPortrait:
            {
               NSLog(@"竖屏状态");
            }
            break;
            case UIInterfaceOrientationPortraitUpsideDown:
            {
              NSLog(@"倒竖屏状态");
            }
            break;
            case UIInterfaceOrientationLandscapeLeft:
            case UIInterfaceOrientationLandscapeRight:
            {
             NSLog(@"左右状态");
            }
            break;
            //default:
            //break;
        }
    

    在处理枚举类型的switch语句中,不要实现default分支,这样的话加入新枚举之后,编译器就会提示开发者:switch语句并未处理所有枚举

    5. 属性的一些细节

    应用程序二进制接口 (Application Binary Interface ABI),其中定义了生成代码时所赢遵循的规范.


    图1
    这是我看到所有对属性解释中,最清晰简洁的
    //In header file 
    @property (copy) NSString *firstName;
    @property (copy) NSString *lastName;
    
    //In implementation file
    - (id) initWithFirstName:(NSString *)firstName
                             lastName:(NSString *)lastName;
    {
          if ((self = [super init])) {
             _firstName = [firstName copy];
             _lastName = [lastName copy];
         }
         return self;
    }
    

    iOS开发相比于 Mac OS X开发,使用atomic通常不会有性能瓶颈.

    在初始化方法 和 dealloc 中直接通过实例变量(_firstName)来获取;
    内部对象读取时,直接_firstName,写入数据时,通过属性set赋值self.firstName = @"XXX"

    6. 理解 "对象等同性" 这一概念
    NSString *foo = @"test 123";
    NSString *bar = [NSString stringWithFormat:@"test %i",123];
        
    BOOL equalA = (foo == bar); 对比的是对象地址
    BOOL equalB = [foo isEqual:bar];判断两个对象的地址是否相同,再判断类型是否一致, 然后再判断对象的具体内容是否一致
    BOOL equalC = [foo isEqualToString:bar]; 首先两个对象必须为NSString类型,其次得相等.
    
    NSLog(@"equalA:%zd equalB: %zd equalC: %zd",equalA,equalB,equalC);
    //equalA:0 equalB: 1 equalC: 1
    

    自定义判定等同性方法

    //In header file
    @interface ECOPerson : NSObject
    
    @property(nonatomic,copy)NSString *firstName;
    @property(nonatomic,copy)NSString *lastName;
    @property(assign,nonatomic) NSUInteger age;
    
    @end
    
    //In implementation
    - (BOOL)isEqual:(id)object
    {
        if (self.class == [object class]) {
            return [self isEqualToPerson:object];
        } else {
            return [super isEqual:object];
        }
    }
    
    - (BOOL)isEqualToPerson:(ECOPerson *)otherPerson
    {
        if (self == otherPerson) {
               return YES;
        }
    
        if (self.class != [otherPerson class]) {
           return NO;
        }
    
        if (![otherPerson.firstName isEqualToString:self.firstName]) {
           return NO;
        }
    
        if (![otherPerson.lastName isEqualToString:self.lastName]) {
           return NO;
        }
    
        if (otherPerson.age != self.age) {
           return NO;
        }
    
        return YES;
    }
    
    - (NSUInteger)hash
    {
        NSUInteger fistNameHash = [_firstName hash];
        NSUInteger lastNameHash = [_lastName hash];
        NSUInteger ageHash = _age;
    
        return fistNameHash ^ lastNameHash ^ ageHash;
    }
    
    

    哈希值相等 不一定 两个对象相等,但两个对象相等,哈希值一定相等;
    若想检测对象的等同性,请提供"isEqual" 与 "hash"方法
    编写hash方法时,尽量使用计算速度快,哈希碰撞少的算法.

    相关文章

      网友评论

          本文标题:iOS - OC <<编写高质量iOS与OS X代码的多个有效方

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