ios面试题

1. 什么是KVC

KVC,即是指 NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性。而不是通过调用Setter、Getter方法访问。KVO 就是基于 KVC 实现的关键技术之一。

2. AFNetworking实现原理

AFNetworking3.0之前是NSURLConnection, 之后是NSURLSession, 包括一些线程的优化以及封装等

3. 浅复制和深复制的区别?

答案:浅层复制:只复制指向对象的指针,而不复制引用对象本身。

深层复制:复制引用对象本身。

意思就是说我有个A对象,复制一份后得到A_copy对象后,对于浅复制来说,A和A_copy指向的是同一个内存资源,复制的只不过是是一个指针,对象本身资源

还是只有一份,那如果我们对A_copy执行了修改操作,那么发现A引用的对象同样被修改,这其实违背了我们复制拷贝的一个思想。深复制就好理解了,内存中存在了两份独立对象本身。

用网上一哥们通俗的话将就是:

浅复制好比你和你的影子,你完蛋,你的影子也完蛋

深复制好比你和你的克隆人,你完蛋,你的克隆人还活着。

4. 传递者链 和响应者链

答案: 响应者链应该是:First Responser—-> UIView -- > The Window -- >The Application -- > App Delegate

传递者链  UIWindow -> UIView -> Next UIView ->  NextView (直到用户触碰的那个View)

5. app退到后台,有的再点开还是之前的页面,有的点开是重启,怎么设置

Appdelegate方法里 有个进入后台 和将要返回到前台的设置 在你将要从后台进入前台的方法里 去重新设置window的 rootViewcontrller

6. 重新@property (nonatomic, copy) NSString *name;  的setter方法原型;


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

UIView:属于UIkit.framework框架,负责渲染矩形区域的内容,为矩形区域添加动画,响应区域的触摸事件,布局和管 理一个或多个子视图 UIWindow:属于UIKit.framework框架,是一种特殊的UIView,通常在一个程序中只会有一个UIWindow,但可以手 动创建多个UIWindow,同时加到程序里面。UIWindow在程序中主要起到三个作用:

1、作为容器,包含app所要显示的所有视图2、传递触摸消息到程序中view和其他对象3、与UIViewController协同工作,方便完成设备方向旋转的支持

CAlayer:属于QuartzCore.framework,是用来绘制内容的,对内容进行动画处理依赖与UIView来进行显示,不能处 理用户事件。UIView和CALayer是相互依赖的,UIView依赖CALayer提供内容,CALayer依赖UIView一共容器显示 绘制内容。延伸: UIViewController:管理视图的几成熟,每个视图控制器都有一个自带的视图,并且负责这个视图相关的一切事务。方便 管理视图中的子视图,负责model与view的通信;检测设备旋转以及内存警告;是所有视图控制类的积累,定义了控制器 的基本功能。

2. 为什么很多内置类如UITableViewController的delegate属性都是assign而不是retain的?

会引起循环引用----若是retain,在alloc一次之后,若release一次,会导致内训泄漏,若release两次会导致两个 对象的dealloc嵌套执行,结果就是都没有执行成功,最后崩溃! 所有的引用计数系统,都存在循环应用的问题。例如下面的引用关系:

* 对象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方式的,那基本上就没有机会释放这两个对象了。自己在设计使用 delegate模式时,也要注意这点。

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

Notification 是观察者模式的实现,KVO是观察者模式的OB-C底层实现。NOtification 通过 Notifydcation addobserver 和 remove observer 工作。 KVO是键值监听,键值观察机制,提供了观察某一属性变化的方法 KVC是键值编码,是一种间接访问对象的属性,使用字符串来标示属性(例如:setValue:forKey:) Delegate:把某个对象要做的事情委托给别的对象去做。那么别的对象就是这个对象的代理,代替它来打理要做的 事。反映到程序中,首先要明确一个对象的委托方是哪个对象,委托所做的内容是什么。

4. 线程与进程的区别和联系?

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

5. 简述多线程的作用以及什么地方会用到多线程?OC实现多线程的方法有哪些?谈谈多线程安全问题的几种解

决方案?何为线程同步,如何实现的?分线程回调主线程方法是什么,有什么作用?

(1)、多线程的作用:可以解决负载均衡问题,充分利用cpu资源 。为了提高CPU的使用率,采用多线程的方式去同时完 成几件事情而互不干扰,

(2)、大多情况下,要用到多线程的主要是需要处理大量的IO操作时或处理的情况需要花大量的时间等等,比如:读写文 件、视频图像的采集、处理、显示、保存等。

(3)、ios有三种主要方法:1、NSThread。2、NSOperation。3、GCD。

