ios知识点总结(一)
基础
1. @property 后面可以有哪些修饰符?
- 原子性---
nonatomic
、atomic
在默认情况下,由编译器合成的方法会通过锁定机制确保其原子性(atomicity)。如果属性具备 nonatomic 特质,则不使用自旋锁。请注意,尽管没有名为“atomic”的特质(如果某属性不具备 nonatomic 特质,那它就是“原子的” ( atomic) ),但是仍然可以在属性特质中写明这一点,编译器不会报错。若是自己定义存取方法,那么就应该遵从与属性特质相符的原子性。
-
读/写权限---
readwrite(读写)
、readonly (只读)
实际上是决定是否生成setter、getter方法 -
内存管理语义---
assign
、strong
、weak
、unsafe_unretained
、copy
assign
直接赋值,常用于修饰基础类型,如int,bool。修饰对象时,引用计数不会+1,会造成野指针。
weak
直接赋值,ARC下修饰对象使用,引用计数不会+1,对象销毁时,会指向nil,不会造成野指针。
Runtime维护了一个weak表,用于存储指向某个对象的所有weak指针。weak表其实是一个hash(哈希)表,Key是所指对象的地址,Value是weak指针的地址(这个地址的值是所指对象指针的地址)数组。当此对象的引用计数为0的时候会 dealloc,假如 weak 指向的对象内存地址是a,那么就会以a为键, 在这个 weak 表中搜索,找到所有以a为键的 weak 对象,从而设置为 nil。
strong
直接赋值并且对象的retain count +1,一般用于修饰对象。
copy
不会增加对象的 retain count,而是会重新复制一份对象,然后将指针指向新复制的对象。
NSString、NSArray、NSDictionary使用copy修饰,因为他们会对应可变的NSMutableString、NSMutableArray、NSMutableDictionary。假如有一个属性是NSString类型的,但是我们却将一个NSMutableString赋值给了它(这是合法的),如果我们使用strong关键字,那么现在这个对象是一个NSMutableString的对象,如果在别的地方修改了这个对象的值,那么该属性也跟着变了,这可能会带来意想不到的后果。但如果我们使用copy关键字的话,就不会存在这个问题了,因为它会拷贝一份NSMutableString的值,这时属性依然是 immutable 的,即使NSMutableString的对象修改了也不会影响属性的值。
a、 对非集合类对象的copy操作:
[immutableObject copy] // 浅复制
[immutableObject mutableCopy] //深复制
[mutableObject copy] //深复制
[mutableObject mutableCopy] //深复制
b、集合类对象的copy与mutableCopy
NSString、NSArray、NSDictionary 使用copy与mutableCopy[immutableObject copy] // 浅复制
[immutableObject mutableCopy] //单层深复制
[mutableObject copy] //单层深复制
[mutableObject mutableCopy] //单层深复制
- 方法名---
getter=<name>
、setter=<name>
2. 面向对象三大特性
封装,继承,多态
3. 成员变量跟属性
关系:属性是对成员变量的封装,即 property = ivar+setter+getter
4. @synthesize和@dynamic分别有什么作用?
@property有两个对应的词,一个是 @synthesize,一个是 @dynamic。如果 @synthesize和 @dynamic都没写,那么默认的就是@syntheszie var = _var;
@synthesize 的语义是如果你没有手动实现 setter 方法和 getter 方法,那么编译器会自动为你加上这两个方法。
@dynamic 告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成。(当然对于 readonly 的属性只需提供 getter 即可)。假如一个属性被声明为 @dynamic var,然后你没有提供 @setter方法和 @getter 方法,编译的时候没问题,但是当程序运行到 instance.var = someVar,由于缺 setter 方法会导致程序崩溃;或者当运行到 someVar = var 时,由于缺 getter 方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。
5. 如何将class定义一个对外只读对内可读写的属性
.h文件中,属性用readonly修饰,.m文件使用readwrite修饰
6. public、private、protected的作用域
public:不受限制,都可以访问;
protected:除本身跟子类可访问,其余外部类不可访问;
private:只能本身内部访问。
外部可以通过“->”来访问,对于private、protected,可通过kvc或者runtime实现修改、访问。
7. Categroy的理解
- category的主要作用是为已经存在的类添加方法
- 可以把类的实现分开在几个不同的文件里面。这样做有几个显而易见的好处,a)可以减少单个文件的体积 b)可以把不同的功能组织到不同的category里 c)可以由多个开发者共同完成一个类 d)可以按需加载想要的category 等等。
- 声明私有方法
- 模拟多继承
- 把framework的私有方法公开
category是无法添加实例变量的(因为在运行期,对象的内存布局已经确定,如果添加实例变量就会破坏类的内部布局,这对编译型语言来说是灾难性的)。可以添加属性,但是只是声明,具体的setter,getter方法还需要自己去实现,并且是这样实现setter:objc_setAssociatedObject,getter:objc_getAssociatedObject。
8. oc对象的内存布局
- 所有父类的成员变量和自己的成员变量都会存放在该对象所对应的存储空间中.
- 每一个对象内部都有一个isa指针,指向他的类对象,类对象中存放着本对象的 a)对象方法列表(对象能够接收的消息列表,保存在它所对应的类对象中;b)成员变量的列表;c)属性列表。
每个 Objective-C 对象都有相同的结构,如下图所示:
image
- 根对象就是NSObject,它的superclass指针指向nil
- 类对象既然称为对象,那它也是一个实例。类对象中也有一个isa指针指向它的元类(meta class),即类对象是元类的实例。元类内部存放的是类方法列表,根元类的isa指针指向自己,superclass指针指向NSObject类。