iOS面试题精选总结——综述(一)

iOS面试题精选总结——综述(一)
一.Objective-C概述

1.Objective-C语言的特点
Objective-C语言是C语言的一个超集,只是在C语言的基础上加上了面向对象的特性;
Objective-C与Java语言相同都是单继承,这一点与C++语言不同;
Objective-C不支持命名空间机制,取而代之的是类名之前添加前缀,以此来区分;
Objective-C作为一门面向对象的语言,自然具有面向对象的语言特性,如:封装,继承,多态。它具有静态语言的特性,又有动态语言的效率。
Objective-C具有相当多的动态特性,表现在三个方面:动态类型,动态绑定,动态加载。之所以叫做动态,是因为必须到运行时才会做一些事情。
1.动态类型:即运行时再决定对象的类型。这类动态类型在日常中非常常见。简单说就是id类型。实际上静态类型因为其固定性和可预知性而实用的非常广泛,静态类型是强类型,而动态类型是弱类型,运行时决定接受者;
2.动态绑定:基于动态类型,在某个实例对象被确定后,其类型就被确定了。该对象的属性和响应消息也被完全确定,这就是动态绑定。
3.动态加载:根据需求加载所需要的资源,这点很容易理解,对于iOS开发来说,基本就是根据不同的急性做适配。让程序在运行时添加代码块以及其他资源。用户可以根据需要加载一些可执行代码和资源,而不是启动时就加载所有组件。可执行代码中可以含有和程序运行时整合的新类。

2.我们说的Objectvie-C是动态运行时语言是什么意思
多态。主要是将数据类型的确定由编译时,推迟到了运行时。
这个问题涉及到两个概念,运行时和多态。
运行时:运行时机制使我们直到运行时才去决定一个对象的类型,以及调用该类型对象指定方法。
多态:不同对象以自己的方式响应相同的消息的能力叫做多态。
也可以说,运行时机制是多态的基础。

3.关于多态
多态,子类指针可以赋值给父类。

4.Objective-C语言的优缺点
优点:1.Cateogies
2.Posing
3.动态识别
4.指标计算
5.弹性讯息传递
6.不是一个过度复杂的 C 衍生语言
7.Objective-C与C++可混合编程

缺点:1.不支持命名空间
2.不支持运算符重载
3.不支持多继承
4.使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到,性能低劣

二.property与属性修饰符

5.@property后面可以有哪些属性修饰符?作用?
@property是一个属性访问声明,扩号内支持以下几种属性:
1.getter=getterName,setter=setterName,设置getter和setter的方法名;
2.readwrite,readonly,设置访问级别;
3.assign,setter方法直接赋值,不进行任何retain操作,为了解决原类型与循环引用的问题;
4.retain,setter方法对参数进行release旧值再retain新值,所有实现都是这个顺序;
5.copy,setter方法进行copy操作,与retain处理流程一样,先旧值release,再copy出新的值,retainCount为1。这是为了减少对上下文的依赖而引入的机制;
6.nonatomic:非原子性访问,不加同步,多线程并发访问会提高性能。注意,如果不加此属性,则默认是两个访问方法都为原子性事务访问。锁被加到所属对象实例里;

6.浅拷贝和深拷贝的区别
浅拷贝:只复制指向对象的指针,而不复制引用对象本身。
深拷贝:复制引用对象本身。
意思就是说我有个A对象,复制一份后得到A_copy对象后,对于浅拷贝来说,A和A_copy指向的是同一个内存资源,复制的只不过是一个指针,对象本身资源还是只有一份,那如果我们对A_copy执行了修改操作,那么发现A引用的对象同样被修改,这其实违背了我们复制拷贝的一个思想。深拷贝就好理解了,内存中存在了两份独立对象本身。

7.定义属性时,什么时候用assign,retain,copy以及它们的之间的区别
1.assign:普通赋值,一般常用于基本数据类型,常见委托设计模式,以此来防止循环引用。
2.retain:保留计数,获得到了对象的所有权。引用计数在原有基础上加1。
3.copy:一般认为,是在内存中重新开辟了一个新的内存空间,用来存储新的对象,和原来的对象是两个不同的地址,引用计数为1,但是当copy对象为不可变对象时,那么copy的作用相当于retain。因为,这样可以节约内存空间。