(4)解决方案:使用锁:锁是线程编程同步工具的基础。锁可以让你很容易保护代码中一大块区域以便你可以确保代码的正 确性。使用NSLock类;使用@synchronized指令等。

(5)回到主线程的方法: dispatch_async(dispatch_get_main_queue(), ^{ });

作用:主线程是显示UI界面,子线程多数是进行数据处理


1.远程推送原理是什么??

由App向iOS设备发送一个注册通知

iOS向APNs远程推送服务器发送App的Bundle Id和设备的UDID

APNs根据设备的UDID和App的Bundle Id生成deviceToken再发回给App

App再将deviceToken发送给远程推送服务器(商家自己的服务器), 由服务器保存在数据库中

当商家想发送推送时, 在远程推送服务器中输入要发送的消息并选择发给哪些用户的deviceToken,由远程推送服务器发送给APNs

APNs根据deviceToken发送给对应的用户

2. http和scoket通信的区别?socket连接相关库,TCP,UDP的连接方法,HTTP的几种常用方式? http和scoket通信的区别: http是客户端用http协议进行请求,发送请求时候需要封装http请求头,并绑定请求的数据,服务器一般有web服务器配 合(当然也非绝对)。 http请求方式为客户端主动发起请求,服务器才能给响应,一次请求完毕后则断开连接,以节省资 源。服务器不能主动给客户端响应(除非采取http长连接技术)。iphone主要使用类是NSUrlConnection。 scoket是客户端跟服务器直接使用socket“套接字”进行连接,并没有规定连接后断开,所以客户端和服务器可以保持连 接通道,双方都可以主动发送数据。一般在游戏开发或股票开发这种要求即时性很强并且保持发送数据量比较大的场合使 用。主要使用类是CFSocketRef。 UDP:是用户数据报协议:主要用在实时性要求高以及对质量相对较弱的地方,但面对现在高质量的线路不是容易丢包除非 是一些拥塞条件下 ,如流媒体 TCP:是传输控制协议:是面连接的,那么运行环境必然要求其可靠性不可丢包有良好的拥塞控制机制如http ftp telnet 等

http的常用方式:get,post

3. #import、#include和@class有什么区别

@class一般用于头文件中需要声明该类的某个实例变量的时候用到,它只是声明了一个类名,关于这个类的内部实现都没 有告诉编译器,在m文件中还是需要使用#import。

而#import比起#include的好处就是不会引起交叉编译。

4. 举出5个以上你所熟悉的ios sdk库有哪些和第三方库有哪些?ios-sdk:Foundation.framework,CoreGraphics.framework,UIKit.framework, MediaPlayer.framework, CoreAudio.framework第三方库: 1.json编码解码;2.ASIHTTPRequest等相关协议封装;3.EGORefreshTableHeaderView下拉刷新代 码;4.AsyncImageView 异步加载图片并缓存;5.SDWebImage——简化网络图片处理

5. ViewController的 loadView, viewDidLoad,viewWillAppear,viewDidUnload,dealloc、init分别是在什么时 候调用的?在自定义ViewController的时候这几个函数里面应该做什么工作?

1、viewDidLoad 此方法只有当view从nib文件初始化的时候才被调用 2、viewDidUnload当系统内存吃紧的时候会调用该方法,在该方法中将所有IBOutlet(无论是property还是实例变量) 置 为nil(系统release view时已经将其release掉了)在该方法中释放其他与view有关的对象、其他在运行时创建(但 非系统必须)的对象、在viewDidLoad中 被创建的对象、缓存数据等 release对象后,将对象置为nil(IBOutlet只需要 将其置为nil,系统release view时已经将其release掉了) dealloc方法,viewDidUnload和dealloc方法没有关联,dealloc还是继续做它该做的事情流程应该是这样:(loadView/nib文件)来加载view到内存 -->viewDidLoad函数进一步初始化这些view -->内存不足时,调用 viewDidUnload函数释放views -->当需要使用view时有回到第一步如此循环 4、viewWillAppear方法,视图即将过渡到屏幕上时调用,(一般在返回需要刷新页面时,我都选择使用代理,所以很少用到) 5、viewWillDisappear方法,这个A->B之后,A在B之后的操作


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

编译时是NSString,运行时是NSDate

2. 描述程序启动的顺序

>1、main.m是程序的入口

>2、UIApplicationMain()创建应用程序对象,并且为此对象指定委托,检测程序的执行,同时开启事件循环,处理程序接收到的事 件

>3、UIApplicationDelegate方法的执行

>4、加载window>5、指定根视图控制器 6、在指定的试图控制器中添加控件,实现应用程序界面

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

控制好内存,不用的内存实时释放;冗余代码;用户体验度;耗时操作,开线程进行处理

