[关闭]
@Rookie 2017-08-01T14:35:12.000000Z 字数 10495 阅读 1455

iOS解答面试题

找工作


1. 简述OC中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?readwrite,readonly,assign,retain,copy,nonatomic 、atomic、strong、weak属性的作用?

1、 OC使用了一种叫做引用计数的机制来管理对象,如果对一个对象使用了alloc、[Mutable]copy,retain,那么你必须使用相应的realease或者autorelease。也可以理解为自己生成的对象,自己持有。非自己生成的对象,自己也能持有。不在需要自己持有的对象时释放。非自己持有的对象无法释放。生成并持有对象,持有对象,释放对象,废弃对象。readwrite(默认):可读可写,表示既有getter方法,也有setter方法。readonly:表示只有getter方法,没有setter方法。nonatomic:不考虑线程安全。atomic(默认):线程操作安全。strong(默认):ARC下和MRC下retain一样,weak(ARC下):和(MRC下)assign类似,区别是当weak指向的内存释放掉后自动置为nil,防止野指针。
unsafe_unretained声明一个若引用,但不会自动置为nil,可能会出现野指针。
线程安全下的setter和getter方法:

  1. - NSString *)value{
  2. @synchronizedself){
  3. return [[_value retain] autorelease];
  4. }
  5. }
  6. - (void)setValue:(NSString *)aValue{
  7. @synchronized(self){
  8. [aValue retain];
  9. [_value release];
  10. _value = aValue;
  11. }
  12. }

2. 类变量的@protected ,@private,@public,@package,声明各有什么含义?

上面的几个声明表明的时类成员的作用域,@private作用范围只能在自身类(外界既不可访问,又不能继承);@protected作用范围在自身类和子类,如果什么都不加修饰,默认是@protected(外界不可访问,但是可以继承);@public作用范围最大,可以在任何地方被访问(外界即可访问,又可以继承);@package作用范围在某个框架内

3. 线程是什么?进程是什么?二者有什么区别和联系?

线程是CPU独立运行和独立调度的基本单位(可以理解为一个进程中执行的代码片段),进程是资源分配的基本单位(进程是一块包含了某些资源的内存区域)。进程是线程的容器,真正完成代码执行的是线程,而进程则作为线程的执行环境。一个程序至少包含一个进程,一个进程至少包含一个线程,一个进程中的多个线程共享当前进程所拥有的资源。

4. 谈谈你对多线程开发的理解?ios中有几种实现多线程的方法?

好处:
1、使用线程可以把程序中占据时间长的任务放到后台去处理,如图片、视频的下载
2、发挥多核处理器的优势,并发执行让系统运行的更快、更流畅,用户体验更好
缺点:
1、大量的线程降低代码的可读性,
2、更多的线程需要更多的内存空间
3、当多个线程对同一个资源出现争夺的时候要注意线程安全的问题。
iOS有三种多线程编程的技术:
1、NSThread(两种创建方式)
[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];
NSThread *myThread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:nil];
[myThread start];
2、NSOperationQueue
NSOperationQueue *oprationQueue = [[NSOperationQueue alloc] init];
oprationQueue addOperationWithBlock:^{
//这个block语句块在子线程中执行
}
http://alloc.sinaapp.com/wp/?p=237
3、Grand Central Dispatch (GCD)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 耗时的操作
dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面
});
});
http://blog.csdn.net/totogo2010/article/details/8016129

PS:不显示的创建线程的方法:
用NSObject的类方法  performSelectorInBackground:withObject: 创建一个线程:
[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];

5. 线程同步和异步的区别?IOS中如何实现多线程的同步?