8.原子(atomic)跟非原子(nonatomic)属性有什么区别?
1.atomic提供多线程安全。是防止在写未完成的时候被另一个线程读取,造成数据错误。
2.nonatomic在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了nonatomic,那么访问器只是简单地返回这个值。

9.为什么delegate属性都是assign而不是retain的?
防止循环引用,以至对象无法得到正确的释放。

三.类别,扩展,代理,通知,协议

10.类别的作用?继承和类别在实现中有何区别?
category可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能修改和删除。并且如果类别和原来的类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。
类别主要有3个作用:
1.将类的实现分散到多个不同文件或多个不同框架中;
2.创建对私有方法的前向引用;
3.向对象添加非正式协议;
继承可以添加,修改或者删除方法,并且可以添加属性;

11.类别和类扩展的区别
category和extensions的不同在于,后者可以添加属性。另外后者添加的方法是必须要实现的。
extensions可以认为是一个私有的category。

12.扩展是什么?作用是什么?
扩展:在自己的类的实现文件中添加类目来声明私有方法。
扩展:“匿名”的类目,扩展定义类的私有方法,一般是在类的实现文件@implementation之上定义。只能本类调用,子类也无法调用父类的扩展。
另外在本类的实现文件@implementation之上也可以定义私有方法,私有的静态变量,扩展的特点就是定义私有方法

13.代理的作用?
代理的目的是改变或传递控制链。允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针。可以减少框架的复杂度。
另外一点,代理可以理解为java中的回调监听机制的一种类似。
自定义代理模式分为6步:
1.定义协议
2.定义代理属性
3.指定代理对象
4.代理类要服从协议
5.代理类实现协议中的方法
6.委托方通知代理来执行任务

14.通知和协议的不同之处?
协议有控制链,通知没有
简单来说,通知的话,它可以一对多,一条消息可以发送给多个消息接收者。
代理按我们的理解,到不是直接说不能一对多,比如我们知道的明星经纪代理人,很多时候一个经纪代理人负责好几个明星的事物。只是对于不同明星间,代理的事物都是不一样的,一一对应,不可能说明天要处理A明星要一个发布会,代理人发出处理发布会的消息后,变成B的发布会了。但是通知就不一样,他只关心发出通知,而不关心多少接收到感兴趣要处理。
因此控制链(has-a),单一拥有和可控制的对应关系。

15.Objective-C中的协议和java中的接口概念有何不同?
Objective-C中的代理有两层含义,官方定义为formal和informalprotocol。前者和java接口一样。informalprotocol中的方法属于设计模式考虑范畴,不是必须实现的,但是如果有实现,就会改变类的属性。
非正式协议概念其实就是类别的另一种表达方式,这里有一些你可能希望实现的方法,你可以使用他们更好的完成工作。这个意思是,这些是可选的。如果我们要一个更好的方法,我们就会申明一个这样的类别去实现。然后你在后期可以直接使用这些更好的方法。这么看,总觉得类别这玩意儿有点像协议的可选协议。
现在来看,其实protocol已经开始对两者都统一规范起来操作,因为资料中说非正式协议使用interface修饰,现在我们看到协议中两个修饰词:必须实现(@requied)和可选实现(@optional)。

16.Objective-C的类可以多重继承吗?可以实现多个接口吗?category是什么?重写一个类的方式用继承好还是分类好?为什么?
Objective-C的类不可以多重继承,可以实现多个接口,通过实现多个接口可以完成C++的多重继承;category是类别,一般情况用分类好,用category去重写类的方法,仅对本cagegory有效,不会影响到其他类与原类的关系。

四.static

17.static关键字的作用
1.函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只分配一次,因此其值在下次调用时仍维持上次的值;
2.在模块内的static全局变量可以被模块内所有函数访问,但不能被模块外的其他函数访问;
3.在模块内的static函数只可被这一模块内的其他函数调用,这个函数的使用范围被限制在声明它的模块内;
4.在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
5.在类中的static成员函数属于整个类所拥有,这个函数不接受this指针,因而只能访问类的static成员变量;

18.static有什么用途?
限制变量的作用域
设置变量的存储域