4. 控制器的生命周期 以及响应链

5. 简述OC中内存管理机制?。与retain配对使用的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?readwrite,readonly,assign,retain,copy,nonatomic 、atomic、strong、weak属性的作用?并区别strong(强引用)、 weak(弱引用)?什么情况使用copy,assign,和retain?

(1)管理机制:使用了一种叫做引用计数的机制来管理内存中的对象。OC中每个对象都对应着他们自己的引用计数,引用计数可以理解为一个整数计数器,当使用alloc方法创建对象的时候,持有计数会自动设置为1。当你向一个对象发送retain消息 时,持有计数数值会增加1。相反,当你像一个对象发送release消息时,持有计数数值会减小1。当对象的持有计数变为0的时候,对象会释放自己所占用的内存。

(2)(3)小问:

retain(引用计数加1)->release(引用计数减1)

alloc(申请内存空间)->dealloc(释放内存空间)

(4)小问:

readwrite: 表示既有getter,也有setter  (默认)

readonly: 表示只有getter,没有setter

assign: 简单赋值,不更改索引计数    (默认)

retain: release旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1

copy: 其实是建立了一个相同的对象,地址不同(retain:指针拷贝  copy:内容拷贝(根据不同对象调用copy方法会产生浅拷贝, 深拷贝不同效果. 例如可变数组调用copy就是深拷贝出来一个不可变数组)

nonatomic:不考虑线程安全

atomic:线程操作安全  (默认)

线程安全情况下的setter和getter:

- (NSString*) value  {

@synchronized(self) {

return [[_value retain] autorelease];

}}

(void) setValue:(NSString*)aValue {

@synchronized(self) {

[aValue retain];

[_value release];

_value = aValue;

}  }

(5)问:

strong:(ARC下的)和(MRC)retain一样    (默认)

weak:(ARC下的)和(MRC)assign一样, weak当指向的内存释放掉后自动nil化,防止野指针

(6)问:

copy : 用于NSString、block等类型

assign:用于基本数据类型

retain:  用于OC对象类型


1. Objective-C如何对内存管理的,说说你的看法和解决方法?每个对象都有一个引用计数器,每个新对象的计数器是1,当对象的计数器减为0时,就会被销毁通过retain可以让对象的计数器+1、release可以让对象的计数器-1还可以通过autorelease pool管理内存如果用ARC,编译器会自动生成管理内存的代码

2. 内存管理的几条原则时什么?按照默认法则.哪些方法生成的对象需要手动释放?在和property结合的时候怎样有效的避免内存泄露?

只要调用了alloc、copy、new方法产生了一个新对象,都必须在最后调用一次release或者autorelease

只要调用了retain,都必须在最后调用一次release或者autorelease

@property如果用了copy或者retian,就需要对不再使用的属性做一次release操作

如果用了ARC,另外讨论

3. What is Singleton?

单例:保证程序运行过程中,永远只有一个对象实例

目的是:全局共享一份资源、节省不必要的内存开销

4. 对象是什么时候被释放的?

每个对象都有一个引用计数器,每个新对象的计数器是1,当对象的计数器减为0时,就会被销毁

5. 什么情况下会发生内存泄漏和内存溢出?

当程序在申请内存后,无法释放已申请的内存空间(例如一个对象或者变量使用完成后没有释放,这个对象一直占用着内存),一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。内存泄露会最终会导致内存溢出!

当程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个int,但给它存了long才能存下的数,那就是内存溢出。

1.自动释放池是什么,如何工作?

答:内存释放池提供了一个对象容器,每次对象发送autorelease消息时,对象的引用 计数并不真正变化,而是向内存释放池中添加一条记录,记下对象的这种要求。直到 当内存释放池发送drain或release消息时,即当池被销毁前会通知池中的所有对象,全 部发送release消息才会真正将引用计数减少。简单说内存释放池可以自动管理对象释 放问题,这些语句必须要放在下面语句之间,直到池被释放,一个对象要想纳入内存 释放池对象,必须要发送autorelease。

2. 请解释一下iOS应用的沙盒机制?

iOS中的沙盒机制(SandBox)是一种安全体系,它规定了应用程序只能在为该 应用创建的文件夹内读取文件,不可以访问其他地方的内容。所有的非代码文件都保 存在这个地方,比如图片、声音、属性列表和文本文件等。

1.每个应用程序都在自己的沙盒内

2.不能随意跨越自己的沙盒去访问别的应用程序沙盒的内容

3.应用程序向外请求或接收数据都需要经过权限认证

3 谈谈你对多线程开发的理解?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];

你可能感兴趣的:(ios面试题)