同步:一个线程要等待上一个线程执行完之后才能执行当前的线程,生活中的例子(上厕所)。
异步:同时去做两件或者多件事。比如边听歌边看报。
原子操作(atomic)、加锁(NSLock、NSRecursive、NSConditionLock)、@synchronized
GCD串行队列,GCD当中的屏障,NSOperationQueue设置最大并发数为1
参考(http://blog.csdn.net/lifengzhong/article/details/7487505

6. 获取一台设备唯一标识的方法有哪些?

MAC地址,udid,keychain,open udid,广告标识IDFA-identifierForIdentifier
参考链接< http://www.2cto.com/kf/201308/237648.html >。

7. iOS类是否可以多继承?如果没有,那可以用其他方法实现吗?简述实现过程。

不可以,可以通过消息转发、delegate和protocol和类别来实现类似多继承。

8.堆和栈的区别?

栈区(stack)--由编译器自动分配释放,存放函数的参数值、局部变量的值。
堆区(heap)--一般由程序员分配释放。
全局区(静态区)(static)--全局变量和静态变量。程序结束后由系统释放。
文字常量区--常量字符串存放在这里。程序结束后由系统释放。
程序代码区—存放函数体的二进制文件。
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢 出。
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

9. iOS本地数据存储都有哪几种方式?iOS如何实现复杂对象的存储?

1¡¢ NSKeyedArchiver(归档)采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法。
2¡¢ NSUserDefaults:用来保存应用程序设置和属性、用户保存的数据。用户再次打开程序或开机后这些数据仍然存在。NSUserDefaults可以存储的数据类型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary。
3¡¢ Write写入方式:永久保存在磁盘中。
4¡¢ SQLite(FMDB、CoreData)
NSCoding + NSKeyedArchiver实现复杂对象的存储。

10. iOS的动态性

iOS的动态性来自三个方面:动态类型、动态绑定、动态载入、SEL类型
1、动态类型<弱类型>(id):在代码的运行阶段判断代码的类型,使用id类型可以让应用在“运行时”使用任何类型来替换。动态类型让程序更加灵活,但是会使数据的统一性降低和代码的可读性。我们常用静态类型<强类型>(如NSString),使用静态类型编译器可以完全分析你的代码,这让代码的性能和可预知性更高。
2、动态绑定:让代码在运行时判断需要调用什么方法,而不是在编译时。动态类型和动态绑定使得选择哪个接收者已经调用什么方法都放到运行时去完成。
3、动态载入:应用程序可以根据需要加载可执行代码以及资源,而不是 在启动时就加载所有资源。
4、SEL类型 iOS在编译的时候会根据方法的名字(包括参数序列),生成一个用来区分这个方法的唯一的ID,这个ID是SEL类型的,SEL的本质就是类方法的编号[函数地址]。(类似C语言里面的函数指针,但是OC的类不能直接使用函数指针,这样只能做一个@selector语法来取。注意:@selector是查找当前类(含子类)的方法。)

11. 深拷贝和浅拷贝的理解?

深拷贝拷贝的是内容,浅拷贝拷贝的是指针。深拷贝和浅拷贝最大的区别就是子类对象的地址是否改变,如果子类对象的地址改变那么就是深拷贝。

12. 怎样实现一个singleton的类。

  1. static LOSingleton * shareInstance;
  2. +( LOSingleton *)sharedInstance{
  3. @synchronized(self){//这个东西其实就是 一个加锁。如果self 其他线程访问,则会阻塞。这样做一般是用来对单例 进行一个死锁的保护
  4. if (shareInstance == nil) {
  5. shareInstance = [[super allocWithZone:NULL] init];
  6. }
  7. }
  8. return shareInstance;
  9. }
  10. //第二种方式
  11. + (LOSingleton *) sharedInstance
  12. {
  13. static LOSingleton *sharedInstance = nil ;
  14. static dispatch_once_t onceToken; // 锁
  15. dispatch_once (& onceToken, ^ { // 最多调用一次
  16. sharedInstance = [[self alloc] init];
  17. });
  18. return sharedInstance;
  19. }

13. RunLoop是什么?

一个RunLoop就是一个时间处理的循环,用来不停的调度工作以及处理输入时间。使用runloop的目的是让你的线程在有工作的时候忙于工作,而没工作的时候处于休眠状态。runloop的设计是为了减少cpu无谓的空转。

14. 简述应用程序按Home键进入后台时的生命周期,以及从后台回到前台时的生命周期?

应用程序的状态:
Not running 未运行,程序没启动
Inactive 未激活,程序在前台运行,不过没接受到事件,没有事件处理的状态下通常处于这个状态。
Active 激活 程序在前台并且接收到了事件
Backgound 后台 程序在后台而且能执行代码,大多数程序进入这个状态后会在在这个状态上停留一会。
Suspended 挂起 程序在后台不能执行代码。

  1. - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  2.     //告诉代理进程启动但还没进入状态保存
  3. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  4.   // 告诉代理启动基本完成程序准备开始运行
  5. - (void)applicationWillResignActive:(UIApplication *)application
  6.   // 当应用程序将要入非活动状态执行,在此期间,应用程序不接收消息或事件,比如来电话了
  7. - (void)applicationDidBecomeActive:(UIApplication *)application 
  8.     //  当应用程序入活动状态执行,这个刚好跟上面那个方法相反
  9. - (void)applicationDidEnterBackground:(UIApplication *)application
  10.   //  当程序被推送到后台的时候调用。所以要设置后台继续运行,则在这个函数里面设置即可
  11. - (void)applicationWillEnterForeground:(UIApplication *)application
  12. //当程序从后台将要重新回到前台时候调用,这个刚好跟上面的那个方法相反。
  13. - (void)applicationWillTerminate:(UIApplication *)application
  14. //当程序将要退出是被调用,通常是用来保存数据和一些退出前的清理工作。这个需要要设置UIApplicationExitsOnSuspend的键值。
  15. - (void)applicationDidFinishLaunching:(UIApplication*)application
  16. //当程序载入后执行

15. 描述应用程序的启动顺序。

1、程序入口main函数创建UIApplication实例和UIApplication代理实例
2、在UIApplication代理实例中重写启动方法,设置第一ViewController
3、在第一ViewController中添加控件,实现对应的程序界面。
为什么很多内置类如UITableViewControl的delegate属性都是assign而不是retain?请举例说明。
防止循环引用,
Student * str=[];
Teacher *teacher=[[Teacher alloc] init];
Student * student=[[Student alloc] init];
teacher.delegate=student;
student.delegate= teacher;
在teacher中dealloc会release当前的Delegate,就会触发student对象release,继而也会导致student执行dealloc,在student中也会release自己的delegate,产生循环了。

16. 用obj-c写一个冒泡排序

  1. NSMutableArray *array = [NSMutableArray arrayWithArray:@[@"3",@"1",@"10",@"5",@"2",@"7",@"12",@"4",@"8"]];
  2. NSString *tmp;
  3. for (int i = 0; i < array.count; i ++) {
  4. for (int j = 0; j < array.count - 1 - i; j++) {
  5. if ([[array objectAtIndex:j] integerValue] > [[array objectAtIndex:j + 1] integerValue]) {
  6. tmp = [array objectAtIndex:j];
  7. [array replaceObjectAtIndex:j withObject:[array objectAtIndex:j + 1]];
  8. [array replaceObjectAtIndex:j + 1 withObject:tmp];
  9. }
  10. }
  11. }

17. 简述你对UIView、UIWindow和CALayer的理解

UIView继承于UIResponder, UIResponder继承于NSObject,UIView可以响应用户事件。CALayer继承于NSObject,所以CALayer不能响应事件。
UIView构建界面,UIView侧重于对内容的管理,CALayer侧重于对内容的绘制。
UIView是用来显示内容的,可以处理用户事件;CALayer是用来绘制内容的,对内容进行动画处理,依赖与UIView来进行显示,不能处理用户事件。

18.面向对象的三大特征,并作简单的介绍

封装、继承、多态。封装:是把客观事物封装成抽象的类,隐藏内部的实现,对外部提供接口。继承:可以使用现有类的所有功能,并且在无需重新编写原来的类的情况下对这些功能进行扩展。多态:不同的对象以自己的方式响应相同的的消息的能力叫做多态,或者说父类指针指向子类对象<如UITableView的,cellForRow方法,返回值类型是UITbaleViewCell,但是你返回的cell可以是你自定义的cell,在比如多个类里面都有同一个方法>

19. 简述NotificationCenter、KVC、KVO、Delegate?并说明它们之间的区别?

Notification:观察者模式,controller向defaultNotificationCenter添加自己的 notification,其他类注册这个notification就可以收到通知,这些类可以在收到通知时做自己的操作(多观察者默认随机顺序发通知给 观察者们,而且每个观察者都要等当前的某个观察者的操作做完才能轮到他来操作,可以用NotificationQueue的方式安排观察者的反应顺序,也 可以在添加观察者中设定反映时间,取消观察需要在viewDidUnload 跟dealloc中都要注销)。
KVC键值编码,可以直接通过字符串的名字(key)来间接访问属性的机制,而不是通过调用getter和setter方法访问。
KVO:观测指定对象的属性,当指定对象的属性更改之后会通知相应的观察者。
delegate:一对一,delegate遵循某个协议并实现协议声明的方法。

20. 分别描述类别(categories)和延展(extensions)是什么?以及两者的区别?继承和类别在实现中有何区别?为什么Category只能为对象添加方法,却不能添加成员变量?

category类目:在不知道源码的情况下为一个类扩展方法,extension:为一个类声明私有方法和变量。
继承是创建了一个新的类,而类别只是对类的一个扩展,还是之前的类。
类目的作用就是为已知的类添加方法。

21.谈谈你对MVC的理解?为什么要用MVC?在Cocoa中MVC是怎么实现的?你还熟悉其他的OC设计模式或别的设计模式吗?

MVC是Model-VIew-Controller,就是模型-视图-控制器, MVC把软件系统分为三个部分:Model,View,Controller。在cocoa中,你的程序中的每一个object(对象)都将明显地仅属于这三部分中的一个,而完全不属于另外两个。MVC可以帮助确保帮助实现程序最大程度的可重用性。各MVC元素彼此独立运作,通过分开这些元素,可以构建可维护,可独立更新的程序组建。
单例模式,delegate设计模式,target-action设计模式

22. 说说响应链

当事件发生的时候,响应链首先被发送给第一个响应者(往往是事件发生的视图,也就是用户触摸屏幕的地方)。事件将沿着响应者链一直向下传递,直到被接受并作出处理。一般来说,第一响应这是个视图对象或者其子类,当其被触摸后事件就交由它处理,如果他不处理,时间就会被传递给视图控制器对象UIViewController(如果存在),然后是它的父视图对象(superview),以此类推知道顶层视图。接下来会沿着顶层视图(top view)到窗口(UIwindow 对象) 再到程序的(UIApplication对象),如果整个过程都没有响应这个事件,则该事件被丢弃,一般情况下,在响应链中只要有对象处理事件,事件就会被传递
典型的响应路线图如:
First  Responser --> The Window -->The Applicationn --> App Delegate

23.什么是沙盒(sandbox)?沙盒包含哪些文件,描述每个文件的使用场景。如何获取这些文件的路径?如何获取应用程序包中文件的路径?

iOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映像,属性列表,文本文件等。
默认情况下,每个沙盒含有3个文件夹:Documents, Library 和 tmp。
Documents:苹果建议将程序中建立的或在程序中浏览到的文件数据保存在该目录下,iTunes备份和恢复的时候会包括此目录
Library:存储程序的默认设置或其它状态信息;
Library/Caches:存放缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出删除
tmp:提供一个即时创建临时文件的地方。
iTunes在与iPhone同步时,备份所有的Documents和Library文件。iPhone在重启时,会丢弃所有的tmp文件!

24.谈谈对性能优化的看法,如何做?

从用户体验出发:1、程序logging不要太长、2、相同数据不做重复获取、3、昂贵资源要重用(cell、sqlite、date),4、良好的编程习惯和程序设计:选择正确的集合对象和算法来进行编程、选择适合的数据存储格式(plist、SQLite)、优化SQLite查询语句5、数据资源方面的优化(缓存和异步加载)
解决方案:
• 能够发现问题
• 利用log或工具分析问题原因
• 假设问题原因
• 改进代码和设计
http://blog.csdn.net/yangxt/article/details/8173412

25. 分发平台原理

用Xcode打包IPA版本
搭建本地Web服务器
开启HTTPS
编写好对应的.plist文件
上传ipa、.plist、ca证书到Web服务器,配置好index.html
在手机上用Safari打开链接,完成下载
编写plist文件
原理是通过Safari解析链接中的”itms-services://“来实现的。
链接指向plist,plist指向IPA。

Safari会去读取install.plist中的信息,如:iOS应用的名称、版本、安装地址等.(这些信息,打包的时候就知道,如果不知道,可以把ipa解压,从解压的info.plist里面去获取,填到自己创建的install.plist里面)

我们用iphone打开浏览器,输入本地服务器的地址,然后再点击Download,哈哈,是不是已经弹出对话框询问需要安装了??
Oops, 弹出的框是"Cannot connect to *"
怎么办? 服务器没有配置https.
我们用openssl来生成

26. VPN开发原理

苹果是从iOS 8开始,才开放了新的框架 NetworkExtension ,该框架提供了配置和控制VPN支持和wifi热点相关的接口。通过该框架,我们可以很方便的实现VPN以及wifi热点相应的功能。接下来,我将介绍如何使用该框架实现一个简单的VPN功能。

IKEv2连接在用户自身网络状况经常变化的情况下仍旧能够维持加密连接,而不会出现频繁闪断、断开又重连之类的情况,能大大提高网络连接的稳定性。IKEv2能够拥有比PPTP/L2TP更加高效的网络通讯效率。IKEv2是IKE(v1)的改良版,使用了公钥证书和密码等多重认证,弥补了v1时代的安全性上的不足。比PPTP/L2TP更是可靠许多。同时IKEv2还支持硬件加速,保证了高效的传输效率。(引用自网络) ↩

怎样翻墙. 翻墙的方法

  1. GAE(GoAgent)法 如果你想动手搭建自己专属的GAE代理,图文教程在这里。
    GoAgent 的 Github 项目 (link is external) 在今天也被删除了 (2015年8月25日)。GoAgent 也是中国最流行的翻墙工具。它依赖谷歌的App Engine来建立跨越GFW的通道。 它曾托管于谷歌代码 (link is external),之后迁移到了Github。作者phuslu没有对项目删除作出任何解释,但他更改了他的账户描述为“凡事只要有开始,就必然会有结局”。

  2. VPN法 VPN在连接方式上分为PPTP VPN、L2TP/IPSec VPN、OpenVPN。扫盲贴见这里。

  3. 修改DNS/hosts法 一些靠谱的DNS:
  4. 专用软件法 -- 老牌的翻墙软件有:自由门、无界、世界通、赛风、Hotspot Shield、花园网络、Puff等。

Great Firewall of China,常用简称:GFW,中文也称中国国家防火墙[1]

虚拟专用网络(Virtual Private Network,VPN)能够在不使用专用物理连接的情况下,将一个虚拟的网络扩展到全网,因此所有连接到VPN中的设备可如同物理连接到同一私有网络中一样,发送并接收数据。如果个人设备使用VPN接入目标私有网络,这种方式也叫作远程访问VPN;当VPN用来连接两个远程网络的时候,被称为site-to-site VPN。

具体而言,Shadowsocks 将原来 ssh 创建的 Socks5 协议拆开成 Server 端和 Client 端,两个端分别安装在境外服务器和境内设备上。

+------+ +------+ +=====+ +------+ +-------+
| 设备 | <-> |Client| <-> | GFW | <-> |Server| <-> | 服务器 |
+------+ +------+ +=====+ +------+ +-------+
Client 和 Server 之间可以通过多种方式加密,并要求提供密码确保链路的安全性。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注