19.解释一下关键字static,self,super用实例说明
static:静态全局变量,持久性作用,存储区域在静态区域,它的生命周期和应用进行绑定。程序结束时,由系统自动回收。
self:当前消息的接收者。
super:向父类发送消息。

20.如何引用一个已经定义过的全局变量
extern可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变量,假定你将那个变量写错了,那么在编译间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么编译期间不会报错,而在连接期间报错;

五.内存管理

21.简述内存管理基本原则
1.如果使用alloc,new,copy(mutableCopy)或者retain一个对象时,你就有义务向它发送一条release或者autorelease消息。其他方法创建的对象,不需要由你来管理内存。
2.向一个对象发送一条autorelease消息,这个对象并不会立即销毁,而是将这个对象放入自动释放池,待池子释放时,它会想池中每一个对象发送一条release消息,以此来释放对象。
3.向一个对象发送release消息,并不意味着这个对象被销毁了,而是当这个对象的引用计数为0时,系统才会调用dealloc方法,释放该对象和对象本身它所拥有的实例。

22.Objective-C如何对内存管理的,说说你的看法和解决方法

23.内存管理的几条原则时什么?
谁申请,谁释放
内存管理主要避免“过早释放”和“内存溢出”,对于“过早释放”需要注意@property设置特性时,一定要用对特性关键字,对于“内存泄漏”,一定要申明了要负责释放,要细心。
关键字alloc或new生成的对象需要手动释放;
设置正确的property属性,对于retain需要在合适的地方释放

24.内存管理的几条原则是什么?按照默认法则,哪些关键字生成的对象需要手动释放?哪些情况下不需要手动释放,会直接进入自动释放池?
当使用new,alloc或copy方式创建一个对象时,该对象引用计数器为1。如果需要使用该对象,可以向其发送release或autorelease消息,在其使用完毕时被销毁。
如果通过其他方法获取一个对象,则可以假设这个对象引用计数为1,并且被设置为autorelease,不需要对该对象进行清理,如果确实需要retain这个对象,则需要使用完毕后release。
如果retain了某个对象,需要release或autorelease该对象,保持retain方法和release方法使用次数相等。
使用new,alloc,copy关键字生成的对象和retain了的对象需要手动释放。设置为autorelease的对象不需要手动释放,会直接进入自动释放池。

25.Objective-C内存管理
如果您通过分配和初始化的方式来创建对象,您就拥有这个对象,需要负责该对象的释放。这个规则在使用NSObject的方法new时也同样适用。
如果您拷贝一个对象,您也拥有拷贝得到的对象,需要负责该对象的释放。
如果您保持一个对象,您就部分拥有这个对象,需要在不再使用时释放该对象。
如果您从其他对象那里接收到一个对象,则您不拥有该对象,也不应该释放它。

26.自动释放池是什么,如何工作?
当您向一个对象发送一个autorelease消息时,Cocoa就会将对象的一个引用放入到最新的自动释放池。它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放。
1.Objective-C是通过一种“referring counting”(引用计数)的方式来管理内存的,对象在开始分配内存的时候引用计数为1,以后每当碰到有copy,retain的时候引用计数都会加1,每当碰到release和autorelease的时候就会减1,如果对象的计数变为0,就会被系统销毁。
2.NSAutoreleasePool就是用来做引用计数的管理工作的,这个东西一般不用你管的。
3.autorelease和release没什么区别,只是引用计数减1的时机不同而已,autorelease会在对象的使用真正结束的时候才会引用计数减1。

27.如果我们不创建内存池,是否有内存池提供给我们?
界面线程维护着自己的内存池,用户自己创建的数据线程,则需要创建该线程的内存池。

28.什么时候需要在程序中创建内存池
用户自己创建的数据线程,则需要创建该线程的内存池

29.自动释放池是什么?如何工作?
自动释放池是NSAutoreleasePool类的一个实例,当向一个对象发送autorelease消息时,该对象会自动入池,待池销毁时,将会向池中的对象发送一条release消息,释放对象。[pool release];[pool drain]表示的是池本身。

30.当我们将一个对象加入自动释放池时,该对象何时被销毁?
我们在application kit应用程序中,自动释放池中的临时对象被销毁的时候是,一个事件循环结束后。注意自动释放池没有被释放,而是被排空了,向池发送了drain消息。

