本文介绍: 继续学习Effective_Objective-C。这一章的简介就是在于让开发者熟练的掌握OC语言的编程规范。选择与你的公司、应用程序或者二者皆有关联的名称作为类名的前缀,并在所有代码中均使用这一前缀。若是自己所开发的程序库中用到了第三方库,则应为其中的名称加上前缀。这一章学的大部分之前都了解过或者使用过但不知道原理,还是要加深印象。
前言
15.用前缀避免命名空间冲突
- OC语言中没有其他语言那种内置的命名空间机制,所以我们在对文件命名时要十分的注意,若是发生重名冲突,那么应用程序相应的链接过程就会出错,导致运行文件不知道究竟该调用那个文件,因为其中出现了重复的符号。
- 也就是理解成命名的时候需要加上前缀,比如一个项目里存在很多歌ViewController的子类,那么在命名的时候需要分清楚子类的名称,加上前缀总是好的
要点总结
16.提供全能初始化方法
全能初始化
- 如果创建类实例的方式不止一种,那么这个类就会有许多个初始化方法。在这个过程里有一个方法使得其他方法初始化的时候必须调用它,那么这个方法称“全能初始化方法”。
- 只有在全能初始化方法中,才会存储内部数据,其他的方法只是在存储内部数据后再进行了一些其他操作而已
要点
- 在类中提供一个全能初始化方法,并与文档里指明。其他初始化方法均应调用此方法。
- 若全能初始化方法与超类不同,则需覆写超类中的对应方法。
- 如果超类的初始化方法不适用于子类,那么应该覆写这个超类方法,并在其中抛出异常。
- 一个类有多个全能初始化方法要注意,我们就是要维持原来类的调用链,每个子类的全能初始化方法都应该调用其超类的对应方法,并逐层向上。因为其父类有两个全能初始化方法,这两种初始化方法定义出来的数据可能是不同的,若是你在子类中调用了错误的父类初始化方法,它就会可能因为数据类型的问题使程序发生错误
- 重写初始化方法也要注意如果子类的全能初始化方法与超类方法的名称不同,我们总应覆写超类的全能初始化方法,避免子类调用父类的全能初始化方法
17.实现description方法
description
- 调试程序的时候,打印数组信息并查看信息如下
- 在构建需要打印到日志的字符串的时候,array对象会收到来自descriprion的消息,该方法返回得到描述信息将取代“格式字符串的%@”。
- 如果自定义类呢?我尝试打印了一下button类。
- 接着自定义类
- 和button的信息相比较,上面的内容不太有用,这里就提到了可以在自己的类覆写description方法,否则打印的时候就会调用NSObject的默认方法。
- EOCPerson里有自己的名字,我们在m文件重写description打印自己需要的。这也是吗了UIButton里面的实现也是改变了,它选择打印了自己的frame layer等属性
#import "EOCPerson.h"
@interface EOCPerson : NSObject
@property (nonatomic, strong)NSString *firstName;
@end
@implementation EOCPerson
- (NSString *)description {
return [NSString stringWithFormat:@"< %p, "%@>",self, self.firstName];
}
@end
以字典形式输出description
debugDescription
- 在NSObject协议里面还有一个方法也是用来调试打印代码
debugDescription
。 - 二者区别在于就是描述的位置不一样,description是在函数调用类的时候触发方法才输出的,而debugDescription是在控制台中使用命令打印该对象时才调用的。当然加断点查看时也可以看到debugDescription的描述。
- 这里还交给我们了一个调试方法是 po + 类可以打印详细的信息
- 如果你在description不想将一些内容输出的话,你就可以将那些数据写在debugDescription中,让程序员自己调试时可以方便的看到这些数据,而description方法就输出你想要让用户看到的信息就行了。
要点
18.尽量使用不可变对象
- 这里的不可变对象不是使用系统提供的不可变类,而是在设置属性的时候添加上readnoly属性
- 默认情况下的属性是既可读又可写的,这样的类我们在这里成为可变类,但一般的数据未必需要改变。
- 原则上尽量把对外公布出来的属性设为只读,并且在有确定的必要的时候设为可读。
- 当我们需要修改封装在对象内部的数据的的时候而且不想数据被外人改动的时候,需要将readonly改为readwrite并且为了避免竞争条件的出现,我们可在必要的时候通过派发队列等手段将数据的存储设置为同步操作(暂时未了解)
- 虽然保持了只能在代码内部实现属性,但其实还可以通过KVC来设置属性。
要点
- 尽量创建不可变的对象。
- 若某属性仅可于对象内部修改,则在“class–continuation分类”中将其由readonly属性扩展为readwrite属性。
- 不要把可变的collection作为属性公开,而应提供相关方法,以此修改对象中的可变collection。
19.使用清晰协调的命名方式
方法命名
- 如果方法的返口值是新创建的,那么方法名的首个词应是返回值的类型,除非前面还有修饰语,例如localizedString。属性的存取方法不遵循这种命名方式,因为一般认为这些方法不会创建新对象,即便有时返口内部对象的一份拷贝,我们也认为那相当手原有的对象。这些存取方法应该按照其所对应的属性来命名。
- 应该把表示参数类型的名词放在参数前面。
- 如果方法要在当前对象上执行操作,那么就应该包含动词;若执行操作时还需数,
则应该在动词后面加上一个或者多名词 - 不要使str这种简称,应该用 string 这样的全称。(经典)
- Boolean 属性应加is前级。如果某方法返口非属性的 Boolean 值,那么应该根据其功
能,选用has 或is 当前缀。 - get这个前缀留给那些借由“输出” 参数,来保布返口值的方法,比如说,把返回值填充到“C语言式数组”(C-style array)里的那种方法就可以使用这个词做前缀。
类与协议命名
- 应该为类与协议的名称加上前缀,以避免命名空间冲突,而且应该像给方法起名时那样把词句组织好,使其从左至右读起来较为通顺。基本命名规则就是:命名方式应该一致,如果要从其他的类中继承子类,那么就要遵守其原本的命名惯例。 例如:UIView它的子类就应该是***View,表明其来历。
- 在写自己项目的时候就出现了这个问题,我把view放在前面了导致看的时候比较混乱,一大段的view 不知道哪个是哪个
要点
- 起名时应遵从标准的OC命名规范,这样创建出来的接口更容易为开发者所理解。
- 方法名要言简意赅,从左至右读起来要像个日常用语中的句子才好。
- 方法名里不要使用缩略后的类型名称。
- 方法名起名时的第一要务就是确保其风格与你自己的代码或所要集成的框架相符。
20.为私有方法名加前缀
- 通常我们在写方法时,并没有对其进行私有共有分类,导致调试时可能很麻烦,现在为私有方法加上前缀,这样便于修改方法或方法签名。具体加什么来代表私有方法因人而异,自己怎么舒服怎么来,唯一注意的是:一定不要只使用_作为前缀,用p_都比那个好,因为苹果公司使用的就是_作为私有方法的前缀的,你自己定义的私有方法名有可能就会和人家自带的冲突。
- 给私有方法的名称加上前缀,这样可以很容易地将其同公共方法区分开。
- 不要单用一个下划线做私有方法的前缀,因为这种做法是预留给苹果公司用的。
21.理解Objective-C的错误类型
ARC的异常安全
- ARC的异常机制举例“自动引用计数”在默认情况下不是“异常安全的”,就是说,如果抛出异常,那么本应该在作用域末尾释放的对象现在却不会释放了,这样就会造成内存泄漏问题,如果想生成“异常安全”的代码,可以通过设置编译器的标志来实现,不过这将引入一些额外的代码,在不抛出异常时,也照样要执行这部分代码。需要打开的编译器标志叫做
-fobjc-arc-exceptions
- 所以OC语言现在的解决方法就是只在及其罕见的情况下抛出异常,异常抛出之后,无须考虑恢复问题,而且这时应用程序也应该退出了,所以无需我们去写“异常安全代码”了。
NSError
- 现在OC不会轻易的抛出异常,当然错误是随时都可能发生的,所以对于没有达到严重错误级别的错误,OC语言会返回nil 或者 0,还有就是使用NSError.以表明其中有错误发生.
- 这个是返回nil的例
- NSError相比之下更加的灵活,它可以把错误的原因回报给调用者。封装如下
NSError用法
- 第一种常见就是通过委托协议传递这个错误,当前对象会把协议中的某个方法传给委托的对象,此方法常用于API的设计。
- 另一种常见用法是:经由方法的“输出参数”返回给调用者。就是说用一个方法来判断你传过去的error是否真的有错误,返回Boolean值,之后你就可以根据error是否有内容,或者Boolean值来决定处理的代码和不处理的代码
- 还可以为error参数“解引用(error所指的那个指针现在要指向一个新的NSError对象)”之前,必须先保证error参数不是nil,因为空指针解引用会导致段错误并使程序崩溃,所以注意要判断error是不是nil。
- 错误范围和错误码和用户信息等分别返回不同的类型:
要点
- 只有发生了可使整个应用程序崩溃的严重错误时,才应使用异常。
- 在错误不那么严重的情况下,可以指派“委托方法”来处理错误,也可以把错误信息放在NSError对象里,经由“输出参数”返回给调用者。
-
- NSError 对象里封装了三条信息:
22.理解NSCopying协议
- 又遇到了Copy…
- 使用对象的时候经常觉得是否进行拷贝,深拷贝还是浅拷贝?对于这些问题在OC语言里面需要通过copy方法完成。
- 对于系统自带的容器类,字典数组集合都自带copy方法,这里需要说的是我们需要对自己自定义的类实现copy的时候,如何实现?
NSCopying
- NSCopying是NSObject的协议之一,它用于实现自定义类的copy。
- 该协议只有一个方法
- 若想某个类实现copy功能,则需要声明NSCopying协议然后实现对应的方法。
- 需要注意如果你的类分为可变版本和不可变版本那么还需要实现NSMutableCopying协议和对应的方法
@protocol NSCopying
- (id)copyWithZone:(nullable NSZone *)zone;
@end
@protocol NSMutableCopying
- (id)mutableCopyWithZone:(nullable NSZone *)zone;
@end
- 对于不可变的
NSArray
与可变的NSMutableArray
来说,存在如下关系
[NSMutableArray copy] => NSArray
[NSArray mutableCopy] => NSMutableArray
深浅拷贝的使用时机
- 要执行“深拷贝”还是“浅拷贝”?
- 如果有需要,我们可以自行添加一个深拷贝方法。
- 这个自行实现的深拷贝也可以看出来深浅拷贝的区别,深拷贝是在堆里新开辟一块内存存放底层数据。
- 浅拷贝是只拷贝存放在栈上指向堆内存的指针。
NSArray *array = @[@"immutableCopy", @"mutableCopy"];
NSArray *immurtableArray = [array copy];
NSArray *mutableArray = [array mutableCopy];
要点
- 若想令自己所写的对象具有拷贝功能,则需实现NSCopying协议。
- 如果自定义的对象分为可变版本和不可变版本,那么就要同时实现NSCopying与NSMutableCopying协议。
- 复制对象时需决定采用浅拷贝还是深拷贝,一般情况下应该尽量执行浅拷贝。
- 如果你所写的对象需要深拷贝,那么可考虑新增一个专门执行深拷贝的方法。
总结
- 这一章学的大部分之前都了解过或者使用过但不知道原理,还是要加深印象。
原文地址:https://blog.csdn.net/weixin_61639290/article/details/128377543
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_11667.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。