【面试】iOS 开发面试题(一)

    1. #import 跟#include 又什么区别,@class呢, #import<> 跟 #import””又什么区别?
  答:#import是Objective-C导入头文件的关键字,#include是C/C++导入头文件的关键字,使用#import头文件会自动只导入一次,不会重复导入,至关于#include和#pragma once;@class告诉编译器某个类的声明,当执行时,才去查看类的实现文件,能够解决头文件的相互包含;#import<>用来包含系统的头文件,#import””用来包含用户头文件。


  2. 属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么做用,在那种状况下用?
  1. readwrite 是可读可写特性;须要生成getter方法和setter方法时
  2. readonly 是只读特性 只会生成getter方法 不会生成setter方法 ;不但愿属性在类外改变
  3. assign 是赋值特性,setter方法将传入参数赋值给实例变量;仅设置变量时;
  4. retain 表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1;
  5. copy 表示赋值特性,setter方法将传入对象复制一份;须要彻底一份新的变量时。
  6. nonatomic 非原子操做,决定编译器生成的setter getter是不是原子操做,atomic表示多线程安全,通常使用nonatomic 
java



       3. Object-c的类能够多重继承么?能够实现多个接口么?Category是什么?重写一个类的方式用继承好仍是分类好?为何?数组

  答: Object-c的类不能够多重继承;能够实现多个接口,经过实现多个接口能够完成C++的多重继承;Category是类别,通常状况用分类好,用Category去重写类的方法,仅对本Category有效,不会影响到其余类与原有类的关系。



  4.写一个setter方法用于完成@property (nonatomic,retain)NSString *name,写一个setter方法用于完成@property(nonatomic,copy)NSString *name
  - (void) setName:(NSString*) str
  {
  [str retain];
  [name release];
  name = str;
  }
  - (void)setName:(NSString *)str
  {
  id t = [str copy];
  [name release];
  name = t;
  }


  5.对于语句NSString*obj = [[NSData alloc] init]; obj在编译时和运行时分别时什么类型的对象?
  编译时是NSString的类型;运行时是NSData类型的对象


  6.常见的object-c的数据类型有那些, 和C的基本数据类型有什么区别?如:NSInteger和int
  object-c的数据类型有NSString,NSNumber,NSArray,NSMutableArray,NSData等等,这些都是class,建立后即是对象,而C语言的基本数据类型int,只是必定字节的内存空间,用于存放数值;NSInteger是基本数据类型,并非NSNumber的子类,固然也不是NSObject的子类。NSInteger是基本数据类型Int或者Long的别名(NSInteger的定义typedef long NSInteger),它的区别在于,NSInteger会根据系统是32位仍是64位来决定是自己是int仍是Long。


  7.id 声明的对象有什么特性?
  Id 声明的对象具备运行时的特性,便可以指向任意类型的objcetive-c的对象;


  8.Objective-C如何对内存管理的,说说你的见解和解决方法?
  Objective-C的内存管理主要有三种方式ARC(自动内存计数)、手动内存计数、内存池。
  1. (Garbage Collection)自动内存计数:这种方式和java相似,在你的程序的执行过程当中。始终有一个高人在背后准确地帮你收拾垃圾,你不用考虑它何时开始工做,怎样工做。你只须要明白,我申请了一段内存空间,当我再也不使用从而这段内存成为垃圾的时候,我就完全的把它忘记掉,反正那个高人会帮我收拾垃圾。遗憾的是,那个高人须要消耗必定的资源,在携带设备里面,资源是紧俏商品因此iPhone不支持这个功能。因此“Garbage Collection”不是本入门指南的范围,对“Garbage Collection”内部机制感兴趣的同窗能够参考一些其余的资料,不过说老实话“Garbage Collection”不大适合适初学者研究。
  解决: 经过alloc – initial方式建立的, 建立后引用计数+1, 此后每retain一次引用计数+1, 那么在程序中作相应次数的release就行了.
  2. (Reference Counted)手动内存计数:就是说,从一段内存被申请以后,就存在一个变量用于保存这段内存被使用的次数,咱们暂时把它称为计数器,当计数器变为0的时候,那么就是释放这段内存的时候。好比说,当在程序A里面一段内存被成功申请完成以后,那么这个计数器就从0变成1(咱们把这个过程叫作alloc),而后程序B也须要使用这个内存,那么计数器就从1变成了2(咱们把这个过程叫作retain)。紧接着程序A再也不须要这段内存了,那么程序A就把这个计数器减1(咱们把这个过程叫作release);程序B也再也不须要这段内存的时候,那么也把计数器减1(这个过程仍是release)。当系统(也就是Foundation)发现这个计数器变成了0,那么就会调用内存回收程序把这段内存回收(咱们把这个过程叫作dealloc)。顺便提一句,若是没有Foundation,那么维护计数器,释放内存等等工做须要你手工来完成。
  解决:通常是由类的静态方法建立的, 函数名中不会出现alloc或init字样, 如[NSString string]和[NSArray arrayWithObject:], 建立后引用计数+0, 在函数出栈后释放, 即至关于一个栈上的局部变量. 固然也能够经过retain延长对象的生存期.
  3. (NSAutoRealeasePool)内存池:能够经过建立和释放内存池控制内存申请和回收的时机.
  解决:是由autorelease加入系统内存池, 内存池是能够嵌套的, 每一个内存池都须要有一个建立释放对, 就像main函数中写的同样. 使用也很简单, 好比[[[NSString alloc]initialWithFormat:@”Hey you!”] autorelease], 即将一个NSString对象加入到最内层的系统内存池, 当咱们释放这个内存池时, 其中的对象都会被释放.


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


  10. 看下面的程序,第一个NSLog会输出什么?这时str的retainCount是多少?第二个和第三个呢? 为何?
  =======================================================
  NSMutableArray* ary = [[NSMutableArray array] retain];
  NSString *str = [NSString stringWithFormat:@"test"];
  [str retain];
  [aryaddObject:str];
  NSLog(@”%@%d”,str,[str retainCount]);
  [strretain];
  [strrelease];
  [strrelease];
  NSLog(@”%@%d”,str,[str retainCount]);
  [aryremoveAllObjects];
  NSLog(@”%@%d”,str,[str retainCount]);
  =======================================================
  str的retainCount建立+1,retain+1,加入数组自动+1 3
  retain+1,release-1,release-1 2
  数组删除全部对象,全部数组内的对象自动-1 1


  11. 内存管理的几条原则时什么?按照默认法则.那些关键字生成的对象
  须要手动释放?在和property结合的时候怎样有效的避免内存泄露?
  谁申请,谁释放
  遵循Cocoa Touch的使用原则;
  内存管理主要要避免“过早释放”和“内存泄漏”,对于“过早释放”须要注意@property设置特性时,必定要用对特性关键字,对于“内存泄漏”,必定要申请了要负责释放,要细心。
  关键字alloc 或new 生成的对象须要手动释放;
  设置正确的property属性,对于retain须要在合适的地方释放,


  12.如何对iOS设备进行性能测试?
  Profile-> Instruments ->Time Profiler


  13. Object C中建立线程的方法是什么?若是在主线程中执行代码,方法是什么?若是想延时执行代码、方法又是什么?
  线程建立有三种方法:使用NSThread建立、使用GCD的dispatch、使用子类化的NSOperation,而后将其加入NSOperationQueue;在主线程执行代码,方法是performSelectorOnMainThread,若是想延时执行代码能够用performSelector:onThread:withObject:waitUntilDone:


  14.描述一下iOS SDK中如何实现MVC的开发模式

        MVC是Model-VIew-Controller,就是模型-视图-控制器, MVC把软件系统分为三个部分:Model,View,Controller。在cocoa中,你的程序中的每个object(对象)都将明显地仅属于这三部分中的一个,而彻底不属于另外两个。model数据模型,view是对这些数据的显示,viewcontroller就是把model拿到view中显示,起到model和view之间桥梁的做用。MVC能够帮助确保帮助实现程序最大程度的可重用性。各MVC元素彼此独立运做,经过分开这些元素,能够构建可维护,可独立更新的程序组建, 提升代码的重用性.安全



  15 浅复制和深复制的区别?
  答案:浅层复制:只复制指向对象的指针,而不复制引用对象自己。
  深层复制:复制引用对象自己。
  意思就是说我有个A对象,复制一份后获得A_copy对象后,对于浅复制来讲,A和A_copy指向的是同一个内存资源,复制的只不过是是一个指针,对象自己资源
  仍是只有一份,那若是咱们对A_copy执行了修改操做,那么发现A引用的对象一样被修改,这其实违背了咱们复制拷贝的一个思想。深复制就好理解了,内存中存在了
  两份独立对象自己。


  16. 类别的做用?继承和类别在实现中有何区别?
  答案:category 能够在不获悉,不改变原来代码的状况下往里面添加新的方法,只能添加,不能删除修改。
  而且若是类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,由于类别具备更高的优先级。
  类别主要有3个做用:
  (1)将类的实现分散到多个不一样文件或多个不一样框架中。
  (2)建立对私有方法的前向引用。
  (3)向对象添加非正式协议。
  继承能够增长,修改或者删除方法,而且能够增长属性。


  17. 类别和类扩展的区别。
  答案:category和extensions的不一样在于 后者能够添加属性。另外后者添加的方法是必需要实现的。
  extensions能够认为是一个私有的Category。


  18. 什么是KVO和KVC?
  答案:kvc:键 – 值编码是一种间接访问对象的属性使用字符串来标识属性,而不是经过调用存取方法,直接或经过实例变量访问的机制。
  不少状况下能够简化程序代码。apple文档其实给了一个很好的例子。
  kvo:键值观察机制,他提供了观察某一属性变化的方法,极大的简化了代码。
  具体用看到嗯哼用到过的一个地方是对于按钮点击变化状态的的监控。
  好比我自定义的一个button
  [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就好了,
  能够按照kvc查找的逻辑理解,就说的过去了。


  19. 代理的做用?
  答案:代理的目的是改变或传递控制链。容许一个类在某些特定时刻通知到其余类,而不须要获取到那些类的指针。能够减小框架复杂度。
  另一点,代理能够理解为java中的回调监听机制的一种相似。


  20. oc中可修改和不能够修改类型。
  答案:可修改不可修改的集合类。这个我我的简单理解就是可动态添加修改和不可动态添加修改同样。
  好比NSArray和NSMutableArray。前者在初始化后的内存控件就是固定不可变的,后者能够添加等,能够动态申请新的内存空间。