31.Objective-C的垃圾回收机制?
Objective-C2.0有Garbage collection,但是iOS平台不提供。

六.内存管理

32.堆和栈的区别
管理方式:对于栈来讲,是由编译器自动管理,无需我们手动管理;对于堆来说,释放工作由程序员控制,容易产生memory leak。
申请大小:
栈:在windows下,栈是向低地址扩展的数据结构,是一块连续的内存区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在windows下,栈的大小是2M,如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获取的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获取的空间比较灵活,也比较大。
碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出。
分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆的不同,他的动态分配是由编译器进行释放,无需我们手动实现。
分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持;分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。

33.堆和栈的区别
1.栈区:由编译器自动分配释放,存放函数的参数值,局部变量的值等。先进后出。
2.堆区:一般由程序员分配释放,若程序员不释放,程序结束时由OS回收。
3.全局区:全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量是一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后有系统释放。
4.文字常量区:常量字符串就是放在这里的。程序结束后由系统释放。
5.程序代码区:存放函数体的二进制代码。

34.Heap和stack的差别
stack的空间由操作系统自动分配/释放,Heap上的空间手动分配/释放。
stack空间有限,Heap是很大的自由存储区,C中的malloc函数分配的空间即在堆上,C++中对应的是new操作符。程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行。

35.堆和栈上的指针
指针所指向的这块内存是在哪里分配的,在堆上称为堆上的指针,在栈上称为栈上的指针。
在堆上的指针,可以保存在全局数据结构中,供不同函数使用访问同一块内存。
在栈上的指针,在函数退出后,该内存即不可访问。

36.全局变量和局部变量在内存中是否有区别?如果有,是什么区别?
全局变量存储在静态区,局部变量在栈

37.堆栈溢出一般是由什么原因导致的?
没有回收垃圾资源

七.block,委托
38.什么是block
对于闭包,有很多定义,其中闭包就是能够读取其他函数内部变量的函数。

39.block实现原理
http://blog.csdn.net/jasonblog/article/details/7756763

40.谈谈对block的理解?并写出一个使用block执行UIView动画?
block是可以获取其他函数局部变量的匿名函数,其不但方便开发,并且可以大幅度提高应用的执行效率(多核心CPU可直接处理block指令)。
[UIView transitionWithView:self.view
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
}
completion:NULL];

41.写出上面代码的block的定义
typedef void(^animation)(void);
typedef void(^completion)(BOOL finished);

42.试着使用+beginAnimations:context:以及上述block的定义,写出一个可以完成
+ (void)transitionWithView:(UIView*)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void(^)(void))animations completion:(void(^)(BOOL finished))completion

43.委托是什么?委托和委托双方的property声明用什么属性?为什么?
委托:一个对象保存另一个对象的引用,被引用对象实现了事先确定的协议,该协议用于将应用对象中的变化通知给被应用对象。
委托和委托双方的property声明的属性都是assign而不是retain。
为了避免循环引用造成的内存泄漏。

44.循环引用的问题这样理解
比如在main函数中创建了两个类的对象A和B,现在引用计数都是1。现在让A和B相互引用,现在两个对象的引用计数都增加了1,都变成了2。
现在执行[A release];[B release];此时创建对象的main函数已经释放了自己对对象的所有权,但是此时A和B的引用计数都还是1,因此他们相互引用了。
这时你发现A和B将无法释放,因为要想释放A必须先释放B,在B的delloc方法中在释放A。同理,要想释放B必须先释放A,在A的delloc方法中再释放B。所以这两个对象将一直存在在内存中而不释放。这就是所谓的循环引用的问题。要想解决这个问题,一般的方法可以将引用的属性设置为assign,而不是retain来处理。

八.线程 进程 多线程

46.线程与进程的区别和联系?
进程和线程都是由操作系统所管理的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,消耗资源较大,效率要差一些。但对于一些要求同步进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

