美文网首页
《Effective Objective-C 2.0》读书笔记(

《Effective Objective-C 2.0》读书笔记(

作者: KeyboardDirver | 来源:发表于2019-04-08 13:36 被阅读0次

第三章 接口与API的设置

第15条:用前缀避免命名空间冲突

命名空间冲突的表现

错误的原因在于,应用程序中的两份代码都各自实现了名为EOCTheClass的类,这导致EOCTheClass所对应的类符号和“元类”符号各定义了两次。比无法连接更糟糕的是,在运行期再入了含有重命名类的程序库。此时“动态加载器”(dynamic loader)就遭遇了“重名符号错误”(duplicate symbol error),很有可能会令整个应用程序崩溃。
苹果保留使用“两个字母前缀”(two-letter prefix)的权利,为了避免与苹果冲突推荐使用三个字母前缀,在函数命名时添加前缀不仅能减少命名冲突,同时在程序出错时的问题回溯中,也可以较为直观的发现问题所在地。

第16条:提供“全能初始化方法”

"全能初始化方法"(designated initializer) 常译为“指定出初始化方法”。为明确“designated”一词之含义,译文将其译成“全能”
有指定构造方法,当我们需要修改构造方法时就不必把每一个构造方法全都修改一遍,只需修改全能构造方法即可。

进入NSDate 文件

- (instancetype)init NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)ti NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;

我们会发现NS_DESIGNATED_INITIALIZER 这个就是也就是指定构造方法。当自定义一个初始化方法时必须调用super的指定构造方法,不然

此外还有NS_UNAVAILABLE 如果在方法后著明那么在IDE的提示器中将不会出现此方法 此方法不可见
NS_UNAVAILABLE 和 NS_DESIGNATED_INITIALIZER

第17条:时间description方法

主要是这两个方法的使用 可以方便的自定义打印信息。在自定义的类中

-(NSString *)description;
- (NSString *)debugDescription;
  • 实现description方法 返回一个有意义的字符串,用以描述该实现。
  • 若想在调试时打印出更详尽的对象描述信息,则应该实现debugDescription方法。
第18条:尽量使用不可变对象

有一点要注意属性声明为readonly 也不是一定不可改的。 可以使用
1.kvc
2.直接使用类型信息查询功能查询出属性所对应的实例变量在内存布局中的偏移量,以此来认为设置这个实例变量的值。这样做是不符合公共API规范的。

  • 尽量使用不可变的对象。
  • 若某属性仅可于对象内部修改,则在.m中 的extern 中将其由readonly 设置为 readwrite
  • 不要把可变的collection 作为属性公开,而应该提供相关方法,以此修改对象中的可变collection。
第19条:使用清晰而协调的命名方式

方法命名规则:
1.如果方法的返回值时新创建的,那方法名的首个单词应该是返回值的类型,除前面有修饰语,例如localizedString。属性的存取方法不遵循着这种命名方式,因为一般认为这些方法不会创建新对象。即使有时返回内部对象的一份拷贝,我们也认为那相当于原有的对象。这些存取方法应该按照其所对应的属性来命名。
2.应该把表示参数类型的名词后面加上一个或多个名词。
3.若果方法要在当前对象上执行操作,那么就应该包含动词;若执行操作时还要参数,则应该在动词后面加上一个或者多个动词。
4.不要使用str这种简称,应该使用string这样的全称。
5.Boolean属性因该加is前缀。如果某方法返回非属性的Boolean值,那么应该根据其功能,选用has或is当前缀。
6.将get这个前缀留给那些借由“输出参数”来保存返回值的方法,比如说,把返回值填充到”C语言式数组”(C-style arrary)里的那种方法就可以使用这个词做前缀。

要点:

  • 起名时应该遵从标准的Object-C命名规范,这样创建出来的接口更容易为开发者所理解。
  • 方法名要言简意赅,从左至右读起来要像个日常用于的句子才好。
  • 方法名里不要使用缩略后的类型名称。
  • 给方法起名时的第一要务就是确保其风格与你自己的代码或所需要集成的框架相符。
第20条:为私有方法名添加前缀

在项目中使用#param mark 对文件中的私有方法和公共方法进行分隔

  • 给私有方法的名称加上前缀,这样可以容易地将其同公共方法区分开。
  • 不要单用一个下划线做私有方法的前缀,因为这种方法是域留给苹果公司用的。
第21条:理解Object-C错误模型
NSException exceptionWithName:<#(nonnull NSExceptionName)#> reason:<#(nullable NSString *)#> userInfo:<#(nullable NSDictionary *)#>

//可能会导致内存泄漏  详情见第30条

本条还举例说明使用error的二级指针来传递error对象的方法,注意在使用error解引用的时候必须保证 error参数不是nil 。 NSError* 存储的是指向NSError的指针。并不是NSError对象, *error取出的是NSerror * 是一个指针。

处理异常还可以使用

@try {
        <#Code that can potentially throw an exception#>
    } @catch (NSException *exception) {
        <#Handle an exception thrown in the @try block#>
    } @finally {
        <#Code that gets executed whether or not an exception is thrown#>
    }

或者断言NSAssert

要点

  • 只有发生了可使整个应用崩溃的严重错误时,才一改使用异常。
  • 在错误不那么严重的情况下,可以指派”委托方法“(delegate method)来处理错误,也可以把错误信息放在NSError对象里,经由”输出参数“返回给调用者。
第22条:理解NSCopying协议

提到拷贝协议有NSCopying 和NSMutableCopying
还有就是深拷贝和前拷贝的问题了
首先要明确深拷贝和前拷贝的定义:
深拷贝:非容器类型(比如NSString)拷贝对象内存中的内从到新的内存中,如果是容器类型的(比如NSArray)会拷贝容器的外壳和容器中的内容。也就是把NSArray拷贝一份,数组中的对象也都拷贝一份。

浅拷贝:只是对对象的指针进行拷贝,内存中的内容没有进行拷贝(指针拷贝)。

在OC中的深拷贝是不完全的深拷贝,比如NSarray 使用mutableCopy只是拷贝了array的外壳深成了一个心的array地址,而数组中的对象并没有尽心深拷贝还是对象的地址并没有发生变化。网上关于深拷贝和前拷贝的文章5花8门,还是看书靠谱,有些写的不是很容易理解,对于深拷贝和前拷贝的没有明确的定义,有的文章比较片面,所以看技术文章要理性对待,实践才是检验真理的唯一标准。
若果嫌每个属性都进行拷贝比较麻烦可以利用runtime遍历属性进行 copy 这样可以在基类方法实现,方便子类调用。

要点

  • 若想令自己所写的对象具有拷贝功能,则需实现NSCopying协议。
  • 如果自定义的随想分为可变版本与不可变版本,那么就要同时实现NSCopying和NSMutableCopying协议。
  • 复制对象时需决定次采用深拷贝还是浅拷贝,一般情况下应该尽量执行浅拷贝。
  • 如果你所写的对象需要深拷贝,吗么可考虑戏赠一个专门执行深拷贝的方法。

相关文章

网友评论

      本文标题:《Effective Objective-C 2.0》读书笔记(

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