iOS 知识点总结

292 阅读8分钟

属性关键字 readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?

1. readwrite 是可读可写特性。需要生成getter方法和setter方法。
2. readonly 是只读特性。只会生成getter方法,不会生成setter方法,不希望属性在类外改变。
3. assign 是赋值特性。setter方法将传入参数赋值给实例变量;仅设置变量时,assign用于基本数据类型。
4. retain(MRC)/strong(ARC) 表示持有特性。setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1。
5. copy 表示拷贝特性。setter方法将传入对象复制一份,需要完全一份新的变量时。
6. nonatomic 非原子操作。不写的话默认就是atomic。atomic 和 nonatomic     的区别在于,系统自动生成的 getter/setter 方法不一样。对于atomic的属性,系统生成的 getter/setter 会保证 get、set 操作的完整性,而nonatomic就没有这个保证了。所以,nonatomic的速度要比atomic快。

不过atomic可并不能保证线程安全。

OC中的一个完整的类包括哪两部分

OC中的类必须包括两部分,interface部分和implementation部分。OC中将成员变量和成员方法的声明部分放置在interface部分中,包括继承关系,protocal实现关系,都在interface里面的头部进行声明,
然后将实现部分放置在implementation部分中,相当于是将类拆分成声明和实现两部分。

属性的setter和getter方法

setter是给外部提供一个修改内部属性值的接口,通过给对象指针发送该消息(调用setter方法)可以做到修改内部属性值。

getter 方法是外界提供一个查看内部变量的的接口 。

copy与mutableCopy

深拷贝:
对象拷贝 - 重新申请一片内存保留这个对象,与原对象之间没有半点关系。
浅拷贝:
指针拷贝 - 实际上相当于引用计数+1,被拷贝的和拷贝的引用同一个对象。
1.对非集合类对象的copy操作,以NSString为例
对不可变对象进行 copy 操作是指针拷贝,mutableCopy 操作时对象拷贝。
对可变对象进行 copy 和 mutableCopy 都是对象拷贝,内存地址不变。
2.对集合类对象的copy操作
对不可变对象做copy是指针拷贝,做mutableCopy是不完全深拷贝。
对可变对象做copy或mutableCopy都是不完全深拷贝。

不完全深拷贝(也有人说是单层深拷贝 )------ 即虽然新开辟了内存地址,但是存放在内存上的值(也就是数组里的元素仍然指向原数组元素值,并没有另外复制一份)。 并且如果打个断点可以发现对任何对象做copy操作返回的是一个不可变的对象,对任何对象做mutableCopy返回的是一个可变的对象

frame 和 bounds 有什么不同?

frame指的是:该view在父view坐标系统中的位置和大小。(参照点是父view的坐标系统)
bounds指的是:该view在本身坐标系统中的位置和大小。(参照点是本身坐标系统)

Objective-C的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方法用继承好还是分类好?为什么

Objective-C的类不可以多重继承;可以实现多个接口(协议);Category是类别;一般情况用分类好,用Category去重写类的方法,仅对本Category有效,不会影响到其他类与原有类的关系

什么情况使用 weak 关键字,相比 assign 有什么不同

1.在 ARC 中,在有可能出现循环引用的时候,往往要通过让其中一端使用 weak 来解决,比如: delegate 代理属性。
2.自身已经对它进行一次强引用,没有必要再强引用一次,此时也会使用 weak,自定义 IBOutlet 控件属性一般也使用 weak;当然,也可以使用strong。

IBOutlet连出来的视图属性为什么可以被设置成weak?
因为父控件的subViews数组已经对它有一个强引用。

不同点:
assign 可以用非 OC 对象,而 weak 必须用于 OC 对象。
weak 表明该属性定义了一种“非拥有关系”。在属性所指的对象销毁时,属性值会自动清空(nil)。

Objective-C 内存管理

Objective-C的内存管理主要有三种方式ARC(自动内存计数)、手动内存计数、内存池。
1. 自动内存计数ARC:由Xcode自动在App编译阶段,在代码中添加内存管理代码。
2. 手动内存计数MRC:遵循内存谁申请、谁释放;谁添加,谁释放的原则。
3. 内存释放池Release Pool:把需要释放的内存统一放在一个池子中,当池子被抽干后(drain),池子中所有的内存空间
也被自动释放掉。内存池的释放操作分为自动和手动。自动释放受runloop机制影响。