47.进程和线程
进程是一块包含了某些资源的内存区域。操作系统利用进程把它的工作划分为一些功能单元。
进程中所包含的一个或多个执行单元称为线程。进程还拥有一个私有的虚拟地址空间,该空间仅能被它所包含的线程访问。
通常在一个进程中可以包含若干个线程,它们可以利用进程所拥有的资源。
在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位。
由于线程比进程更小,基本上不拥有系统资源,故对它的调度所付出的开销就会更小得多,能更高效提高系统内多个程序间并发执行的程度。
简而言之,一个程序至少有一个进程,一个进程至少有一个线程,一个程序就是一个进程,而一个进程中的多个任务则被称为线程。
线程只归属于一个进程并且它只能访问该进程所拥有的资源。当操作系统创建一个进程后,该进程会自动申请一个名为主线程或首要线程的程序。应用程序是由一个或多个相互协作的进程组成的。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口,顺序执行序列和程序的出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的金本单位,线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源,但是它可与同属一个进程的其它的线程共享进程所拥有的全部资源。
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行。

48.进程和线程的差别
线程是进程内的一个执行单元,也是进程内的可调度实体。
区别:
1.调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。
2.并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行。
3.拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源。
4.系统开销:在创建或撤销进程时,由于系统要为之分配和回收资源,导致系统的开销明显大于创建或撤销线程时的开销。

49.网络编程中设计并发服务器,使用多进程与多线程,请问有什么区别?
1.进程:子进程是父进程的复制品。子进程获得父进程数据空间,堆和栈的复制品。
2.线程:相对与进程而言,线程是一个更加接近与执行体的概念,它可以与同进程的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。两者都可以提高程序的并发度,提高程序运行效率和响应时间。线程和进程在使用上各有优缺点:线程进行开销小,但不利于资源管理和保护;而进程正相反。线程适合于在SMP机器上运行,而进程则可以跨机器迁移。

50.多线程是什么
多线程是个复杂的概念,按字面意思是同步完成多项任务,提高了资源的使用效率,从硬件,操作系统,应用软件不同的角度去看,多线程被赋予不同的内涵,对于硬件,现在市面上多数的CPU都是多核的,多核的CPU运算多线程更为出色;从操作系统角度,是多任务,现在用的主流操作系统都是多任务的,可以一边听歌,一边写博客;对于应用来说,多线程可以让应用有更快的回应,可以在网络下载时,同时响应用户的触摸操作。在iOS应用中,对多线程最初的理解,就是并发,它的含义是原来先做烧水,再摘菜,再炒菜的工作,会变成烧水的同时去摘菜,最后去炒菜。

51.iOS中的多线程
iOS中的多线程,是Cocoa框架下的多线程,通过Cocoa的封装,可以让我们更为方便的使用线程,做过C++的同学可能会对线程有更多的理解,比如线程的创建,信号量,共享变量有认识,Cocoa框架下会方便很多,它对线程做了封装,有些封装,可以让我们创建的对象,本身便拥有线程,也就是线程的对象化抽象,从而减少我们的工程,提供程序的健壮性。
GCD,从系统级别提供的一个易用地多线程类库,具有运行时的特性,能充分利用多核硬件。GCD的API接口为C语言的函数,函数参数中多数有block。
NSOperation是一个抽象类,它封装了线程的细节实现,我们可以通过子类化该对象,加上NSQueue来同面向对象的思想,管理多线程程序。
NSThread是一个控制线程执行的对象,它不如NSOperation抽象,通过它我们可以方便地得到一个线程,并控制它。但NSThread的线程之间的并发控制,是需要我们自己来控制的,可以通过NSCondition实现。

52.在项目什么时候选择使用GCD,什么时候选择NSOperation?
项目中使用NSOperation的优点是NSOperation是对线程的高度抽象,在项目中使用它 ,会使项目的程序结构更好,子类化NSOperation的设计思路,是具有面向对象的优点,使得实现是多线程支持,而接口简单,建议在复杂项目中使用。
项目中使用GCD的优点是,GCD本身非常简单,易用,对于不复杂的多线程操作,会节省代码量,而block参数的使用,会是代码更为易读,建议在简单项目中使用。

53.NSOperation Queue?
存放NSOperation的集合类。

