iOS面试题 一共分为
笔试题
和面试题
两部分
笔试题
一共分为10个 总共613题
面试题
一共400题
笔试题 一个10个系列 分别为
①(语法篇) 共147题 已更新
②(常识篇) 共72题 已更新
③(界面篇) 共83题 已更新
④(iOS篇) 共52题 已更新
⑤(操作篇) 共68题 已更新
⑥(数据结构篇) 共23题 已更新
⑦(多线程篇) 共60题 已更新
⑧(网络篇) 共22题 已更新
⑨(多媒体篇) 共59题 已更新
⑩(安全篇) 共27题 已更新
面试题
一共分为3个 总共400题
⑪(面试篇 1/3) 共127题 已更新
⑪(面试篇 2/3) 共137题 已更新
⑪(面试篇 3/3) 共136题 已更新
##面试题 400题
id
声明的对象有什么特性
?参考答案:
Id声明的对象具有运动时的特性,即可以指向任意类型的objective-c的对象。
内存管理方式
?参考答案:
Objective-C的内存管理主要有三种方式 ARC(自动内存计数)、手动内存计数、内存池
数据类型
有哪些,和C的基本数据类型
有什么区别
?参考答案:
Objective-C的数据类型有 NSString,NSNumber,NSArray,NSMutableArray,NSData等 这些都是class,创建后便是对象
而C语言的基本数据类型int,只是一定字节的内存空间,用于存放数值; NSInteger是基本数据类型,并不是NSNumber的子类,当然也不是NSObject的子类
NSInteger是基本数据类型Int或者Long的别名(NSInteger的定义typedef long NSInteger),它的区别在于,NSInteger会根据系统是32位还是64位决定本身是int还是long
NSString *obj = [[NSData alloc]init]
;obj在编译时
和运行时
分别是什么类型的对象?参考答案:
编译时是 NSString的类型,
运行时是 NSData的类型的对象。
setter方法
用于完成@property(nontamic,retain
)NSString *name.写一个setter方法
用于完成@property(nontamic,copy
)NSString *name.?参考答案:
retain-(void)setName:(NSString *)str { [str retain]; [name release]; name = str; }
copy
-(void)setName:(NSString *)str { id t = [str copy]; [name release]; name = t; }
readwrite
,readonly
,assign
,retain
,copy
,nonatomic
各有什么作用
?参考答案:
1. readwrite 是可读可写特性
2. readonly 是可读特性 ,只会生成getter方法,不会生成setter方法。不希望属性在类外改变
3. assign 是赋值特性 ,setter方法将传入参数赋值给实例变量,仅设置变量时
4. retain 是持有特性 ,setter方法将传入参数先保留,再赋值,传入参数的retaincount会 + 1
5. copy 是赋值特性 ,setter方法将传入对象,复制一份,需要完成一份新的变量时
6. nonatomic 是否是原子操作 ,atomic表示多线程安全,一般使用nonatomic
#import
跟 #include
有什么区别,@class
呢,#import<>
跟 #import""
又有什么区别?参考答案:
#import 是Objective-C导入头文件的关键字
#include 是C/C++导入头文件的关键字
使用 #import 头文件会自动只导入一次 ,不会重复导入,相当于 #include 和 #pargma once;
@class 则告诉编译器某个类的生命,当执行时,才去查看类的实现文件,可以解决头文件的相互包含
#import<> 用来包含系统的头文件
#import"" 用来包含用户头文件
(atomic
)和非原子(non-atomic)
属性有什么区别?参考答案:
1. atomic 提供多线程安全。是防止在写未完成的时候被另外一个线程读取,造成数据错误。
2. non-atomic 在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果制定了nonatomic,那么访问器只是简单地返回这个值
创建线程
的方法是什么?参考答案:
创建线程有三种方法:
1.使用 NSThread 创建
2.使用 GCD的Dispatch
3.使用 子类话的NSOperation 然后将其加如NSOperationQueue;
主线程中执行代码
,方法是什么?参考答案:
在主线程执行代码,方法是 performSelectorOnMainThread
延迟执行代码
,方法是什么?参考答案:
如果想延迟执行代码可以用 performSelector:onThread:withObject:waitUntilDone
MVC的开发模式
?参考答案:
MVC是 模型、视图、控制器开发模式
对于iOS SDK 所有的View都是视图层 的,它应该独立于模型层,由视图控制器层来控制
所有的用户数据都是 模型层 ,它应该独立于视图
所有的ViewController都是 控制层 ,由它负责控制视图,访问模型数据
类别
的作用
?继承
和类别
在实现
中有何区别
?参考答案:
1. Category 可以在不获悉,不改变原来的代码情况下往里面添加 新的方法,只能添加,不能删除修改。并且如果类别和原来类找那个的方法名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。
类别主要的3个作用
1. 将类的实现分散到多个不同文件或多个不同框架中
2. 创建对私有方法的前向引用
3. 向对象添加非正式协议
继承 可以增加,修改或者删除方法。并且可以增加属性
多重继承
么?可以实现多个接口
么?Category
是什么?重写一个类
的方式用继承好
还是分类好
?为什么?参考答案:
1. Objective-C的类 不可以多重继承
2. 可以实现多个接口 通过实现多个接口完成C++的多重继承
3. Category是类别
4. 一般情况用分类好 ,用Category去重写类的方法,仅对本Category有效,不会影响到其他类与原有类的关系
参考答案:
+(void)initWithCString:(c*****t char *)nullTerminatedCString encoding:(NSStringEncoding)encoding; +(void)initWithCString:(c*****t char *)nullTerminatedCString encoding:(NSStringEncoding)encoding { NSString *obj; obj = [self allocWithZone:NSDefaultMallocZone()]; obj = [obj initWithCString:nullTerminatedCString:nullTerminatedCString encodding:encoding]; return AUTORELEASE(obj); }
static
关键字的作用
?参考答案:
1. 函数体内static 变量的作用范围为该函数体,不同auto变量, 该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值
2. 在模块内的static 全局变量可以被模块内所有函数访问,但不能被模块外其它函数访问;
3. 在模块内的static 函数只可被这一模块内的其他函数调用,这个函数的使用范围被限制在声明 它模块内
4. 在类中 static 成员变量属于整个类所拥有,对类的对象只有一份拷贝;
5. 在类中 static 成员变量属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量
线程
与进程
的区别
和联系
?参考答案:
进程和线程都是由操作系统所体会的程序运行的基本单元。系统利用该基本单元实现系统对应用的并发性。
线程和进程的主要差别在于它们是 不同的操作系统资源管理方式
进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其他进程产生影响, 而线程只是一个进程中的不同执行路径
线程 有自己对的堆栈和局部变量,但线程之间没有单独的独立空间,一个线程死掉等于整个进程死掉,所以多进程的程序要比多线程的程序健壮 但是 进程在切换时,消耗资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程
堆
和栈
的区别
是什么?参考答案:
1.管理方式:
对于栈来讲,是由编译器自动管理,无需我们手动控制;
对于堆来说,释放工作由程序员控制,容易产生memory leak。
2.申请大小-栈:
在Windows下。栈的大小是2M(也有的说是1M。总之是一个编译时就确定的常数),
如果申请的空间超过栈的剩余空间时,将提示Overflow
2.申请大小-堆:
堆是向高地址扩展的数据结构,是不连续的内存区域。
这是由于系统用链表来存储的空闲内存地址的。
自然是不连续的,而链表的遍历方向是由低地址向高地址。
堆的大小受计算机系统中有效地虚拟内存。
由此可见,堆获得空间比较灵活,也比较大。
3.碎片问题:
对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。
对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列。它们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出。
4.分配方式:
堆都是动态分配的,没有静态分配的堆。
栈有2中分配方式:静态分配和动态分配。
静态分配是编译器完成的。比如局部变量的分配
动态分配是由alloca函数进行分配
但是栈的动态分配和堆是不同的。它们动态分配是由编译器进行释放。无需我们手工实现
5.分配效率:
栈是机器系统提供的数据结构,计算机 会在底层栈提供支持:
分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行。这就决定了栈的效率比较高。
堆则是C/C++函数库提供的,它的机制是很复杂的
键-值
,键路径
是什么?参考答案:
模型的性质是通过一个简单的键(通常是个字符串)来指定的。视图和控制器通过键来查找相应的属性值
在一个给定的实体中,同一个属性的所有值具有相同的数据类型。键-值编码技术用于进行这样的查找-它是一种间接访问对象属性的机制
键路径 是一个由用点作分隔符的键组成的字符串,用于指定一个连接在一起的对象性质序列。第一个键的性质是由先前的性质决定的。接下来每个键的值也是相对于其前面的性质
键路径 使您可以独立于模型实现方式指定相关对象的性质。通过键路径,您可以指定对象图中的一个任意深度的路径,使其指向相关对象的特定属性
Target-action
?参考答案:
Target-action 是一种设计模式,直译过来就是 目标-动作机制。
Target目标即我们要调用哪个目标对象的方法
Action动作是行为的意思,就是我们要调用目标对象中的哪一个方法
当时期发生时,事件会被发送到控件对象中,然后再由这个控件对象去触发 Target对象上的Action行为,来最终处理事件
因此 Target-action机制由2部分组成:即目标对象和行为Selector。目标对象指定最终处理事件的对象,而行为Selector则是处理事件的方法
内存管理
?参考答案:
如果您通过分配和初始化(比如 [[MyClass alloc]init]) 的方式创建对象,您就拥有这个对象,需要负责该对象的释放。这个规则在使用NSObject的便利方法new时 也同样适用。
如果你拷贝一个对象。你也拥有拷贝得到的对象,需要负责该对象的释放
如果您保持一个对象。您就部分拥有这个对象,需要在不再使用时释放该对象
反过来,如果您从其他对象哪里接收到一个对象,则您不拥有该对象,也不应该释放它(这个规则有少数的例外,在参考文档有显式的说明
自动释放池
是什么,如何工作
的?参考答案:
1.自动释放池是什么
当您向一个对象发送一个autorelease消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放池。
它仍然是一个正当的对象,因此自动释放池定义的作用域内的其他对象可以向它发送消息
当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放
2.自动释放池如何工作的
1.objc是通过一种referring counting(引用计数)的方式来管理内存的,对象在开始分配内存(alloc)的时候 引用计数为一,以后每当碰到有copy,retain的时候引用计数都会加一,每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0.就会被系统销毁
2.NSAutoreleasePool 就是用来做引用计数的管理工作的。这个东西一般不用您关的
3.autorelease和release没什么区别,只是引用计数减一的时机不同而已。autorelease会在对象使用真正结束的时候才做引用计数减一
参考答案:
类工厂方法 的实现是为了向客户提供方便,它们将分配和初始化合在一个步骤中,返回被创建的对象,并进行自动释放处理。这些方法的形式 +(type)className… 其中className不包含任何前缀
工厂方法 可能不仅仅为了方便使用。它们不但可以将分配和初始化结合在一起。还可以为初始化过程提供对象的分配信息
类工厂方法 的另一个目的是使类提供单例对象。虽然init…方法可以确认一个类在每次程序运行过程只存在一个实例。但是他需要首先分配一个新的实例。然后还必须释放该实例。 工厂方法则可以避免为可能没有用的对象盲目分配内存。
单件实例
是什么?参考答案:
Foundation和Application Kit框架的一些类只允许创建单件对象。即这些类当前进程中的唯一实例。
举例来说, NSFileManager 和 NSWorkspace类在使用时都是基于进程进行单件对象的实例化。当向这些类请求实例的时候,它们会向您传递单一实例的引用,如果该实例还不存在,则首先进行实例的分配和初始化。单件对象充当控制中心的角色,负责指引或协调类的各种服务。
如果类在概念上只有一个实例(比如 NSWorkspace),就应该产生一个单件实例。而不是多个实例;如果将来可能有多个实例。您可以使用单件实例机制。而不是工厂方法或函数
动态绑定
?参考答案:
在运行时确定调用的方法,动态绑定将调用方法的确定推迟到运行时。
在编译时,方法的调用并不和代码绑定在一起,只有消息发送出来之后,才确定被调用的代码。通过动态类型和动态绑定技术,您的代码每次执行都可以得到不同的结果。
运行时 因只负责确定消息的接受者和被调用的方法。
运行时 的消息分发机制为动态绑定提供支持。当您向一个动态类型确定了的对象发送消息时,运行环境系统会通过接受者的isa指针定位对象的类,并以此为起点确定被调用的方法。方法和消息时动态绑定的
而且,你不必在Objective-C代码做任何工作。就可以自动获取动态绑定的好处。您每次发送消息时,特别是当消息的接受者是动态类型已确定的对象,动态绑定就会例行而透明的发生
Objective-C
有哪些优缺点
?参考答案:
Objective-C的优点
1.Cateogies
2. Posing
3. 动态识别
4. 指表计算
5. 弹性讯息传递
6. 不是一个过度复杂的C衍生语言
7. Objective-C与C++的可混合编程
缺点:
1.不支持缓名空间
2. 不支持运算符重载
3. 不支持多重继承
4. 使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到
sprintf
,strcpy
,memcpy
使用上有什么要注意的地方
?参考答案:
1.sprintf 是格式化函数。将一段数通过特定的格式,格式化到一个字符串缓冲区中去。sprintf格式化的函数的长度不可控,有可能格式化后的字符串会超出缓冲区的大小,造成溢出
2.strcpy 是一个字符串拷贝的函数,它的函数原型为 strcpy(char dst, c*****t char src); 将src开始的一段字符串拷贝到dst开始的内存中去,结束的标志符号’\0’,由于拷贝的长度不是由我们自己控制的,所以这个字符串拷贝很容易出错
3.具有字符串拷贝功能的函数有 memcpy ,这是一个内存拷贝函数,它的函数原型为 memcpy(char dst, c****t char *src,unsigned int len); 将长度为len的一段内存,从src拷贝到dst中去,这个函数的长度可控。但是会有内存叠加的问题
delegate
,什么时候调用Notification
?参考答案:
1.delegate 针对one-to-one关系。并且reciever可以返回值给sender
2.notification 可针对one-to-one/many/noce,reciever无法返回值给sender
所以delegate 用于sender希望接受到reciever的某个功能反馈值
notification 用于通知多个object某个事件
KVC
和KVO
?参考答案:
1.KVC(Key-Value-Coding) 内部的实现:一个对象在调用setValue的时候
1.1 首先根据方法名找到运行的方法所需要的环境参数
1.2 他会从自己isa指针结合环境参数,找到具体的方法实现的接口
1.3 再直接查找得来的具体的方法实现
2.KVO(Key-Value-Observing) 当观察者为一个对象的属性进行了注册,被观察对象的isa指针被修改的时候。isa指针就会指向一个中间类,而不是真实的类。所以isa指针其实不需要指向实例对象真实的类。所以我们的程序最好不要依赖isa指针。在调用类的方法的时候。最好要明确对象实例的类名
loadview
,viewDidLoad
,viewDidUnload
分别在什么时候调用
的?参考答案:
1.loadview 在controller的view为nil时调用,此方法在编程实现view时调用,view控制器摩恩会注册 memory warning notification
2.viewDidLoad 在view从nib文件初始化调用
3.当view controller的任何view没有用的时候,viewDidUnload 会被调用,在这里实现将retain的view release,如果retain的IBOutlet view属性则不要在这里release。IBOutlet会负责release
类别
的作用
是什么?参考答案:
类别主要的3个作用
1. 将类的实现分散到多个不同文件或多个不同框架中
2. 创建对私有方法的前向引用
3. 向对象添加非正式协议
类别的局限性 有两个方面局限性
1. 无法向类中添加实例变量,类别没有位置容纳实例变量
2. 名称冲突,
即当类别中的方法与原始类方法名称冲突时,类别具有更高的优先级。
类别方法将完全取代初始方法。从而无法再使用初始方法。
无法添加实例变量的局限可以使用字典对象解决
volatile
有什么含义
?并给出三个不同例子。参考答案:
一个定义为 volatile的变量是说明变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了。精准地说就是,优化器在用到这个变量时必须每次都消息地重新读取这个变量的值。而不是使用保存在寄存器里的备份
下面是> volatile变量的几个列子
1. 并行设备的硬件寄存器(如:状态寄存器)
2. 一个中断服务子线程中会访问到非自动变量(Non-automatic variables)
3.多线程应用中被几个任务共享的变量)
@synthesize
是系统自动生成getter
和setter
属性声明吗?参考答案:
@dynamic是开发者自己提供相应的属性声明。对于只读属性需要提供setter,对于读写属性需要提供setter和getter
@synthesize意思是,除非开发人员已经做了。否则编译器生成相应的代码。以满足属性声明。
@dynamic的意思是告诉编译器,属性的获取与赋值方法由用户自己实现,不自动生成。
浅复制
和深复制
的区别?参考答案:
浅层复制:只复制指向对象的指针,而不复制引用对象本身。
深层复制:复制引用对象本身。
意思就是说我有A对象,复制一份后得到A_copy对象后,
对于浅复制来说,A和A_copy指向的是同一个内存资源。复制的只不过是一个指针。对象本身资源还是只有一份
那么我们对A_copy执行了修改操作。那么发现A引用的对象同样被修改,这其实违背我们复制拷贝的一个思想。
深复制就好理解了,内存中存在了两份独立对象本身
类别
的作用
?继承
和类别
在实现有何区别。参考答案:
类别只是对现有的类进行完善其功能
继承 也可以实现这一目的,但是继承实际上从新创建了一个新的类,可以达到同样目的,
但是类别更倾向于从方法上对现有类做一些很简单的功能上的扩展,比较方便,类别不能增加新的实例变量。
如果引入新的实例变量。只能继承了
类别主要的3个作用
1. 将类的实现分散到多个不同文件或多个不同框架中
2. 创建对私有方法的前向引用
3. 向对象添加非正式协议
继承 可以增加,修改或者删除方法。并且可以增加属性
类别
和类扩展
的区别
?参考答案:
category和 extensions 不同的在于后者可以添加属性,另外后者添加的方法是必须要实现的。
extensions 可以认为是一个私有的 Category。
oc
中的协议
和 java
中的接口
概念有何不同?参考答案:
OC的 代理 有2层含义。官方定义 formal和 informal protocol。前者和java接口一样。informal protocol中的方法属于设计模式考虑范畴,不是必须实现的,但是如果有实现,就会改变类的属性
其实关于正式协议, 类别 和非正式协议 我很早前学习的时候大致看过,也写在了学习教程里 -非正式协议概念其实就是类别的另一种变大方式-这里有一些您可能希望实现的方法。你可以使用它们更好地完成工作
这个意思是,这些是可选的。比如需要一个更好地方法。我们就会申请一个这样的类别去实现。然后你在后期可以直接使用这些更好地方法。这么看,总觉得类别这玩意优点像协议的可选协议。
代理
的作用
?参考答案:
代理的目的就是改变或传递控制链。允许一个类在某些特定时刻通知到其他类,而不需要获取到哪些类的指针。可以减少框架复杂度。另外一段,代理可以理解为java中的回调监听机制的一种类似
可变
和不可变
类型?参考答案:
可修改不可修改的集合类这个我个人简单理解就是可动态添加修改和不可动态添加修改一样。
不如NSArray和MSMutableArray。 前者在初始化后的内存控件就固定不可变的。后者可以添加等。可以动态申请的内存控件。
动态运行时
语言是什么意思?参考答案:
多态主要是将数据类型的确定由编译器时,推迟到了运行时。这个问题其实涉及到两个概念,运行时和多态
简单来说,运行时机制 我们直到运行才决定一个对象的类别,以及调用该类别对象指定方法/font>
多态:不同对象以自己的方式响应相同的消息的能力叫多态。意思就是假设生物类(life)都用有一个相同的方法-eat,那么人类属于生物,猪也属于生物,都继承了life后,实现各自的eat。
但是调用是我们只需调用各自的eat方法。
也就是不同的对象以自己的方式响应了相同的消息(响应了eat这个选择器)
因此也就是说,运行时机制是多态的基础
推送消息
?参考答案:
推送通知更是一种技术
简单点就是客户端获取资源的一种手段。普通情况下,
都是客户度主动的pull。
推送则是服务端主动push
多态性
的理解?参考答案:
多态简单的说就是对不同对象响应同一个方法时 做出不同反应。(不同对象以自己的方式响应相同的消息)。
在OC中动态类型id是是实现多态的一种方式,id是一个独特的数据类型,可以转换为任何数据类型。
响应者链
?参考答案:
响应者:对用户交互动作事件进行响应的对象。
响应者链:成为处理事件的响应者的先后顺序链。
如果一个View 有一个视图控制器(ViewController),
它的下一个响应者是这个视图控制器,紧接着才是它的父视图(Super View),
如果一直到RootView都没有处理这个事件,事件会传递到UIWindow(iOS有一个单例Window),
此时window如果也没有处理事件,
便进入UIApplication,UIApplication是一个响应者链的重点,它的下一个响应者指向nil,已结束整个循环
frame
和 bounds
有什么不同?参考答案:
frame指的是:该view在父view坐标系统中的位置和大小(参照点是父亲的坐标系统)
bounds指的是:该view在本身坐标系统中的位置和大小(参照点是本身坐标系统)
方法
和 选择器
有何不同 ?参考答案:
selector是一个方法的名字
method是一个组合体,包含了名字和实现
NSOPeration queue
?参考答案:
存放 NSOPeration的集合体。
操作和操作队列。基本可以看成java中的线程和线程池的概念
用于处理iOS多线程开发的问题
惰性加载
?参考答案:
只在用来的时候才去初始化。也可以理解为 延迟加载
最好也最简单的一个例子就是tableview中图片的加载显示了。
一个延时记载。避免内存过高。一个异步加载,避免线程堵塞。
视图控制器
中嵌入两个tableview控制器
?参考答案:
一个视图控制器只提供了一个View视图,理论上一个tableviewController也不能放吧。
只能说可以嵌入一个tableview视图。
当然一个视图控制器嵌入多少个 tableview都是可以的
tableview
是否可以关联
两个不同的数据源
。你会怎么处理?参考答案:
首先从代码来看,数据源如何关联上的,
其实是在数据源关联的代理方法里实现的。
因为我们并不关系如何去关联他,他怎么关联上,方法只是让我返回根据自己的需要去设置
如相关的数据源。
当然可以设置多个数据源。在数据源关联的代理方法合并两个数据源即可。
id
、nil
代表什么?参考答案:
id和void * 并非完全一样。
id 是指向 struct objc_objc的一个指针
这个意思基本上是说,id是一个指向任何一个继承了Object(或者NSObject)类的对象。
需要注意的是id是一个指针。所以你在使用id不需要加星号。
比如 id foo = nil 定义了一个nil指针。这个指针指向NSObject的一个任意子类。
而 id *foo = nil 则定义了一个指针,这个指针指向另一个指针。被指向的这个指针指向NSObject的一个子类。
nil和C语言的NULL相同,在objc/objc.h中定义。
nil表示一个Object-C对象,这个对象的指针指向空(没有东西就是空)。
首字母大写Nil和nil有一点不一样。
Nil定义个指向空的类(是Class,而不是对象)。
SEL是Selector的一个类型,表示一个方法的名字 Method (我们常说的方法)表示一种类型,这种类型与Selector和实现(implementation)相关。
IMP定义为 id(* IMP)(id,SEL,…)。
层
和UIView
的区别是什么?参考答案:
两者最大的区别是,图层不会直接渲染到屏幕上,
UIview是iOS系统中界面元素的基础,所有的界面元素都是继承自它。
CALayer它本身完全是由CoreAnimation来实现的。它真正的绘图部分。是由一个CALayer类来管理的。
UIView本身更像是一个CALayer的管理器。一个UIView上可以有n个CALayer,每个layer显示一种东西。增强UIView的展示能力。
GCD
的?参考答案:
Grand Central Dispatch(GCD) 是Apple开发的一个多核线程的较新的解决方法。
它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。
它是一个在线程池模式的基础上执行的并行任务。
在macOSX 10.6雪豹首次推出,也可在iOS 4以上版本使用
它具有以下优点:
GCD能通过推迟昂贵计算任务并在后台运行它们来改善应用的响应性能。
GCD提供了一个易于使用的并发模型而不仅仅只是锁和线程。以帮助我们避开并发陷阱。
GCD具有在常见模式(例如单例)上用更高性能的原语优化你的代码的潜在能力。
可扩展标记语言
extensible markup language XML?参考答案:
XML 指可扩展标记语言(Extensible Markup Language)
XML 是一种标记语言,很类似HTML
XML 的设计宗旨是传输数据,而非显示数据
XML 标签没有被预定义,您需要自定义标签。
XML 被设计为具有自我描述性。
XML W3C的推荐标准
XML
与 HTML
的区别?参考答案:
XML与HTML的设计区别 是:
XML的核心是数据,其重点是数据的内容。
而HTML被设计用来显示数据,其重点是数据地显示
XML与HTML的语法区别 是:
HTML的标记不是所有的都需要成对出现
XML则要求所有的标记必须成对出现;
HTML标记不区分大小写
XML则大小敏感,即区分大小写
XML不是HTML的替代。
XML和HTML为不同的目的而设计:
XML被设计为传输和存储数据,其焦点是数据的内容。
HTML被设计用来显示数据,其焦点是数据的外观。
HTML旨在显示信息,而XML旨在传输信息。
HTTP协议
的主要特点
?参考答案:
1.支持客户/服务器模式
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有
GET、HEAD、POST。
每种方法规定了客户与服务器联系的类型不同。
由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完用户的请求,并收到用户的应答后,即断开连接。采用这种方式节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是值协议对事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息。则它必须重传。这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
TCP
/UDP
区别联系?参考答案:
TCP—传输控制协议,提供的是面向连接,可靠的字节流服务。
当客户和服务器彼此交换数据前,必须先在双方质安监建立一个TCP连接,之后才能传输数据。
TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据从一端传到另一端。
UDP—用户数据报协议。是一个简单的面向数据报的运输层协议。
UDP不提供可靠性。它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。
由于UDP在传输数据报前不用在用户和服务端之间建立一个连接,且没有超时重发等机制。故而传输速度很快
socket连接
和http连接
的区别
?参考答案:
socket连接,socket连接就是所谓的长链接,理论上客户端和服务端一旦建立起连接不会主动断掉。
但是由于各种环境因素可能会是连接断开,比如说:服务器端或客户端主机down了。网络故障,或者两者之间长时间没有数据传输,网络防火墙可能会断开该连接以释放网络资源。
所以当一个socket连接中没有数据的传输,那么为了维持连接需要发送心跳消息~~具体心跳消息格式是开发者自己定义的
http连接。http连接就是所谓的短连接,即客户端向服务端发送一次请求,服务器响应后连接即会断掉。
由于UDP在传输数据报前不用在用户和服务端之间建立一个连接,且没有超时重发等机制。故而传输速度很快
TCP连接
的三次握手
?参考答案:
第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器受到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端受到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕。客户端和服务器进入ESTABLISHED状态。完成三次握手。
握手过程中传送的包不包含数据。三次握手完毕后。客户端与服务器才正式开始传送数据。
理想状态下,TCP连接一旦建立。杂通信双方总的任何一方主动关闭连接之前,TCP连接都将一直保持下去。
socket
建立网络连接
的步骤
?参考答案:
建立socket连接至少需要一对套接字。
其中一个运行于客户端。称为ClientSocket。
另一个运行于服务器。称为ServerSocket。
套接字之间的过程分为三个步骤:
服务器监听,客户端请求,连接确认。
1.服务器监听:服务器套接字并不定位具体的客户端套接字。而是处于等待连接的状态。实时监控网络状态,等待客户端的连接请求。
2.客户端请求:指客户端的套接字提出连接请求,要求连接的目标是服务器端的套接字为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
3.连接确认:当服务器套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器套接字的描述发送给客户端,一旦客户端确认了此件数,双方就正式建立连接。
而服务器端套接字继续处于监听状态,继续接受其他客户端套接字的连接请求。
栈
和堆
上的指针
的理解?参考答案:
指针所指向的这个块内存是在哪里分配的,
在堆上称为堆上的指针。
在栈上为栈上的指针。
在堆上的指针。可以保存在全局数据结构中,供不同函数使用访问同一块内存。
在栈上的指针,在函数推出后,该内存即不可访问。
指针
的释放
?参考答案:
具体来说包括两个概念。
1.释放该指针指向的内存,只有堆上的内存才需要我们手工释放。栈上的不需要
2.将指针重定向为NULL
数据结构
中的指针
?参考答案:
其实就是指向一块内存的地址,通过指针传递,可实现复杂的内访问。
函数指针
?参考答案:
指向一块函数的入口地址。
指针
作为函数
的参数
?参考答案:
比如指向一个复杂数据结构的指针作为函数变量。
这种方法避免整个复杂数据类型内存的压栈出栈操作。提高效率
注意:指针本身不可变,但是指针指向的数据结构可以改变。
指向指针
的指针
?参考答案:
指针指向的变量是一个指针。即具体内容为一个指针的值,是一个地址。
此时指针指向的变量长度也是4位。
指针
与地址
的区别?参考答案:
1.指针意味着已经有一个指针变量存在。它的值是一个地址。指针变量本身也存放在一个长度为四个字节的地址当中
而地址概念本身并不代表任何变量存在。
2.指针的值,如果没有限制。通常是可以变化的。也可以指向另一个地址。
地址表示内存空间的一个位置点,他是用来赋给指针的。地址本身没有大小概念。
指针指向变量的大小,取决于地址后面存放的变量类型。
指针
与数组名
的关系?参考答案:
其值都是一个地址。但前者是可以移动的。后者是不可变的。
防止
指针的越界
使用问题?参考答案:
必须让指针指向一个有效的内存地址:
1.防止数组越界
2.防止向一块内存中拷贝过多的内容
3.防止使用空指针
4.防止改变const修改的指针
5.防止改变静态存储区的内容
6.发放两次释放一个指针
7.防止使用野指针
参考答案:
指针转换通常是指针类型和 void *类型之前进行强制转换。
从而与期望或返回 void 指针的函数进行正确的交接。
static
有什么用途(请至少说两种)参考答案:
1.限制变量的作用域
2.设置变量的存储域
参考答案:
1.引用必须被初始化,指针不必。
2.引用初始化以后不能被改变。指针可以改变所指的对象
3.不存在指向空值的引用,但是存在指向空值的指针。
全局变量
和局部变量
在内存
中是否有区别
?如果有,是什么区别?参考答案:
全局变量储存在静态数据库。
局部变量在堆栈
平衡二叉树
?参考答案:
左右子树都是平衡二叉树且左右子树的深度差值的绝对值不大于1
堆
栈
溢出一般是由什么原因导致的?参考答案:
没有回收垃圾资源
函数
不能声明为虚函数
?参考答案:
constructor
冒泡排序算法
的时间复杂度
是什么?参考答案:
O(n^2)
参考答案:
if(x > 0.0000001 && x<-0.0000001)
Internet
采用哪种网络协议
?该协议的主要层次结构
?参考答案:
tcp/ip
应用层
传输层
网络层
数据链路层
物理层
Internet
物理地址
和IP地址
转换
采用什么协议
?参考答案:
ARP(Address Resolution Protocol)
(地址解析协议)
IP地址
的编码
分为哪两部分?参考答案:
IP地址由两部分组成。网络号和主机号
局部变量
能否和全局变量
重名
?参考答案:
能。
局部会屏蔽全局。要用全局变量,需要使用“::”
局部变量可以与全局变量同名。在函数内引用这个变量时。
会用到同名的局部变量,而不会用到全局变量
定义过的
全局变量
?参考答案:
可以用引用头文件的方式。
也可以用extern关键字
全局变量
可不可以定义
在可被多个.C文件 包含的头文件中?为什么?参考答案:
可以,在不同的C文件中以static形式来声明同名全局变量。
可以在不同的C文件中声明同名的全局变量。前提是其中只有一个C文件中对此变量赋初值,此时连接不会出错。
参考答案:
和while(1)相同。
do...while
和 while...do
有什么区别?参考答案:
前一个循环一遍再判断。
后一个判断再循环
Heap
和 stack
的差别?参考答案:
Heap是堆,
stack是栈。
stack的空间是由操作系统自动分配/释放
Heap上的空间手动分配/释放。
stack空间有限
Heap是很大的自由存储区 C中的malloc函数分配的内存空间即在堆上,C++中对应的是new操作符。
程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也是在栈上进行
参考答案:
字符串str1 需要11个字节才能存放下(包含末尾的’\0’),而string只有10个字节的空间,strcpy会导致数组越界
参考答案:
字符串数组 str1不能在数组内结束;
strcpy(string,str1)调用使得从 str1[url=]内存[/url]起复制到string内存起所复制的字节数具有不确定性。
参考答案:
if (strlen(str) <=10) 应该改为 if (strlen(str) <10),因为strlen的结果未统计’\0’所占用的1个字节
参考答案:
传入中GetMemory(char *p)函数的形参为字符串指针。
在函数内部修改形参并不能真正的改变传入形参的值,执行完
char *str = NULL;
GetMemory(str);后的str仍然为NULL;
参考答案:
char p[] = “hello world”
return p;
p[]数组为函数内部的局部自动变量,在函数返回后,内存已经被释放。
这是许多程序员常犯的粗偶,其根源在于不理解变量的生存期。
参考答案:
传入GetMemory的参数为字符串指针的指针,但是在GetMemory中执行申请内存及赋值语句
p = (char *)malloc(num);
后未判断内存是否申请成功,应该加上:
if (*p == NULL){
… //进行申请内存失败处理
}
参考答案:
在执行 char *str = (char *)malloc(100);后未进行内存是否申请成功的判断;
另外,free(str)后未置str为空,导致可能变成一个-野||指针,用加上 : str == NULL;
参考答案:
BOOL型变量:if(!var)
int型变量:if(var == 0)
float型变量:
const float EPSINON = 0.0000001;
if (x>= -EPSINON) && (x<= EPSINON)
指针变量:if(var==NULL)
多继承
吗?没有的话用什么代替
?参考答案:
Cocoa中所有的类都是NSObject的子类。
多继承在这里是用 protocol委托代理来实现的。
你不用去考虑繁琐的多继承,虚基类的概念。
多态性在objective-c中通过委托来实现
私有方法
吗?私有变量
呢?参考答案:
objective-C 类里面的方法只有两种,静态方法和实例方法。
这似乎就不是完整的面向对象了,按照OO的原则就是一个对象只暴露有用的东西。
如果没有了私有方法的话,对于一些小范围的代码重用就不那么顺手。在里面声明一个私有方法。
volatile
有什么含义
?并给出三个不同例子。参考答案:
一个定义为 volatile的变量是说明变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了。精准地说就是,优化器在用到这个变量时必须每次都消息地重新读取这个变量的值。而不是使用保存在寄存器里的备份
下面是> volatile变量的几个列子
1. 并行设备的硬件寄存器(如:状态寄存器)
2. 一个中断服务子线程中会访问到非自动变量(Non-automatic variables)
3.多线程应用中被几个任务共享的变量)
const
还可以是volatile
。参考答案:
是的。
一个例子是只读的状态寄存器。
它是volatile 因为他可能被意想不到地改变。
它是const 因为程序不应该试图去修改它。
指针
可以是volatile
吗?解释为什么?参考答案:
是的。
尽管这并不是很常见。
一个例子是当一个中服务子程序 修改一个指向一个buffer的指针时。
#import
跟 #include
有什么区别,@class
代表什么?参考答案:
@class 一般用于头文件中需要声明该类的某个实例变量的时候用到。
在.m文件中还是需要使用#import
而#import 比起#include的好处就是不会引起重复包含。
内存管理方式
参考答案:
1.当你使用new,alloc和copy方法创建一个对象时,该对象的保留计数器值为1,当你不再使用该对象时,你要负责向该对象发送一条release或autorelease消息。这样,该对象将在使用寿命结束时被销毁。
2.当你通过任何其他方法获取一个对象时,则假设该对象的保留计数器为1,而且已经被设置为自动释放。你不需要执行任何操作里确保该对象被清理。
如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它。
3.如果你保留了某个对象,你需要(最终)释放或自动释放该对象。
必须保持retain方法和release方法的使用次数相等。
内存管理
autorelease
、retain
、copy
、assign
的set方法和含义。参考答案:
你 初始化(alloc/init)的独享,你需要释放(release)它。
例如:NSMutableArray *aArray = [[NSMutableArray alloc]init];后,需要[aaArray release];
你retain或者copy的,你需要释放它
例如:[aArray retain]后,需要[aaArray release];
被传递(assign)的对象,你需要retain和release。
例如:obj2 = [[obj1 someMethod]autorelease];
对象2接受对象1的一个自动释放的值。你或希望将对象2进行retain,以防止它在被使用之前就被释放掉。但是在retain后,一定要适当时候进行释放。
关于索引技术(Reference Counting)的问题,
retain值 = 索引计数(Reference Counting)。
NSArray 对象会retain(retain值加一)。任何数组中的对象。
当NSArray被卸载(dealloc)的时候,所有数组中的对象会被执行一次释放(retain值减一)。
不仅仅是NSArray,任何收集类(Collection Classes)都执行类似操作。
例如 NSDictionary,甚至UINavigationController。Alloc/init建立的对象。
索引计数为1.无需将其再次retain。
对象
是什么时候
被释放
的。参考答案:
引用计数为0时。
autorelease实际上只是把对release的调用延迟了,对于每一个autorelease,系统只是把该Object放入了当前的autoreleasepool中,当该pool被释放时,该pool中的所有的Object会被调用release。
对于每一个RunLoop,系统会隐式创建一个autoreleasepool,这样所有的releasepool会构成一个像CallStack一样的一个栈式结构,在每一个RunLoop结束时。当前栈顶的autoreleasepool会被销毁,这样这个pool里的每个Object(就是autorelease的对象)会被release。
那么什么是一个一个RunLoop呢?一个UI事件,TimerCall,delegate call,都会是一个新的RunLoop
内置的类
,如tableviewController的delegate
的属性是assign
不是retain
?参考答案:
循环引用所有的引用计数系统,都存在循环应用的问题。例如下面的引用关系:
对象a创建并引用到了对象b,
对象b创建并引用到了对象c,
对象c创建并引用到了对象b,
这时候b和c的引用计数分别是2和1.
当a不在使用b,调用release释放b的所有权,因为c还引用了b,所以b的引用计数为1,b不会释放。
b不释放,c的引用计数就是1,c也不会被释放。从此b和c永远留在内存中。
这种情况,必须打断循环引用,通过其他规则来维护引用关系。
比如,我们常见的delegate往往是assign方式的属性而不是retain方式的属性,赋值不会增加引用计数。,就是为了防止delegation两端产生不必要的循环引用。
如果一个UITableviewController对象a通过retain获取了UITableview对象b的所有权,这个UITableview对象b的delegate又是a,如果这个delegate是retain方式的,那基本上就没有机会释放这两个对象了
重用机制
是什么?参考答案:
UITableview通过重用单元格来达到节省内存的目的。:通过为每个单元格指定一个重用标识符(reuseIdentifier),即指定了单元格的种类,以及当单元格滚动出屏幕时,允许恢复单元格以便重用,对于不同种类的单元格使用不同的ID,对简单的表格,一个标识符就够了。
假如一个tableview中有10个单元格,但是屏幕上最多能显示4个,那么实际上iPhone只是为其分配了4个单元格的内存,没有分配10个,当滚动单元格时,屏幕内显示的单元格重复使用这4个内存。
ViewController
的loadView
、ViewDidLoad
、ViewDidUnLoad
分别是什么时候调用的,在自定义ViewController时这几个函数中应该做什么工作?参考答案:
loadView方法 当view需要被展示而它却是nil时,ViewController会调用该方法。不要直接调用该方法。如果手工维护views,必须重载重写该方法。
ViewDidLoad 方法 此方法只有当view从nib文件初始化的时候才被调用。重载重写该方法以进一步定制view在iPhone OS 3.0之后的版本中,还应该重载重写ViewDidUnLoad 来释放堆view的任何所有 ViewDidLoad后调用数据Model
ViewDidUnLoad方法 当系统内存吃紧的时候会调用
id
、nil
代表什么?参考答案:
id和void * 并非完全一样。
id 是指向 struct objc_objc的一个指针
这个意思基本上是说,id是一个指向任何一个继承了Object(或者NSObject)类的对象。
需要注意的是id是一个指针。所以你在使用id不需要加星号。
比如 id foo = nil 定义了一个nil指针。这个指针指向NSObject的一个任意子类。
而 id *foo = nil 则定义了一个指针,这个指针指向另一个指针。被指向的这个指针指向NSObject的一个子类。
nil和C语言的NULL相同,在objc/objc.h中定义。
nil表示一个Object-C对象,这个对象的指针指向空(没有东西就是空)。
cocoa touch
框架。参考答案:
iPhone OS应用程序的基础 Cocoa Touch框架 重用了许多Mac的成熟模式,但是它更多地专注于触摸的接口和优化。
UIKit为您提供了在iPhoneOS上实现图形,事件驱动程序的基本工具,
其建立在和macOS中一样的Foundation框架上,包括文件处理,网络,字符串操作等
有了UIKit,你可以使用iPhone OS上的独特的图形接口控件,按钮,以及全屏视图的功能。您还可以使用加速仪和多点触摸手势来控制您的应用。
Cocoa Touch 既包含只需要几行代码就可以完成全部任务的强大的Objective-C框架。也在需要是提供基础的C语言API来直接访问系统。
自动释放池
是什么,如何工作
的?参考答案:
1.自动释放池是什么
当您向一个对象发送一个autorelease消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放池。
它仍然是一个正当的对象,因此自动释放池定义的作用域内的其他对象可以向它发送消息
当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放
2.自动释放池如何工作的
1.objc是通过一种referring counting(引用计数)的方式来管理内存的,对象在开始分配内存(alloc)的时候 引用计数为一,以后每当碰到有copy,retain的时候引用计数都会加一,每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0.就会被系统销毁
2.NSAutoreleasePool 就是用来做引用计数的管理工作的。这个东西一般不用您关的
3.autorelease和release没什么区别,只是引用计数减一的时机不同而已。autorelease会在对象使用真正结束的时候才做引用计数减一
类工厂方法
是什么?参考答案:
类工厂方法 的实现是为了向客户提供方便,它们将分配和初始化合在一个步骤中,返回被创建的对象,并进行自动释放处理。这些方法的形式 +(type)className… 其中className不包含任何前缀
工厂方法 可能不仅仅为了方便使用。它们不但可以将分配和初始化结合在一起。还可以为初始化过程提供对象的分配信息
类工厂方法 的另一个目的是使类提供单例对象。虽然init…方法可以确认一个类在每次程序运行过程只存在一个实例。但是他需要首先分配一个新的实例。然后还必须释放该实例。 工厂方法则可以避免为可能没有用的对象盲目分配内存。
内存
分几个区
?各自用途?参考答案:
栈区由编译器自动分配释放存放函数的参数值,局部变量的值等。在高级语言中不需要显式的分配和释放
堆区一般由程序员手动分配释放,如果不释放可由OS释放。
数据区存储全局和静态变量1.初始化的全局和静态变量在一块区域,未初始化的放在相邻的一块区域,程序结束后由系统释放。
代码区存放函数体的二进制代码。
引用
与指针
有什么区别?参考答案:
引用就是给变量起一个别名 也就是一个变量有两个名字 它们是同一块空间
指针是分配一块内存用来保存变量的地址 间接引用变量
参考答案:
对UIApplication对象进行了初始化,这个方法除了argc和argv参数外,另外这个函数还有2个字符串参数来识别UIApplication类和UIApplication代理类。
在这里默认是2个nil。
第一个参数为nil。就是默认把UIApplication类作为缺省值进行初始化,可以在这里不填nil而是使用自己定义的UIApplication子类。
至于 第二个参数nil 就设置为nil 就把模板生成的HelloWorldAPPDelegate类作为默认值。
保存
一个变量
到本地
,列举两个简单的方法?参考答案:
直接写入 writeToFile 支持 NSString NSArray NSDictionary 实现NSCoding NSCopy协议
UIView
*view已经实例化,在view添加N个Button
的实例,并且在Button
已经用tag
区分开,如果找到其中指定的Button改变它的某个属性?参考答案:
view中有一个方法可以根据tag值。
把它上面的子视图找出来 [view subviewWithTag:];
参考答案:
可以用[委托方法来实现在A类中初始化一个成员让他指向B类就可以调用B的方法了
参考答案:
这个要根据hello的方法来定了
如果hello方法分配空间了 那个释放在调用以后 就会出错。
[obj2 dealloc];一般情况下我们不显式的调用 这个方法系统在对象引用计数为零的时候 自动调用
另外 obj2 和 obj1 指向的是 同一块空间释放一次就可以了
类方法
创建的对象
不要用release
释放?参考答案:
任何方法创建的对象对遵从内存管理原则 用alloc方法分配的对象就需要释放
如果用类方法创建对象时候,没有用到alloc,那么分配空间的问题。已经在方法内部做了处理,所以我们就不需要去释放了。
传输
一张图片
,可以用什么协议
传输?参考答案:
可以用http ftp等协议。
NSURL
初始化的NSData
对象,用哪个类
去解析
?参考答案:
这个需要根据NSDat数据是什么类型 然后可以用对应的解析工具来解析。
加号方法
与减号
的区别
?参考答案:
加号方法是类方法 可以用类名来调用
减号方法是实例方法 必须由类的实例来调用
修饰
私有变量
?参考答案:
在OC中默认变量属性都是有私有的,我们可以在property关键字来修饰,以便可以不通过接口直接访问。
最基本
的两个框架
是什么?参考答案:
Cocoa Touch框架
Foundation框架
重新加载数据
的方法是什么?参考答案:
[tableView reloadData]方法
self.name
= “object” name
= "object"的区别参考答案:
self.name 需要要合成属性然后系统会默认生成set get方法 所以在赋值是会调用set方法
name = “object” 则直接赋值
缓存池
满的问题(cell)参考答案:
iOS不存在缓存池满的情况,因为通常我们iOS中开发,对象都是在需要的时候才会创建。有种常用的说话叫做懒加载。还有在UITableview中一般只会创建刚开始出现在屏幕中的cell,之后都是从缓存池里取。不会在创建新对象。
缓存池里最多也就一两个对象,缓存池满的这种请求一般在开发java中比较常见,java中一般把最近最少使用的对象先释放。
渲染
自定义格式字符串
的UILabel。参考答案:
通过NSAttributedString类