iOS 面试题
?
1. 写一个 NSString 类的实现
- +?(id)initWithCString:(c*****t char *)nullTerminatedCString encoding:(NSStringEncoding)encoding;?
- + (id) stringWithCString: (c*****t char*)nullTerminatedCString??
- ??????????? encoding: (NSStringEncoding)encoding?
- {?
- ? NSString? *obj;?
- ? obj = [self allocWithZone: NSDefaultMallocZone()];?
- ? obj = [obj initWithCString: nullTerminatedCString encoding: encoding];?
- ? return AUTORELEASE(obj);?
- }?
2static?keyword 的作用:?
(1)函数体内? static? 变量的作用范围为该函数体不同于? auto? 变量该变量的内存仅仅被分配一次,?
因此其值在下次调用时仍维持上次的值;?
(2)在模块内的? static? 全局变量能够被模块内所用函数訪问, 但不能被模块外其他函数訪问;?
(3)在模块内的? static? 函数仅仅可被这一模块内的其他函数调用, 这个函数的使用范围被限制在声明?
它的模块内?
(4)在类中的? static? 成员变量属于整个类所拥有, 对类的全部对象仅仅有一份拷贝?
(5)在类中的? static? 成员函数属于整个类所拥有这个函数不接收? this? 指针因而仅仅能訪问类的 static? 成员变量??
3 线程与进程的差别和联系??
进程和线程都是由操作系统所体会的程序执行的基本单元, 系统利用该基本单元实现系统对应用的并发性?
程和线程的主要差别在于它们是不同的操作系统资源管理方式进程有独立的地址空间, 一个进程崩溃后在保护模式下不会对其他进程产生影响, 而线程仅仅是一个进程中的不同执行路径线程有自己的堆栈和局部变量但线程之间没有单独的地址空间, 一个线程死掉就等于整个进程死掉, 所以多进程的程序要比多线程的程序健壮, 但在进程切换时, 耗费资源较大, 效率要差一些但对于一些要求同一时候进行而且又要共享某些变量的并发操作, 仅仅能用线程, 不能用进程
4 堆和栈的差别?
管理方式: 对于栈来讲, 是由编译器自己主动管理, 无需我们手工控制; 对于堆来说释放工作由程序猿控制 easy 产生 memory leak
?
申请大小:?
栈: 在 Windows 下, 栈是向低地址扩展的数据结构, 是一块连续的内存的区域这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的, 在? WINDOWS 下, 栈的大小是 2M(也有的说是 1M, 总之是一个编译时就确定的常数), 假设申请的空间超过栈的剩余空间时, 将提示 overflow 因此, 能从栈获得的空间较小?
堆: 堆是向高地址扩展的数据结构, 是不连续的内存区域
这是由于系统是用链表来存储的空暇内存地址的, 自然是不连续的, 而链表的遍历方向是由低地址向高地址堆的大小受限于计算机系统中有效的虚拟内存
由此可见堆获得的空间比較灵活, 也比較大?
碎片问题: 对于堆来讲, 频繁的 new/delete 势必会造成内存空间的不连续从而造成大量的碎片, 使程序效率降低对于栈来讲, 则不会存在这个问题由于栈是先进后出的队列, 他们是如此的一一对应以至于永远都不可能有一个内存块从栈中间弹出?
分配方式: 堆都是动态分配的没有静态分配的堆栈有 2 种分配方式: 静态分配和动态分配静态分配是编译器完毕的, 比方局部变量的分配动态分配由 alloca 函数进行分配, 可是栈的动态分配和堆是不同的他的动态分配是由编译器进行释放, 无需我们手工实现?
分配效率: 栈是机器系统提供的数据结构计算机会在底层对栈提供支持: 分配专门的寄存器存放栈的地址, 压栈出栈都有专门的指令执行, 这就决定了栈的效率比較高堆则是 C/C++ 函数库提供的它的机制是非常复杂的
5 什么是键 - 值, 键路径是什么?
模型的性质是通过一个简单的键 (一般是个字符串) 来指定的视图和控制器通过键来查找对应的属性值在一个给定的实体中同一个属性的全部值具有同样的数据类型
键 - 值编码技术用于进行这种查找它是一种间接訪问对象属性的机制?
键路径是一个由用点作分隔符的键组成的字符串, 用于指定一个连接在一起的对象性质序列第一个键的?
性质是由先前的性质决定的, 接下来每一个键的值也是相对于其前面的性质键路径使您能够以独立于模型?
实现的方式指定相关对象的性质通过键路径, 您能够指定对象图中的一个随意深度的路径, 使其指向相?
关对象的特定属性
?
6 目标 - 动作机制?
?
目标是动作消息的接收者一个控件或者更为常见的是它的单元, 以插座变量(參见 "插座变量" 部分)?
的形式保有其动作消息的目标
?
动作是控件发送给目标的消息, 或者从目标的角度看, 它是目标为了响应动作而实现的方法?
程序须要某些机制来进行事件和指令的翻译这个机制就是目标 - 动作机制?
7objc 的内存管理?
?
?
?? 假设您通过分配和初始化 (比方[[MyClass alloc] init]) 的方式来创建对象您就拥?
有这个对象, 须要负责该对象的释放
这个规则在使用 NSObject 的便利方法 new? 时也同样适用?
?
??? 假设您拷贝一个对象您也拥有拷贝得到的对象, 须要负责该对象的释放
?
???? 假设您保持一个对象, 您就部分拥有这个对象, 须要在不再使用时释放该对象
?
反过来?
???? 假设您从其他对象那里接收到一个对象则您不拥有该对象也不应该释放它(这个规则有少数?
的例外, 在參考文档中有显式的说明)
?
8? 自己主动释放池是什么, 怎样工作?
当您向一个对象发送一个 autorelease 消息时 Cocoa 就会将该对象的一个引用放入到最新的自己主动释放池
它仍然是个正当的对象, 因此自己主动释放池定义的作用域内的其他对象能够向它发送消息当程序执行到作用域结束的位置时自己主动释放池就会被释放, 池中的全部对象也就被释放?
1.? ojc-c? 是通过一种 "referring counting"(引用计数)的方式来管理内存的,? 对象在開始分配内存 (alloc) 的时候引用计数为一, 以后每当碰到有 copy,retain 的时候引用计数都会加一,? 每当碰到 release 和 autorelease 的时候引用计数就会减一, 假设此对象的计数变为了 0,? 就会被系统销毁.?
2. NSAutoreleasePool? 就是用来做引用计数的管理工作的, 这个东西一般不用你管的.?
3. autorelease 和 release 没什么差别, 仅仅是引用计数减一的时机不同而已, autorelease 会在对象的使用真正结束的时候才做引用计数减一.?
9 类工厂方法是什么?
类工厂方法的实现是为了向客户提供方便, 它们将分配和初始化合在一个步骤中, 返回被创建的对象, 并?
进行自己主动释放处理
这些方法的形式是 + (type)className...(当中? className 不包含不论什么前缀)?
工厂方法可能不仅仅为了方便使用它们不但能够将分配和初始化合在一起还能够为初始化过程提供对?
象的分配信息?
类工厂方法的还有一个目的是使类 (比方 NSWorkspace) 提供单件实例虽然 init... 方法能够确认一?
个类在每次程序执行过程仅仅存在一个实例, 但它须要首先分配一个生的实例, 然后还必须释放该实例?
工厂方法则能够避免为可能没实用的对象盲目分配内存
?
10 单件实例是什么?
Foundation? 和? Application Kit? 框架中的一些类仅仅同意创建单件对象, 即这些类在当前进程中的唯一实例举例来说, NSFileManager? 和 NSWorkspace? 类在使用时都是基于进程进行单件对象的实例化当向这些类请求实例的时候它们会向您传递单一实例的一个引用假设该实例还不存在则首先进行实例的分配和初始化单件对象充当控制中心的角色, 负责指引或协调类的各种服务
假设类在概念上仅仅有一个实例(比方?
NSWorkspace), 就应该产生一个单件实例, 而不是多个实例假设将来某一天可能有多个实例, 您可?
以使用单件实例机制, 而不是工厂方法或函数
11 动态绑定?
在执行时确定要调用的方法?
?
动态绑定将调用方法的确定也推迟到执行时在编译时, 方法的调用并不和代码绑定在一起, 仅仅有在消实发送出来之后, 才确定被调用的代码通过动态类型和动态绑定技术您的代码每次执行都能够得到不同的结果执行时因子负责确定消息的接收者和被调用的方法
执行时的消息分发机制为动态绑定提供支持
当您向一个动态类型确定了的对象发送消息时执行环境系统会通过接收者的 isa 指针定位对象的类并以此为起点确定被调用的方法, 方法和消息是动态绑定的而且您不必在 Objective-C? 代码中做不论什么工作, 就能够自己主动获取动态绑定的优点您在每次发送消息时,?
?
特别是当消息的接收者是动态类型已经确定的对象时动态绑定就会例行而透明地发生
12obj-c 的优缺点?
objc 优点:?
- ??1) Cateogies?
- ??2) Posing?
??3)? 动态识别?
??4)? 指标计算?
??5)弹性讯息传递?
??6)? 不是一个过度复杂的? C? 衍生语言?
??7) Objective-C? 与? C++? 可混合编程?
缺点:?
? 1)? 不支援命名空间?
? 2)?? 不支持运算符重载?
? 3)不支持多重继承?
??4)使用动态执行时类型全部的方法都是函数调用所以非常多编译时优化方法都用不到(如内联函数等), 性能低劣?
13sprintf,strcpy,memcpy 使用上有什么要注意的地方?
strcpy 是一个字符串拷贝的函数它的函数原型为 strcpy(char *dst, c*****t char *src);?
将? src 開始的一段字符串复制到 dst 開始的内存中去, 结束的标志符号为 \ 0, 由于拷贝的长度不是由我们自己控制的, 所以这个字符串拷贝非常 easy 出错
具备字符串拷贝功能的函数有 memcpy, 这是一个内存拷贝函数它的函数原型为 memcpy(char *dst, c*****t char* src, unsigned int len);?
将长度为 len 的一段内存, 从 src 复制到 dst 中去, 这个函数的长度可控可是会有内存叠加的问题?
sprintf 是格式化函数
将一段数据通过特定的格式格式化到一个字符串缓冲区中去 sprintf 格式化的函数的长度不可控, 有可能格式化后的字符串会超出缓冲区的大小, 造成溢出?
14 答案是:???
- a) int a; // An integer???
- b) int *a; // A pointer to an integer???
- c) int **a; // A pointer to a pointer to an integer???
- d) int a[10]; // An array of 10 integers???
- e) int *a[10]; // An array of 10 pointers to integers???
- f) int (*a)[10]; // A pointer to an array of 10 integers???
- g) int (*a)(int); // A pointer to a function a that? takes an integer argument and returns an integer???
- h) int (*a[10])(int); // An array of 10 pointers to functi*****? that take an integer argument and return an integer?
15.readwrite,readonlyassign,retain,copynonatomic 属性的作用?
@property 是一个属性訪问声明, 扩号内支持以下几个属性:?
1getter=getterName,setter=setterName, 设置 setter 与 getter 的方法名?
2readwrite,readonly, 设置可供訪问级别?
2,assignsetter 方法直接赋值, 不进行不论什么 retain 操作, 为了解决原类型与环循引用问题?
3,retainsetter 方法对參数进行 release 旧值再 retain 新值全部实现都是这个顺序(CC 上有相关资料)?
4,copy,setter 方法进行 Copy 操作, 与 retain 处理流程一样, 先旧值 release, 再 Copy 出新的对象, retainCount 为 1 这是为了降低对上下文的依赖而引入的机制?
copy 是在你不希望 a 和 b 共享一块内存时会使用到
a 和 b 各自有自己的内存
5,nonatomic 非原子性訪问, 不加同步, 多线程并发訪问会提高性能注意, 假设不加此属性, 则默认是两个訪问方法都为原子型事务訪问锁被加到所属对象实例级(我是这么理解的...)
atomic 和 nonatomic 用来决定编译器生成的 getter 和 setter 是否为原子操作
在多线程环境下, 原子操作是必要的, 否则有可能引起错 误的结果加了 atomicsetter 函数会变成以下这样:
16 什么时候用 delegate, 什么时候用 Notification? 答: delegate 针对 one-to-one 关系而且 reciever 能够返回值? 给 sendernotification? 能够针对 one-to-one/many/none,reciever 无法返回值给 sender. 所以, delegate 用于 sender 希望接受到? reciever 的某个功能反馈值, notification 用于通知多个 object 某个事件?
17 什么是 KVC 和 KVO? 答: KVC(Key-Value-Coding)内部的实现: 一个对象在调用 setValue 的时候 (1) 首先依据方法名找到执行方法的时候所须要的环境參数
(2)他会从自己 isa 指针结合环境參数找到详细的方法实现的接口 (3) 再直接查找得来的详细的方法实现 KVO(Key-Value- Observing): 当观察者为一个对象的属性进行了注冊, 被观察对象的 isa 指针被改动的时候 isa 指针就会指向一个中间类, 而不是真实的类所以? isa 指针事实上不须要指向实例对象真实的类
所以我们的程序最好不要依赖于 isa 指针在调用类的方法的时候, 最好要明白对象实例的类名
18ViewController? 的? loadView, viewDidLoad, viewDidUnload? 各自是在什么时候调用的? 在自己定义 ViewController 的时候这几个函数里面应该做什么工作? 答: viewDidLoad 在 view? 从 nib 文件初始化时调用 loadView 在 controller 的 view 为 nil 时调用
此方法在编程实现 view 时调用, view? 控制器默认会注冊 memory warning notification, 当 view controller 的不论什么 view? 没实用的时候, viewDidUnload 会被调用, 在这里实现将 retain? 的 view release, 假设是 retain 的 IBOutlet view? 属性则不要在这里 release,IBOutlet 会负责 release?
19
"NSMutableString *" 这个数据类型则是代表 "NSMutableString" 对象本身这两者是有差别的
而 NSString 仅仅是对象的指针而已
面向过程就是分析出解决这个问题所须要的步骤, 然后用函数把这些步骤一步一步实现, 使用的时候一个一个依次调用就能够了?
面向对象是把构成问题事务分解成各个对象建立对象的目的不是为了完毕一个步骤, 而是为了描叙某个事物在整个解决这个问题的步骤中的行为
20 类别的作用
类别主要有 3 个作用:
(1)将类的实现分散到多个不同文件或多个不同框架中
(2)创建对私有方法的前向引用
(3)向对象加入非正式协议
类别的局限性
有双方面局限性:
(1)无法向类中加入新的实例变量, 类别没有位置容纳实例变量
(2)名称冲突, 即当类别中的方法与原始类方法名称冲突时, 类别具有更高的优先级类别方法将全然代替初始方法从而无法再使用初始方法
无法加入实例变量的局限能够使用字典对象解决
21keywordvolatile 有什么含意? 并给出三个不同的样例:
一个定义为 volatile 的变量是说这变量可能会被意想不到地改变, 这样, 编译器就不会去假设这个变量的值了精确地说就是, 优化器在用到
这个变量时必须每次都小心地又一次读取这个变量的值, 而不是使用保存在寄存器里的备份以下是 volatile 变量的几个样例:
?? 并行设备的硬件寄存器(如: 状态寄存器)
?? 一个中断服务子程序中会訪问到的非自己主动变量(Non-automatic variables)
?? 多线程应用中被几个任务共享的变量
?
?? 一个參数既能够是 const 还能够是 volatile 吗? 解释为什么
?? 一个指针能够是 volatile? 吗? 解释为什么
?
以下是答案:
?? 是的一个样例是仅仅读的状态寄存器
它是 volatile 由于它可能被意想不到地改变它是 const 由于程序不应该试图去改动它
?? 是的虽然这并不非经常见一个样例是当一个中服务子程序修该一个指向一个 buffer 的指针时
22@synthesize? 是系统自己主动生成 getter 和 setter 属性声明
@dynamic? 是开发者自已提供对应的属性声明
@dynamic? 意思是由开发者提供对应的代码: 对于仅仅读属性须要提供? setter, 对于读写属性须要提供? setter? 和 getter@synthesize? 意思是, 除非开发者已经做了, 否则由编译器生成对应的代码, 以满足属性声明
? 查阅了一些资料确定 @dynamic 的意思是告诉编译器, 属性的获取与赋值方法由用户自己实现,? 不自己主动生成
23Difference between shallow copy and deep copy?
浅复制和深复制的差别?
答案: 浅层复制: 仅仅复制指向对象的指针而不复制引用对象本身
深层复制: 复制引用对象本身
意思就是说我有个 A 对象, 复制一份后得到 A_copy 对象后, 对于浅复制来说, A 和 A_copy 指向的是同一个内存资源, 复制的仅仅只是是是一个指针, 对象本身资源
还是仅仅有一份, 那假设我们对 A_copy 执行了改动操作, 那么发现 A 引用的对象同样被改动, 这事实上违背了我们复制拷贝的一个思想深复制就好理解了, 内存中存在了
两份独立对象本身
用网上一哥们通俗的话将就是:
浅复制好比你和你的影子, 你完蛋, 你的影子也完蛋
深复制好比你和你的克隆人, 你完蛋, 你的克隆人还活着
- 24What is advantage of categories?
- What is difference between implementing a category and inheritance?
类别的作用? 继承和类别在实现中有何差别?
答案: category? 能够在不获悉, 不改变原来代码的情况下往里面加入新的方法仅仅能加入, 不能删除改动
而且假设类别和原来类中的方法产生名称冲突则类别将覆盖原来的方法, 由于类别具有更高的优先级
类别主要有 3 个作用:
(1)将类的实现分散到多个不同文件或多个不同框架中
(2)创建对私有方法的前向引用
(3)向对象加入非正式协议
? 继承能够添加, 改动或者删除方法而且能够添加属性
25.Difference between categories and extensions?
类别和类扩展的差别
? 答案: category 和 extensions 的不同在于? 后者能够加入属性另外后者加入的方法是必须要实现的
extensions 能够觉得是一个私有的 Category
26.Difference between protocol in objective c and interfaces in java?
oc 中的协议和 java 中的接口概念有何不同?
答案: OC 中的代理有 2 层含义, 官方定义为? formal 和 informal protocol 前者和 Java 接口一样
informal protocol 中的方法属于设计模式考虑范畴, 不是必须实现的可是假设有实现就会改变类的属性
事实上关于正式协议, 类别和非正式协议我非常早前学习的时候大致看过, 也写在了学习教程里
非正式协议概念事实上就是类别的还有一种表达方式这里有一些你可能希望实现的方法, 你能够使用他们更好的完毕工作
这个意思是这些是可选的比方我门要一个更好的方法, 我们就会申明一个这种类别去实现
然后你在后期能够直接使用这些更好的方法
这么看, 总觉得类别这玩意儿有点像协议的可选协议 "
如今来看事实上 protocal 已经開始对两者都统一和规范起来操作, 由于资料中说非正式协议使用 interface 修饰,
如今我们看到协议中两个修饰词: 必须实现 (@requied) 和可选实现(@optional)
26What are KVO and KVC?
答案: kvc: 键?-? 值编码是一种间接訪问对象的属性使用字符串来标识属性, 而不是通过调用存取方法, 直接或通过实例变量訪问的机制
非常多情况下能够简化程序代码 apple 文档事实上给了一个非常好的样例
kvo: 键值观察机制, 他提供了观察某一属性变化的方法, 极大的简化了代码
详细用看到嗯哼用到过的一个地方是对于按钮点击变化状态的的监控
比方我自己定义的一个 button
- [cpp]?
- [self addObserver:self forKeyPath:@"highlighted" options:0 context:nil];?
- #pragma mark KVO?
- - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context?
- {?
- ??? if ([keyPath isEqualToString:@"highlighted"] ) {?
- ??????? [self setNeedsDisplay];?
- ??? }?
- }?
对于系统是依据 keypath 去取的到对应的值发生改变理论上来说是和 kvc 机制的道理是一样的
对于 kvc 机制怎样通过 key 寻找到 value:
当通过 KVC 调用对象时, 比方:[self valueForKey:@someKey]时程序会自己主动试图通过几种不同的方式解析这个调用首先查找对象是否带有? someKey? 这种方法, 假设没找到, 会继续查找对象是否带有 someKey 这个实例变量 (iVar) 假设还没有找到, 程序会继续试图调用?-(id) valueForUndefinedKey: 这种方法
假设这种方法还是没有被实现的话, 程序会抛出一个 NSUndefinedKeyException 异常错误
(cocoachina.com 注: Key-Value Coding 查找方法的时候, 不仅仅会查找 someKey 这种方法, 还会查找 getsomeKey 这种方法, 前面加一个 get 或者_someKey 以及_getsomeKey 这几种形式
同一时候查找实例变量的时候也会不仅仅查找 someKey 这个变量, 也会查找_someKey 这个变量是否存在
)
设计 valueForUndefinedKey: 方法的主要目的是当你使用 -(id)valueForKey 方法从对象中请求值时, 对象能够在发生错误前有最后的机会响应这个请求这样做有非常多优点以下的两个样例说明了这样做的优点
来至 cocoa, 这个说法应该挺有道理
由于我们知道 button 却是存在一个 highlighted 实例变量. 因此为何上面我们仅仅是 add 一个相关的 keypath 即可了,
27What is purpose of delegates?
代理的作用?
答案: 代理的目的是改变或传递控制链
同意一个类在某些特定时刻通知到其他类而不须要获取到那些类的指针能够降低框架复杂度
另外一点, 代理能够理解为 java 中的回调监听机制的一种相似
28What are mutable and immutable types in Objective C?
oc 中可改动和不能够改动类型
答案: 可改动不可改动的集合类
这个我个人简单理解就是可动态加入改动和不可动态加入改动一样
比方 NSArray 和 NSMutableArray 前者在初始化后的内存控件就是固定不可变的, 后者能够加入等, 能够动态申请新的内存空间
29When we call objective c is runtime language what does it mean?
我们说的 oc 是动态执行时语言是什么意思?
答案: 多态主要是将数据类型的确定由编译时推迟到了执行时
这个问题事实上浅涉及到两个概念, 执行时和多态
简单来说, 执行时机制使我们直到执行时才去决定一个对象的类别, 以及调用该类别对象指定方法
多态: 不同对象以自己的方式响应同样的消息的能力叫做多态意思就是假设生物类 (life) 都用有一个同样的方法 - eat;
那人类属于生物, 猪也属于生物, 都继承了 life 后实现各自的 eat, 可是调用是我们仅仅需调用各自的 eat 方法
也就是不同的对象以自己的方式响应了同样的消息(响应了 eat 这个选择器)
因此也能够说, 执行时机制是多态的基础?~~~
30what is difference between NSNotification and protocol?
通知和协议的不同之处?
答案: 协议有控制链 (has-a) 的关系通知没有
首先我一開始也不太明白, 什么叫控制链 (专业术语了~) 可是简单分析下通知和代理的行为模式我们大致能够有自己的理解
简单来说, 通知的话它能够一对多, 一条消息能够发送给多个消息接受者
代理按我们的理解到不是直接说不能一对多, 比方我们知道的明星经济代理人, 非常多时候一个经济人负责好几个明星的事务
仅仅是对于不同明星间, 代理的事物对象都是不一样的, 一一对应, 不可能说明天要处理 A 明星要一个公布会, 代理人发出处理公布会的消息后, 别称 B 的
公布会了
可是通知就不一样他仅仅关心发出通知, 而不关心多少接收到感兴趣要处理
因此控制链(has-a 从英语单词大致能够看出单一拥有和可控制的对应关系
来源: http://www.bubuko.com/infodetail-2498199.html