54.Objective-C中创建线程的方法是什么?如果在主线程中执行代码,方法是什么?如果想延时执行代码,方法又是什么?
线程创建有三种方法:使用NSThread创建,使用GCD的dispatch,使用子类化的NSOperation,然后将其加入NSOperationQueue;
在主线程执行代码:
1.- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullableid)arg waitUntilDone:(BOOL)wait;
2.dispatch_async(dispatch_get_main_queue,^{
});
3.[[NSOperatonQueue mainQueue] addOperationWithBlock:^{
}];
4.[[NSOperationQueue mainQueue] addOperation:myOperation];
延时执行代码:
1.- (void)performSelector:(SEL)aSelector withObject:(nullableid)anArgument afterDelay:(NSTimeInterval)delay;
2.GCD的dispatch_after方法

55.多线程
多线程编程是防止主线程堵塞,增加运行效率等灯的最佳方法。而原始的多线程方法存在很多的毛病,包括线程锁死等。

九.键路径

56.什么是键-值,键路径是什么
模型的性质是通过一个简单的键来指定的。视图和控制器通过键来查找相应的属性值。在一个给定的实体中,同一个属性的所有值具有相同的数据类型。键-值编码技术用于进行这样的查找,它是一种间接访问对象属性的机制。
键路径是一个由用点作为分隔符的键组成的字符串,用于指定一个连接在一起的对象性质序列。第一个键的性质是由先前的性质决定的,接下来每个键的值也是相对于其前面的性质。键路径使您可以独立于模型实现的方式指定相关对象的性质。通过键路径,您可以指定对象图中的一个任意深度的路径,使其指向相关对象的特定属性。

十.保存数据

58.在iPhone应用中如何保存数据?
1.用NSUserDefaults存储配置信息
2.用CoreData规划应用对象
3.文件沙盒存储
4.数据库存储

59.什么是CoreData?
CoreData是苹果提供一套数据保存框架,其基于SQLite。

60.什么是NSManagedObject模型?
NSManagedObject是NSObject的子类,也是coredata的重要组成部分,它是一个通用的类,实现了coredata模型层所需的基本功能,用户可通过子类化NSManagedObject,建立自己的数据模型。

61.什么是NSManagedObjectContext?
NSManagedObjectContext对象负责应用和数据之间的交互。

62.和CoreData一起有哪几种持久化存储机制?
存入到文件,存入到NSUserDefaults(系统plist文件中),存入到Sqlite文件数据库。

63.iOS开发中数据持久化有哪几种?
文件写入,对象归档,sqlite3数据库,CoreData。

64.对象归档的基本概念,以及它的特点是什么?
归档为对象的数据持久化提供了一种解决方法,它特点是给归档的对象进行加密,增强了数据的安全性。此外,自定义类的对象归档必须实现NSCoding协议。

65.什么是沙盒,文档目录结构的作用?
iOS应用程序只能在该程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒。每个应用程序都有自己的存储空间;应用程序不能翻过自己的围墙去访问别的存储空间的内容;应用程序请求的数据都要通过权限检测,假如不符合条件的话,不会被放行。
Documents目录:您应该将所有的应用程序数据文件写入到这个目录下。这个目录用于存储用户数据或其它应该定期备份的信息。
AppName.app目录:这是应用程序的程序包目录,包含应用程序的本身。由于应用程序必须经过签名,所以在运行时不能对这个目录中的内容进行修改,否则可能会使应用程序无法启动。
Library目录:这个目录下有两个子目录:Caches和Preferences
Preferences目录包含应用程序的偏好设置文件。我们不应该直接创建偏好设置文件,而是应用使用NSUserDefaults类来取得和设置应用程序的偏好。
Caches目录用于存放应用程序专用的支持文件,保存应用程序再次启动过程中的重要的信息。
temp目录:这个目录用于存放临时文件,保存应用程序再次启动过程中不需要的信息。
获取这些目录路径的方法:
1.获取Home目录路径的函数
NSString *homeDir = NSHomeDirectory();
2.获取Documents目录路径的方法
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
3.获取Caches目录路径的方法
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask, YES);
NSString *cachesDir = [paths objectAtIndex:0];
4.获取tmp目录路径的方法
NSString *tmpDir = NSTemporaryDirectory();
5.获取应用程序程序包中资源文件路径的方法,例如获取程序包中一个图片资源(apple.png)路径的方法
NSString *imagePath = [[NSBundle mainBundle] pathForResource:@”apple”ofType:@”png”];
UIImage *appleImage = [[UIImage alloc] initWithContentsOfFile:imagePath];