Category(类别)、 Extension(扩展)和继承的区别

1. 分类有名字,类扩展没有分类名字,是一种特殊的分类。
2. 分类只能扩展方法(属性仅仅是声明,并没真正实现),类扩展可以扩展属性、成员变量和方法。
3. 继承可以增加,修改或者删除方法,并且可以增加属性。

ViewController生命周期

1. initWithCoder:通过nib文件初始化时触发。
2. awakeFromNib:nib文件被加载的时候,会发生一个awakeFromNib的消息到nib文件中的每个对象。
3. loadView:开始加载视图控制器自带的view。
4. viewDidLoad:视图控制器的view被加载完成。
5. viewWillAppear:视图控制器的view将要显示在window上。
6. updateViewConstraints:视图控制器的view开始更新AutoLayout约束。
7. viewWillLayoutSubviews:视图控制器的view将要更新内容视图的位置。
8. viewDidLayoutSubviews:视图控制器的view已经更新视图的位置。
9. viewDidAppear:视图控制器的view已经展示到window上。
10. viewWillDisappear:视图控制器的view将要从window上消失。
11. viewDidDisappear:视图控制器的view已经从window上消失。

kvo和kvc

kvc
通过键值路径为对象的属性赋值。主要是可以为私有的属性赋值 setValue:ForKey:
通过键值路径获取属性的值。主要是可以通过key获得私有属性的值 valueforKey:
kvo
KVO提供了一种观察者的机制,通过对某个对象的某个属性添加观察者,当该属性改变,就会调用"observeValueForKeyPath:"方法,为我们提供一个“对象值改变了!”的时机进行一些操作。
什么是 RunLoop unloop是来做什么的?runloop和线程有什么关系?主线程默认开启了runloop么?子线程呢?
runloop: 从字面意思看:运行循环、跑圈,其实它内部就是do-while循环,在这个循环内部不断地处理各种任务
(比如Source、Timer、Observer)事件。runloop和线程的关系:一个线程对应一个RunLoop,主线程的RunLoop默认创建并启动,子线程的RunLoop需手动创建且手动启动(调用run方法)。RunLoop
只能选择一个Mode启动,如果当前Mode中没有任何Source(Sources0、Sources1)、Timer,
那么就直接退出RunLoop。
runloop的mode是用来做什么的?有几种mode?
model:是runloop里面的运行模式,不同的模式下的runloop处理的事件和消息有一定的差别。
系统默认注册了5个Mode:
1.kCFRunLoopDefaultMode: App的默认 Mode,通常主线程是在这个 Mode 下运行的。
2.UITrackingRunLoopMode: 界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响。
3.UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用。
4.GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到。
5.kCFRunLoopCommonModes: 这是一个占位的 Mode,没有实际作用。注意iOS 对以上5中model进行了封装 NSDefaultRunLoopMode、NSRunLoopCommonModes
SDWebImage里面给UIImageView加载图片的逻辑
SDWebImage 中为 UIImageView 提供了一个分类UIImageView+WebCache.h, 这个分类中有一个最常用的接口
sd_setImageWithURL:placeholderImage:,会在真实图片出现前会先显示占位图片,当真实图片被加载出来后
再替换占位图片。

加载图片的过程大致如下:
1.首先会在 SDWebImageCache 中寻找图片是否有对应的缓存, 它会以url 作为数据的索引先在内存中寻找是否有
对应的缓存
2.如果缓存未找到就会利用通过MD5处理过的key来继续在磁盘中查询对应的数据, 如果找到了, 就会把磁盘中的数据
加载到内存中,并将图片显示出来
3.如果在内存和磁盘缓存中都没有找到,就会向远程服务器发送请求,开始下载图片
4.下载后的图片会加入缓存中,并写入磁盘中
5.整个获取图片的过程都是在子线程中执行,获取到图片后回到主线程将图片显示出来

SDWebImage原理:
调用类别的方法:
1. 从内存(字典)中找图片(当这个图片在本次使用程序的过程中已经被加载过),找到直接使用。
2. 从沙盒中找(当这个图片在之前使用程序的过程中被加载过),找到使用,缓存到内存中。
3. 从网络上获取,使用,缓存到内存,缓存到沙盒。