第三章 接口与API设计(EffectiveObjective-

作者: 谁动了MyWorld | 来源:发表于2016-06-29 19:07 被阅读90次

    1 使用前缀避免命名空间冲突

    • 命名冲突,应用程序链接的时候会报错
      duplicate symbol _OBJC_METACLASS_$_EOCTheClass in: build/somthing.o
      在运行期载入了含有重名类的程序库,"动态加载"遭遇"重名符号错误",会导致程序崩溃
    • 不仅是类名,应用程序中的所有名称都应加前缀,如果要为既有类新增"分类"(category),那么一定要给"分类"及"分类"中的方法加上前缀
    • 如果用第三方库编写自己的代码,并准备将其发布为程序库供其他人开发应用程序所用.
      这是应该给你所用的那一份第三非苦代码加上你自己的前缀.
      例如:你准备发布的程序库叫做EOCLibrary.

    2 提供"全能初始化方法"

    为对象提供必要信息以便其完成工作的初始化方法叫做"全能初始化方法"
    UITableViewCell,在初始化该类对象时,需要指明其样式以及标识符
    - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(nullable NSString *)reuseIdentifier
    如果创建类实例的方式不止一个,那么这个累就会有很多个初始化方法,不过仍然要在其中选定一个作为全能初始化方法,令其他初始化方法都来调用他
    好处:当底层数据存储机制改变时,只需修改此方法的代码就好,无须改变其他初始化方法

    3 现实description方法

    description:在NSObject协议中,自定义NSLog方法返回的字符串
    debugDescription:在NSObject协议中,自定义在控制台通过po命令输出的的字符串

    4 尽量使用不可变对象

    • 设计类的时候,应充分应用属性来封装数据,而在使用属性时,则可将其声明为"只读"(read-only).
      默认情况属性是"可读可写"(read-write).这样设计出来的类是"可变的".
      在编程实践中,则应该尽量把对外公布出来的属性设为只读,而且只在确有必要时才将属性对外公布
    @interface EOCPointOfInterest : NSObject
    @property (nonatomic, copy,readonly) NSString *indentifier;
    @property (nonatomic, copy,readonly) NSString *title;
    @end
    
    • 有时可能想要修改封装在对象内部的数据,但是却不想令这些数据为外人所改动.这个时候,通常做饭是在对象内部将readOnly属性重新什么为readwrite,当然属性是nonatomic的,那么这样做可能会产生"竞争条件"(race condition).可以通过"派发队列"等手段,讲数据存取设为同步操作
    #import "EOCPointOfInterest.h"
    @interfaceEOCPointOfInterest ()
    @property (nonatomic, copy,readwrite) NSString *indentifier;
    @property (nonatomic, copy,readwrite) NSString *title;
    @end
    
    @implementation EOCPointOfInterest
    @end
    
    • 不要把可变的collection作为属性公开,而应该提供相关方法,以此修改对象中的可变collection
      Person有个friends的集合属性
    @interface Person : NSObject
    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, strong,readonly) NSSet *friends;
    - (void)addFriend:(Person*)person;
    - (void)removeFriend:(Person*)person;
    @end
    
    @implementation Person{    
      NSMutableSet *_internalFriends;
    }
    
    - (NSSet *)friends{    
      return [_internalFriendscopy];
    }
    - (void)addFriend:(Person *)person{   
        [_internalFriendsaddObject:person];
    }
    - (void)removeFriend:(Person *)person{ 
       [_internalFriendsremoveObject:person];
    }
    @end
    

    5 使用清晰而协调的命名方式

    方法与变量名使用"驼峰式大小写命名法",变量名小写字母开头,其后每个单词首字母大写
    类名首字母要大写,其后每个单词首字母大写.
    5.1 方法命名

    • 如果方法的返回值是新创建的,那么方法名的首个词应该是返回值类型,除非前面还有修饰语
    • 应该把标识参数类型的名词放在参数前面
    • 如果方法要在当前对象上执行操作,那么就应该包含动词,若执行操作时还需要参数,则应该在动词
      后面加上一个或多个名词
    • 不要使用str这种简称,应该用string这样的全称
    • Boolean属性应加is当前缀.如果某方法返回非属性的Boolean值,那么应该根据其功能选用
      has或is做前缀
    • 将get这个前缀留给哪些借由"输出参数"来保存返回值的方法.

    5.2 类与协议的命名
    应该为类与协议的名称加上前缀,以避免命名控件冲突

    6 为私有方法名加前缀

    • 一个类所做的事情通常都要比从外面看到的更多,编写类的实现代码时,经常要写一些只有内部使用
      的方法,建议为这种方法的名称加上某些前缀, 这样有助于调试, 这样能很容易把公共与私有方法分开
    • 为私有方法添加前缀的好处二:修改其名称或签名之前要三思,公共API不便轻易改动(影响面广)
    • 具体使用何种前缀根据个人喜好,其中最好包含下划线与字母, 如p_作为前缀
    @interface EOCObject : NSObject
    - (void)publicMethod;
    @end
    @implementation EOCObject
    - (void)publicMethod{}
    - (void)p_privateMthod{}
    @end
    
    • 不要单用一个下划线做私有方法的前缀,因为这种做法是预留给苹果的

    7 理解Objective-C 错误类型

    7.1 Objective-C:只在极其严重的错误下抛出异常,抛出异常之后,无需考虑回复问题,而且应用程序此时也应该退出
    7.2 在非致命错误:Objective-C所采用的方式是令方法返回nil/0. 或是使用NSError,以表明其中有错误发生
    7.3 NSError对象里封装了三条消息

    • Error domain:错误范围,也就是产生错误的根源.类型为字符串,通常用一个特有的全局变量来定义
    • Error code:错误码,类型为这个整数.用意指明具体发生了何种错误,通常采用enum来定义
    • User info:用户信息,类型为字典,关于错误的额外描述,包含一段"本地化描述"
      NSError第一种常见用法就是通过协议,来传递错误.有错误发生时,当前对象会把错误信息经由协议中的某个方法传递给委托对象(delegate)
      NSError第二种常见用法:经由方法的"输出参数"返回给调用者.
    - (BOOL)doSomething:(NSError *__autoreleasing *)error{
      //do somethong that may cause an error   
     if (/*there was an error*/) {
            if (error) {
              *error = [NSErrorerrorWithDomain:domaincode:codeuserInfo:userInfo];
            }        
          returnNO;  
      }   
       returnYES;
    }
    

    传递给方法的参数是个指针,而该指针本事又指向另外一个指针,而该指针本身又指向另外一个指针,
    那个指针指向NSError对象,或者也可以把他当成一个直接指向NSError对象的指针.这样一来,就可以经由
    "输出参数"把NSError对象传递给调用者

    NSError *error=nil;
    [selfdoSomething:&error];
    

    8 理解NSCoping协议

    如果想自己的类支持拷贝操作,那就要实现NSCopying协议,该协议只有一个方法
    - (id)copyWithZone:(NSZone *)zone;
    long long age,会据此把内存分成不同的"区"(zone),而对象会创建在某个区里面,现在每个程序只有一个去,
    "默认区"(default zone).所以在实现这个方法的时候,不用考虑参数zone.

    相关文章

      网友评论

        本文标题:第三章 接口与API设计(EffectiveObjective-

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