十一.单例设计模式

66.怎么样实现一个单例模式的类
@interface Tools()

@end

@implementation Tools

static Tools *_instance;

+(instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
if (_instance == nil){
_instance = [super allocWithZone:zone];
}
});
}

+(Tools *)instance {
return [[self alloc] init];
}

-(id)copyWithZone:(NSZone *)zone {
return _instance;
}

-(id)mutableCopyWithZone:(NSZone *)zone {
return _instance;
}

@end

十二.KVC和KVO观察者模式

70.什么是KVC和KVO?它们之间的关系是什么
KVC(键值编码)是一种间接访问对象实例变量的机制,该机制可以不通过存取方法就可以访问对象的实例变量。非对象类型的变量将被自动封装或者解封成对象。此外,使用KVC能够简化代码。我们需要注意KVC有两个较为明显的缺点,一旦使用KVC你的编译器无法检查出错误,即不会对设置的键,键路径进行错误检查,且执行效率要低于合成存取方法和自定义的setter和getter方法。因为使用KVC键值编码,它必须先解析字符串,然后在设置或者访问对象的实例变量。
KVO是一种能使得对象获取到其他对象属性变化的通知机制。
实现KVO键值观察模式,被观察的对象必须使用KVC键值编码来修改它的实例变量,这样才能被观察者观察到。因此,KVC是KVO的基础或者说KVO的实现是建立在KVC的基础之上的。

71.什么是KVO和KVC

72.如何实现KVO
注册观察者
接收变更通知
移除对象的观察者身份

73.代理,通知和KVO的区别以及它们的优缺点
代理是一种回调机制,且是一对一的关系,而通知是一对多的关系,一个中心对象向所有的观察者提供变更通知,KVO是被观察者向观察者直接发送通知,这是通知和KVO的区别。
代理的优点:
1.非常严格的语法。所有将听到的事件必须是在delegate协议中有清晰的定义。
2.如果delegate中的一个方法没有实现那么就会出现编译警告/错误。
3.协议必须在controller的作用域范围内定义。
4.在一个应用中的控制流程是可跟踪的并且是可识别的。
5.在一个控制器中可以定义多个不同的协议,每个协议有不同的delegate。
6没有第三方对象要求保持/监视通信过程。
7.能够接收调用的协议方法的返回值。这意味着delegate能够提供反馈信息给controller。
代理的缺点:
1.需要定义很多代码:协议定义;controller的delegate属性;在delegate本身中实现delegate方法定义
2.在释放代理对象时,需要小心的将delegate改为nil。一旦设定失败,那么调用释放对象的方法将会出现内存crash。
3.在一个controller中有多个delegate对象,并且delegate是遵守同一个协议,但还是很难告诉多个对象同一个事件,不过有可能。
通知的优点:
1.不需要编写多少代码,实现比较简单。
2.对于一个发出的通知,多个对象能够做出反应,即一对多的方式实现简单。
3.controller能够传递context对象,context对象携带了关于发送通知的自定义的信息
通知的缺点:
1.在编译期不会检查通知是否能够被观察者正确的处理。
2.在释放注册的对象时,需要在通知中心取消注册。
3.在调试的时候应用的工作以及控制过程能跟踪。
4.需要第三方对象来管理controller与观察者对象之间的联系。
5.controller和观察者需要提前知道通知名称。如果这些没有在工作区定义,那么会出现不同步的情况。
6.通知发出后,controller不能从观察者获取任何的反馈信息。
KVO的优点:
1.能够提供一种简单的方法实现两个对象间的同步。例如:mode和view之间同步。
2.能够对非我们创建的对象,即内部对象的状态作出响应,而且不需要改变内部对象的实现。
3.能够提供观察的属性的最新值以及先前值。
4.用key paths来观察属性,因此也可以观察嵌套对象。
5.完成了对观察对象的抽象,因为不需要额外的代码来允许观察值能够被观察。
KVO的缺点:
1.我们观察的属性必须使用string来定义。因此在编译器不会出现警告以及检查。
2.对属性重构将导致我们的观察代码不再可用。
3.复杂的“IF”语句要求对象正在观察多个值。这是因为所有的观察代码通过一个方法来指向。
4.当释放观察者时不需要移除观察者。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值