1、#import和#include的区别,@class代表什么?
指令#import和#include都是用于包含头文件的,前者是保证只会包含一次,不会重复包含;后者是C语言
中原来就有的包含头文件的指令,在OC开发中,若是C文件,一般会使用#include指令来包含头文件,为了防止
重复包含,通常会加上条件编译。
@class是声明在类前的指令,相当于告诉编译器有这样的一个类;但是类的定义在后面提供。在编译时期,
编译器看到@class指令声明了对应的类型,是可以正常编译的。这是很常用的指令,主要是防止循环引用。
2、OC的内存管理方式以及过程。
内存管理黄金法则:谁使对象的引用计数+1,谁就负责管理使该对象的引用计数-1.
内存管理的过程:在MRC下,对于需要手动释放的对象的内存管理,我们通过release使对象引用计数-1,
若其引用计数变为0,则对象会被立刻释放掉。对于autorelease交给自动释放池管理的对象,每个run loop
循环结束就会去自动释放池中使所有autorelease类型对象的引用计数-1;若变成0,则释放之。在ARC下,我
们不能直接调用retain/release来管理释放,都是交给自动释放池来管理的。因此,若创建临时变量,想要使
用完就释放之,需要在临时变量放到新创建的自动释放池里,这样就可以使用完后就到达了自动释放池的一个循
环,就会去使对象引用计数-1,变成0后释放。
最后:对于交给自动释放池管理的对象,是在每个run loop事件循环结束时才会去使对象引用计数-1,此
时引用计数为0的才会得到释放。
3、OC中有私有方法吗?私有变量呢?
在OC中,没有实实存在的私有方法。通常所谓的私有方法就是放在.m文件中声明和实现,外部不能直接看到
而已,但是若我们知道有这么一个API,我们是可以调用的。比如,在苹果上架会因为使用了苹果的所谓的私有
API而被拒,而这个所谓的私有API就是指苹果没有公示出来,但是我们通过其他方式可以看到苹果的内部有这样
一个API可以实现某些不公开的功能。
私有变量是有的,可以通过@private来声明私有变量。比如:
@interface HYBTestModel:NSObject {
@private NSString *_privateName;
}
4、OC中有多继承吗?没有的话用什么代替?
OC中没有多继承,这是去掉C++中多继承的特性,改成使用protocol来代替。Cocoa中所有的类都是
NSObject的子类,这是正确的。
5、浅拷贝与深拷贝的区别是什么?
浅拷贝就是指针拷贝(指向原有内存空间),而深拷贝是内容拷贝(有新的内存空间)。
6、属性readwrite、readonly、assign、retain、copy、nonatomic各是什么作用,在哪种情况下使用?
作用分别是:
• readwrite:代表可读可写,会生成getter和setter方法。
• readonly:代表只读,只生成getter方法,不会生成setter方法。
• assign:修饰基本数据类型(NSInteger,CGFloat)和C数据类型(int,float,double,char)等。
• retain:MRC下才能手动使用,与ARC下的strong一样,指定强引用,引用计数+1.
• copy:代表拷贝,也是强引用,引用计数+1,进行指针拷贝。
• nonatomic:代表非原子操作,非线程安全,但可提高性能。
7、什么情况使用weak关键字,相比assign有什么不同?
使用weak关键字的主要场景:
• 在ARC下,在有可能出现循环引用的时候往往要通过让其中一端使用weak来解决,比如:delegate代理属
性,通常就会声明为weak。
• 自身已经对它进行一次强引用,没有必要再强引用一次时也会使用weak。比如:自定义IBOutlet控件属性
一般也使用weak,当然也可以使用strong。
• weak关键字只能用于对象,对于基本类型不能使用。
• assign既可以用于对象,也可以用于基本类型,但是只是简单地进行赋值操作而已。
8、@synthesize和@dynamic分别有什么作用?
分析:@property有两个对应的词,一个是@synthesize,另一个是@dynamic。
• @synthesize的语义是如果你没有手动实现setter方法和getter方法,那么编译器会自动为你加上
这两个方法。
• @dynamic告诉编译器:属性的setter与getter方法由用户自己实现,不自动生成,假如一个属性被
声明为@dynamic var,然后你没有提供@setter方法和@getter方法,编译的时候没有问题,但是当程序
运行到instance.var=someVar,由于缺setter方法会导致程序崩溃;或者当运行到someVar=var时,由
于缺getter方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓额动态绑定。
9、OC中的类方法(加号方法)和实例方法(减号方法)有什么本质区别和练习?
类方法:
• 类方法是属于类对象的(所谓的类对象,不是class instance)
• 类方法只能通过类对象调用
• 类方法中的self是类对象
• 类方法可以调用其他的类方法
• 类方法中不能访问成员变量
• 类方法中不能直接调用对象方法
实例方法:
• 实例方法是属于实例对象的
• 实例方法只能通过实例对象调用
• 实例方法中的self是实例对象
• 实例方法中可以访问成员变量
• 实例方法中直接调用实例方法
• 实例方法中也可以调用类方法(通过类名)
10、线程和进程的区别和联系?
区别:
① 进程:一个具有一定独立功能的程序关于某个数据集合的一次运行活动。可以理解成一个运行中的应用程序。
② 线程:程序执行流的最小单元,线程是进程中的一个实体。
联系:
① 一个进程至少拥有一个线程——即主线程,也可以拥有多个线程。
② 一个线程必须有一个父进程,多个进程可以并发执行。
③ 一个线程可以创建和撤销另一个线程。
④ 同一个进程中的多个线程之间可以并发执行。
11、iOS中的多线程
iOS中的多线程:是Cocoa框架下的多线程,通过Cocoa的封装,可以让我们更为方便的使用线程,做过
C++的可能会对多线程有更多的理解,比如:线程的创立,信号量、共享量有认识,Cocoa框架下会方便很多,
它对线程做了封装,有些封装,可以让我们创建的对象,本身便拥有线程,也就是线程的对象化抽象,从而减
少我们的工程,提供程序的健壮性。
GCD是(Grand Central Dispatch)的缩写,从系统级别提供的一个易用地多线程类库,具有运行时
的特点,能充分利用多核心硬件。GCD的API接口为C语言的函数。函数参数中多数有Block,关于Block的使
用参看这里,为我们提供强大的“接口”,对于GCD的使用参见本文。
NSOperation与Queue
NSOperation是一个抽象类,它封装了线程的细节实现,我们可以通过子类化该对象,机上NSQueue来
同面向对象的思维,管理多线程程序。具体可参看这里:一个机遇NSOperation的多线程网络访问的项目。
NSThread
NSThread是一个控制线程执行的对象,它不如NSOperation抽象,通过它我们可以方便的得到一个线程,
并控制它。但NSThread得线程之间的并发控制,是需要我们自己来控制的,可以通过NSCondition实现。
参看
iOS多线程编程之NSThread的使用
定时器与线程的区别:
• 定时器:可以执行多次,默认在主线程中。
• 线程:只能执行一次。
12、串行/并行/同步异步
• 串行/并行
① 串行:一次只能执行一个任务。
② 并行:并行是一次能执行多个任务。
• 并行/并发
① 并行是CPU的多核芯同时执行多个任务。
② 并发是单核CPU交替执行两个任务。
• 同步异步关注的是消息通讯机制
① 同步:一个线程要等待上一个线程执行完之后才能执行当前的线程,生活中的例子(上厕所)。
② 异步:同时去做两件或者多件事,比如边听歌边看报。
13、多线程编程
• NSThread:当需要进行一些耗时操作时,会把耗时的操作放到线程中。线程同步:多个线程同时访问一个
数据会出问题,NSLock、线程同步块、@synchronize(self){}。
• NSOperationQueue操作队列(不需要考虑线程同步问题)。编程的重点都放在main里面,
NSInvocationOperation、BSBLockOPeration、自定义Operation。创建一个操作绑定相应的方法,当把
操作添加到操作队列中时,操作绑定的方法就会自动执行了,当把操作添加到操作队列中时,默认会调用main方
法。
• GCD(Grand Central Dispatch)宏大的中央调度,串行队列、并发队列、主线程队列;
必须回到主线程刷新UI。
14、三种多线程的对比
1⃣️ NSThread
每个NSThread对象对应一个线程,真正最原始的线程。
1)优点:NSThread轻量级最低,相对简单。
2)缺点:手动管理所有的线程活动,如生命周期、线程同步、睡眠等。
2⃣️ NSOperation
自带线程管理的抽象类。
1)优点:自带线程周期管理,操作上可更注重自己逻辑。
2)缺点:面向对象的抽象类,只能实现它或者使用它定义好的两个子类:NSInvocationOperation和
NSBlockOperation。
3⃣️ GCD
Grand Central Dispatch(GCD)是Apple开发的一个多核编程的解决方法。
1)优点:最高效,避开并发陷阱。
2)缺点:基于C实现。
15、block和weak修饰符的区别:
① __block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。
② __weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。
③ __block对象可以在block中被重新赋值,__weak不可以。
16、static关键字的作用
① 函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在
下次调用时仍维持上次的值;
② 在模块内的static全局变量可以被模块内所有函数访问,但不能被模块外其他函数访问;
③ 在模块内的static函数只可被这一模块内的其他函数调用,这个函数的使用范围被限制在声明它的模块内;
④ 在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
⑤ 在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员
变量。
17、简述类目category优点和缺点。
优点:
• 不需要通过增加子类而增加现有类的行为(方法),且类目中的方法与原始类方法基本没有区别;
• 通过类目可以将庞大一个类的方法进行划分,从而便于代码的日后的维护、更新以及提高代码的阅读性;
缺点
• 无法向类目添加实例变量,如果需要添加实例变量,只能通过定义子类的方式;
• 类目中的方法与原始类以及父类方法相比具有更高优先级,如果覆盖父类的方法,可能导致super消息
的断裂。因此,最好不要覆盖原始类中的方法。
18、类别(延展)的作用
• 给系统原有类添加方法,不能扩展属性。如果类别中方法的名字跟系统的方法名一样,在调用的时候类别
中的方法优先级更高;
• 分散类的实现,如:
+(NSIndexPath *)indexPathForRow:(NSInteger)row inSection:(NSInteger)section
原本属于NSIndexPath的方法,但因为这个方法经常使用表的时候调用、跟表的关系特别密切,因此把这
个方法以类别的形式、声明在UITableView.h中。
• 声明私有方法,某一个方法只实现,不声明,相当于私有方法。
• 类别不能声明变量,类别不可以直接添加属性。property描述setter方法,就不会报错。
19、循环引用的产生原因,以及解决方法。
产生原因:
对象A和对象B相互引用了对方作为自己的成员变量,只有自己销毁的时候才能将成员变量的引用计数-1.对象A
的销毁依赖于对象B的销毁,同时对象B销毁也依赖于对象A的销毁,从而形成循环引用;此时,即使外界没有任
何指针访问它,它也无法释放。
解决方法:
• 事先知道存在循环引用的地方,在合理的位置主动断开一个引用,是对象回收;
• 使用弱引用的方法。
20、代理的作用
• 代理又叫委托,是一种设计模式,代理是对象与对象之间的通信交互,代理解除了对象之间的耦合性。
• 改变或传递控制链,允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针。可以减少
框架复杂度。
• 另外一点,代理可以理解为Java中的回调监听机制的一种类似。
• 代理的属性常是assign的原因:防止循环引用,以致对象无法得到正确的释放。
21、NSNotification、Block、Delegate和KVO的区别
• 代理是一种回调机制,且是一对一的关系,通知是一对多的关系,一个对向所有的观察者提供变更通知;
• 效率:Delegate比NSNotification高;
• Delegate和Block一般是一对一的通信;
• Delegate需要定义协议方法,代理对象实现协议方法,并且需要建立代理关系才可以实现通信;
• Block更加简洁,不需要定义繁琐的协议方法,但通信事件比较多的话,建议使用Delegate。
22、KVC和KVO
KVC、KVO概述:
① KVC(NSKeyValueCoding)“键—值 编码”是一种间接访问对象的属性的机制,在OC2.0之后系统提供
了(.)语法来访问属性,再此之前我们需要用KVC来访问。
② KVO(NSKeyValueObserving)“键-值 监听”定义了这样一种机制,当对象属性值发生变化的时候我们
能收到一个通知。
③ KVC是一种间接访问对象属性的机制。
④ KVO是基于KVC来实现的。
23、谓词的认识
Cocoa框架中提供了一个NSPredicate的类,该类主要用于指定过滤器的条件,每一个对象通过谓词进行筛选,
判断条件是否匹配。
24、@public、@protected、@private它们的含义与作用
• @public:对象的实例变量的作用域在任意地方都可以被访问;
• @protected:对象的实例变量作用域在本类和子类都可以被访问;
• @private:实例变量的作用域只能在本类(自身)中访问。
25、isMemberOfClass和isKindOfClass联系与区别
• 联系:两者都能检测一个对象是否是某个类的成员。
• 区别:isKindOfClass不仅用来确定一个对象是否是一个类的成员,也可以用来确定一个对象是否派生自
该类的类的成员,而isMemberOfClass只能做到第一点。
• 举例:如ClassA派生自NSObject类,ClassA *a=[[ClassA alloc]init],
[a isKindOfClass:[NSObject class]]可以检查出a是否是NSObject派生类的成员,
但isMemberOfClass做不到。
26、UITableViewCell上有个UILabel,显示NSTimer实现的秒表时间,手指滚动cell过程中,label是否刷,为什么?
这是否刷新取决于timer加入到Run Loop中的Mode是什么。Mode主要是用来指定事件在运行循环中的优先级,
分为:
• NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默认,空闲状态;
• UITrackingRunLoopMode:ScrollView滑动时会切换到该Mode;
• UIInitalizationRunLoopMode:run loop启动时,会切换到该mode;
• NSRunLoopCommonModes(kCFRunLoopCommonModes):mode集合。
苹果公开提供的Mode有两个:
• NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
• NSRunLoopCommonModes(kCFRunLoopCommonModes)
• 在编程中:如果我们把一个NSTimer对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
添加到主运行循环中的时候,ScrollView滚动过程中会因为Mode的切换,而导致NSTimer将不再被调度。当
我们滚动的时候,也不希望不调度,那就应该使用默认模式。但是,如果希望在滚动时,定时器也要回调,那就
应该使用common mode。
27、TCP和UDP的区别与联系
• TCP为传输控制协议,为面向连接、可靠的、点到点的通信;
• UDP为用户数据报协议,非连接的不可靠的点到多点的通信;
• TCP侧重可靠传输,UDP侧重快速传输。
28、TCP连接的三次握手
• 第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
• 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包,即
SYN+ACK包,此时服务器进入SYN+RECV状态;
• 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此发送完毕,
客户端和服务器进入ESTABLISHED状态,完成三次状态。
29、ASIHttpRequest、AFNetWorking之间的区别
• ASIHttpRequest功能强大,主要是在MRC下实现的,是对系统CFNetwork API进行了封装,支持HTTP
协议的CFHTTP,配置比较复杂,并且ASIHttpRequest框架默认不会帮你监听网络改变,如果需要让
ASIHttpRequest帮你监听网络状态改变,并且手动开始这个功能。
• AFNetWorking构建于NSURLConnection、NSOperation以及其他熟悉的Foundation技术之上。拥有
良好的架构,丰富的API及模块构建方式,使用起来非常轻松。它基于NSOperation封装的,
AFURLConnectionOperation子类。
• ASIHttpRequest是直接操作对象ASIHttpRequest,是一个实现了NSCoding协议的NSOperation
子类;
AFNetWorking直接操作对象的AFHttpClient,是一个实现NSCoding和NSCopying协议的NSObject子类。
• 同步请求:ASIHttpRequest直接通过调用一个startSynchronous方法;AFNetWorking默认没有
封装同步请求,如果开发者需要使用同步请求,则需要重写getPath:paraments:success:failures方法,
对于AFHttpRequestOperation进行同步处理。
• 性能对比:AFNetWorking请求优于ASIHttpRequest;
30、AFNetWorking大致原理
AFNetWorking是对NSURLConnection和NSURLSession的各自的一层包装:
① 写一个单例,开辟新的线程,保证安全性以及开辟一块内存空间;
② AFN内部开了一条专门用来访问网络请求的线程,使用NSThread;
③ 添加一个RunLoop,保证执行网络获取。
31、如何进行真机调试
① 首先需要用钥匙串创建一个钥匙(key);
② 将钥匙串上传到官网,获取iOS Development证书;
③ 创建APP ID即我们应用程序中的Boundle ID;
④ 添加Device ID即UDID;
⑤ 通过勾选前面所创建的证书:APP、ID、Device ID;
⑥ 生成mobileprovision文件;
⑦ 先决条件:申请开发者账号99$/299$,从Xcode7开始可以免费真机测试;
⑧ 注意:个人版(99$)可以上架AppStore,企业版(299$)不可以上架AppStore,通过企业分发形式
安装,将IPA放在七牛云存储/蒲公英等等。
32、APP发布的上架流程
注意:个人版(99$)可以上架AppStore,企业版(299$)不可以上架AppStore,通过企业分发形式安装,
将IPA放在七牛云存储/蒲公英等等。
① 登录应用发布网站添加应用信息;
② 下载安装发布证书;
③ 选择发布证书,使用Archive编译发布包,用Xcode将代码(发布包)上传到服务器;
④ 等待审核通过;
⑤ 生成IPA:菜单栏->Product->Archive。
33、如何进行网络消息推送
http://upload-images.jianshu.io/upload_images/326255-1d3791a138d9992b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
APP端需要做的:
① APP ID(唯一标识一个APP程序);
② Provisioning Profile(APP程序的发布需要它,所以推送通知只能在真机上测试);
③ Device Token(设备标识,这个是推送通知功能中特有的)。
后台需要的:
① SSL Certificate 授权证书
② Private Key
推送的所有步骤:
* Provider:应用自己的服务器;
* APNS:Apple Push Notification Service的简称,苹果的PUSH服务器。
① 移动设备应用启动时注册消息推送;
② APNS返回该设备注册的唯一设备标示deviceToken;
③ 移动设备向Provide提供deviceToken;
④ Provide向APNS发送和以及需要<推送给设备的消息>;
⑤ APNS将消息根据deviceToken推送给指定设备。
34、SDWebImage内部实现流程
SDWebImage:一个异步下载图片并且支持缓存的UIImageView分类。
① 先从内存图片缓存查找是否有图片,如果内存中已经有图片缓存,SDImageCacheDelegate回调
imageCache:didFindImage:forKey:userInfo:到SDWebImageManager,并展示图片;
② 如果缓存中没有,生成NSInvocationOperation添加到队列开始从硬盘查找图片是否已经缓存;
③ 根据URLKey在硬盘缓存目录下尝试读取图片文件,这一步是在NSOperation进行的操作,所以会主线程
进行回调notifyDelegate;
④ 如果有图片就展示;
⑤ 如果没有,共享或重新生成一个下载器SDWebImageDownloader开始下载图片;
⑥ connectionDidFinishLoading:数据下载完成后交给SDWebImageDecoder做图片解码处理;
⑦ 图片解码处理在一个NSOperationQueue完成,不会拖慢主线程UI。如果有需要对下载的图片进行二次
处理,最好也在这里完成,效率会好很多;
⑧ 成功后通知所有的downloadDelegates下载完成,回调给需要的地方展示图片;
⑨ 将图片保存到SDImageCache中,内存缓存和硬盘缓存同时保存。写文件到硬盘也可以单独
NSInvocationOperation完成,避免拖慢主线程。
35、对NSUserDefaults的理解
NSUserDefaults:系统提供的一种存储数据的方式,主要用于保存少量的数据,默认存储到library下的
Preferences文件夹。
36、对沙盒的理解
每个iOS应用 都被限制在“沙盒”中,沙盒相当于一个加了仅主人可见权限的文件夹,即是在应用安装过程中,
系统为每个单独的应用程序生成它的主目录和一些关键的子目录。苹果对沙盒有几条限制:
① 应用程序在自己的沙盒中运作,但是不能访问任何其他应用程序的沙盒;
② 应用之间不能共享数据,沙盒里的文件不能被复制到其他应用程序的文件夹中,也不能把其他应用文件夹复制
到沙盒中;
③ 苹果禁止任何读写沙盒以外的文件,禁止应用程序将内容写到沙盒以外的文件夹中;
④ 沙盒目录里有三个文件夹:
• Documents——存储应用程序的数据文件,存储用户数据或其他定期备份的信息;
• Library——下有两个文件夹:Caches——存储应用程序再次启动所需的信息,Preferences——包含应用程
序的偏好设置文件,不可在这更改偏好设置;
• temp——存放临时文件即应用程序再次启动不需要的文件。
• 获取沙盒根目录的方法,有几种方法:用NSHomeDirectory获取。
• 获取Document路径:NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,YES).
37、堆和栈的区别:
• 栈区(stack)由编译器自动分配释放,存放方法(函数)的参数值,局部变量的值等,栈是向低地址
扩展的数据结构,是一块连续的内存的区域。即栈顶的地址和栈的最大容量是系统预先规定好的。
• 堆区(heap)一般由程序员分配释放,若程序员不释放,程序结束时由OS回收,向高地址扩展的数据
结构,是不连续的内存区域,从而堆获得的空间比较灵活。
• 碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,
使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,
以至于永远都不可能有一个内存块从栈中间弹出。
• 分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是
编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的
动态分配是由编译器进行释放,无需我们手工实现。
• 分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的
地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很
复杂的。
• 全局区(静态区)(static),全局变量和静态变量的储存是放在一块的,初始化的全局变量和静态变量
在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。
• 文字常量区——常量字符串就是放在这里的,程序结束后由系统释放。
• 程序代码区——存放函数体的二进制代码。
38、Struct与Class的区别:
(http://blog.csdn.net/yuliu0552/article/details/6717915)
共同点:
① 都可以包含成员函数;
② 都能继承;
③ 都能实现多态。
区别:
struct是public的,class是private的。
① **struct作为数据结构的实现体,它默认的数据访问控制是public的;而class作为对象的实现体,
它默认的成员变量访问控制是private的**。
② 当你觉得你要做的更像是一种数据结构的话,那么用struct;如果你要做的更像是一种对象的话,那么用
class。
③ struct更适合看成是一个数据结构的实现体,class更适合看成是一个对象的实现体。
39、介绍一下观察者模式
① 含义:当对象间存在一对多关系时,则使用观察者模式(Observer pattern)。比如,当一个对象被修改
时,则会自动通知它的依赖对象。观察者模式属于行为型模式。
② 何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察着对象)都将得到通知,进行广播
通知。
③ 举例子:西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,
他观察菩萨洒水这个动作。
④ 使用场景:
• 有多个子类共有的方法,且逻辑相同。
• 重要的、复杂的方法,可以考虑作为模板方法。
优缺点:
优点:① 观察者和被观察者是抽象耦合的。
② 建立一套触发机制。
缺点:① 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
② 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发他们之间进行循环调用,可能导致系统
崩溃。
③ 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察
目标发生了变化。
iOS观察者模式:
① 在iOS中观察者模式的实现有三种方法:Notification、KVO以及标准方法。
② 标准方法:标准方法的实现是这样的:Subject(主题)知道所有的观察者,但是不知道他们的类型。
下面我们就从创建Subject和Observer(观察者)的协议(protocol)开始。