2016年就这么过去了,只能说时间过的太快。这一年经历的不少,被迫换了一家公司。新公司感觉氛围还可以,只是技术比较low,所以只能算是一个暂时的工作地点,17年会尝试去一些技术比较牛的地方看看。看过的技术文章也不少,接触的新技术也很多,但是回过头来发现留下来的并不多。接下来会好好整理一下基础的知识,算是自己梳理一下吧,夯实基础才能有更大的发展。
1.开篇第一条并没有实质性的建议,只是告诉我们oc是基于c写的,完美的兼容了c,runtime使得oc具备了c语言所不具备的动态性。也就是动态绑定特性。oc是基于消息机制的,对象调用一个方法,不是再编译期间与对应的对象进行绑定,而是在运行的时候进行消息转发,进而找到对应的函数内存地址然后去执行。
2.第二条算是一个代码规范吧,再.h文件中如果要使用其他类,这时候不要使用#import 改用@class。记住就可以了。这种方式叫做前向引用,可以加快编译速度,避免不必要的导入
3.多用字面值常量,少用与之对应的方法。也算是代码规范。
ok:NSString * str = @"nihao";
no:NSString * str = [NSString stringWithFormat:@"%@",@"nihao"];
4.多用类型常量,少用#define预处理命令,也算是编码规范吧
#define Message @"nihao"
等价于
static NSString * const Message = @"nihao";
这里需要注意一个知识点,那就是static修饰的变量,标识当前的文件可用,外部的文件无法使用。const表示的是一个初始化之后便无法再更改值的常量。
还有一点需要注意的就是,如果你想声明一个全局符号,也就是在别的地方也可以不声明就使用,可以按照下面的写法
.h 文件
extern NSString * const userName ;
.m文件
NSString * const userName = @"haha";
这样在其他文件中,只需要导入包含userName的头文件,就可以直接使用这个值了。
5.枚举类型来标识状态码,还推荐使用移位操作符,加上异或操作来指定对应的值。感觉并没有什么卵用,按照自己的习惯来就好。
6.属性修饰符,顺带讲了一些属性合成。
@property (nonamitic, strong) NSString * userName;
等价于
@synthesis userName = _userName;
- (void) setuserName:(NSString *)userName;
- (NSString *)userName;
@synthesis 标识的是希望编译器帮我们自动合成set方法与get方法,如果不希望编译器帮我们自动合成,那么可以使用@dynamic。但是千万要注意,如果使用了@dynamic但是又没有实现get与set方法,那么在编译阶段是不会报错的。但是在运行的时候会crash。
然后又讲了一些属性修饰符,搞不懂为什么面试的时候爱问这些东西。
- nonatomic 标识的是不会保证该属性的线程安全性。atomic标识的是该属性具备线程安全的特性。如果使用atomic那么会消耗一定的存取性能,慎用。如果一定要对某个属性做加锁操作,有很多的其他选择,使用atomic也并不是很靠谱。比如信号量,NSLock等等,有一篇博客分析了各种锁性能:。
- 读写权限。readwrite是默认的读写权限,也就是可读可写,编译器会自动生成set与get方法。readonly表示的是只读。这个的用处是如果我们想将一个变量作为一个类的私有变量(当然了,oc中不可能有绝对的私有变量,因为有kvc还有runtime啊,简直666),可以再这个类的头文件中声明成readonly,但是再.m文件中声明成readwrite
- assign 只使用与非object类型,比如int float bool等等
- stong arc中标识强引用,会对引用计数加1的修饰符,为这种属性赋值的时候会先保留新值,然后释放掉旧值,然后再重新赋值
- weak arc中标识的弱引用,苹果爸爸为了防止野指针在内存中保存了一个weak表,表的键就是这个属性的内存地址,表的值就是这个属性的值。当这个弱引用的地址被回收的时候,系统会找到这块属性内存地址对应的属性值并把它值为nil,这样给nil发消息就不会崩溃了。
- unsafe_unretained 使用于对象类型,但是有一个问题是如果目标对象销毁了,那么属性值不会自动设置为nil,那么就野指针了,那么就崩了啊,跪了
- copy修饰符 跟strong修饰符 区别就是 copy不会保留新值,而是讲原来的值copy一份,保持其不变性。
7.比较简单了,说了那么多,只记住这些就可以。一个类的内部对属性值设置的时候使用set方法,取值的时候直接去属性值即可,避免调用其get方法,减少了消息转发带来的延迟,对性能有那么一丢丢的提升。
例如:
self.userName = @"haha";
self.label.text = _userName;
还有一个需要注意的啊 ,如果你对一个属性使用了懒加载,千万不要直接下划线取值啊,因为那样的话就永远都取不到了,需要使用对应的get方法
8.记住一个概念,如果两个对象isEqual函数返回的是相等,那么两个对象调用hash返回的一定也是相同的。如果hash返回的是相同的,这时候isEqual不一定相等啊,切记。如果想比较两个对象的属性值是否是相同的,可以直接重写isequal方法,里面的东西你想怎么写就怎么写咯。
9.类簇的概念 类似于工厂设计模式了。我传一个类型进去,就会创建出一个继承自基类的对象。在抽象父类中声明了很多子类可以要去重新实现的方法,注意:只是声明,并没有去实现,子类会去实现这些个方法。这样做的好处呢,就是吧公共的方法暴露出来,里面的实现对用户封闭,很好的封装性
10.关联对象的概念,也就是我们常说的给分类添加属性。分类中可以添加方法,协议等等。唯独不能添加属性,因为对象的内存布局再编译期间决定了,对象的ivarsize那时候已经确定了,无法再扩大。以下是几种常用的关联类型:
OBJC_ASSOCIATION_ASSIGN assign
OBJC_ASSOCIATION_RETAIN_NONATOMIC nonatomic,retain
OBJC_ASSOCIATION_COPY_NONATOMIC nonatomic,copy
OBJC_ASSOCIATION_RETAIN retain
OBJC_ASSOCIATION_COPY copy
其实可以吧关联对象理解为一个字典,一个隶属于对象的字典,我可以往字典中塞model以及其对应的值,也可以从里面拿出来对应的值。这样就比较好理解了