笔试面试是程序员应聘绕不过的坎,想进大厂就一定要有知识储备量,而这个却是最佳的考察方式。笔者分享一些收集的 iOS 面试题,答案仅供参考,如有错误,还请指正。
1.Objective-C 语言的基本特点?
Objective-C 语言是 C 语言的一个超集,只是在 C 的基础之上添加了面向对象(OO)的特性;Objective-C 与 Java 语言相同都是单继承,这一点与 C++ 语言不同(多重继承),这一点可以参看之前有关讲解继承的文章;Objective-C 不支持命名空间,取而代之的是在类名之前添加前缀,以此来区分。
2.#include 与 #import 的区别,#import 与 @class 的区别?
1)#include 和 #import 效果相同,只是后者不会引起交叉编译,确保头文件只会被导入一次。
2)#import 会包含这个类的所有信息,包括实体变量和方法,而 @class 只是告诉编译器,其后面声明的名称是类的名称,至于这些类是如何定义的,暂时不用考虑,后面会再告诉你。使用 #import 编译效率高,防止相互包含的编译错误。
3. 简述类目优缺点,如果覆盖本类或者父类的方法会出现什么问题?
优点:不需要通过增加子类而增加现有类的行为(方法),且类目中的方法与原始类方法基本没有区别。
缺点:无法向类目添加实例变量。覆盖原始类方法后,原始类的方法没办法调用。
4. 简述内存管理基本原则?
如果使用 alloc、copy(mutableCopy)或者 retain 一个对象时,你就有义务向它发送一条 release 或 autorelease 消息。其他方法创建的对象,不需要由你来管理内存。
5. 什么是 ARC 技术?与 GC 是否相同?
ARC 是 Automatic Reference Counting 的简称,我们称之为自动引用计数,是 iOS5.0 之后推出的内存管理的新特性。本质上还是使用引用计数来管理对象,只是我们在编写代码时,不需要向对象发送 release 或 autorelease 方法,也不可以调用 dealloc 方法,编译器会在合适的位置自动给用户生成 release(autorelease)消息。GC 是 Garbage Collection,内存垃圾回收机制,ARC 比 GC 性能好。
6.iOS 中是否支持垃圾回收机制?
iOS 开发只支持 MRC 与 ARC,Mac 开发支持 GC 垃圾回收机制,10.8 之后弃用了 GC,推荐使用 ARC。
7. 深、浅复制的基本概念以及区别?
浅复制:只复制对象本身,不对里面的属性复制。
深复制:不仅复制对象本身,对象持有的属性对象也做复制。
8. 内存中的堆区和栈区的差别?
栈区(stack)由编译器自动分配释放,存放方法(函数)的参数值,局部变量的值等。
堆区(heap)一般由程序员分配与释放,若程序员不释放,则会内存溢出。
9. 用户自定义了一个对象,如何实现拷贝(可变和不可变拷贝)?
必须实现 copying 和 mutableCopying 协议,表示返回一个不可变和可变的对象。否则,程序将会出现异常。
- -(id)copyWithZone:(NSZone *)zone {
- Person *person = [[self Class] allocWithZone:zone];
- person->age = self.age;
- person->name = self.name;
- return person;
- }
- -(id)mutableCopyWithZone:(NSZone *)zone;
10. 定义属性时,什么时候用 assign、retain、copy 和 nonatomic?
assign:普通赋值,一般常用于基本数据类型,常见委托设计模式,以此来防止循环引用。
retain:保留计数,获得了对象的所有权。引用计数在原有基础上加 1。
copy:用来复制对象,一般字符串使用,Foundation 中的不可变对象使用,效果相当于 retain,只是引用计数加 1。
nonatomic:非原子性访问,不加同步,多线程并发访问会提高性能。
11.strong 和 weak,_unsafe_unretained 与 weak 的区别?
strong:强引用,在 ARC 中告诉编译器帮助我们自动插入 retain。
weak:弱引用,是普通赋值,相当于手动管理内存的 assign。
_unsafe_unretained:与 weak 功能一致,区别在于当指向的对象销毁后,weak 会将变量置为 nil,防止调用野指针。
12.ARC 存在内存泄露吗?
ARC 中如果内存管理不当的话,同样会存在内存泄露。例如,ARC 中也会循环引用导致内存泄露;Objective-C 对象与 CoreFoundation 类之间桥接时,管理不当也会产生内存泄露。
13. 当我们释放对象时,为什么需要调用 [super dealloc] 方法?
子类是继承自父类,那么子类中有一些实例变量(对象),是继承自父类的,因此,我们需要调用父类方法,将父类所拥有的实例进行释放。
14. 自动释放池是什么,如何工作?
自动释放池是 NSAutorelease 类的一个实例,当向一个对象发送 autorelease 消息时,该对象会自动入池,待池销毁时,将会向池中所有对象发送一条 release 消息,释放对象。
15. 为什么 delegate(代理)属性都是 assign 而不是 retain 的?
防止循环引用,以至对象无法得到正确的释放。
1.iOS 开发中数据持久性有哪几种?
plist 文件写入,对象归档,sqlite3 数据库,CoreData。
2. 什么是 KVC 和 KVO?它们之间的关系是什么?
KVC:键值编码,是一种间接访问对象实例变量的机制,该机制可以不通过存取方法就可以访问对象的实例变量。
KVO:键值观察,是一种能使得对象获取到其他对象属性变化的通知机制。
实现 KVO 键值观察模式,被观察的对象必须使用 KVC 键值编码来修改它的实例变量,这样才能被观察者观察到。因此,KVC 是 KVO 的基础或者说 KVO 的实现是建立在 KVC 的基础之上的。
3. 简述常见的设计模式?
单例模式、代理设计、观察者(通知)、工厂方法、模板方法。
4. 内存管理在 dealloc 方法中用 release 方法与 self.xx=nil 哪个好?
使用 self.xx=nil 更好,因为先调用了 release 方法,而且还将变量设置为 nil,这样就更安全的释放对象,防止野指针调用。
5. 线程与进程的区别和联系?
一般的应用程序是单个进程,也有多进程(Chrome),进程是个静态的容器,里面容纳了很多个线程,线程是一系列方法的线性执行路径。
6.Objective-C 语言的优缺点?
优点:类目、动态识别、支持 C 语言、Objective-C 与 C++ 可以混编。
缺点:不支持命名空间、不支持运算符重载、不支持多重继承。
7. 代理 delegate、通知 Notification 与 block 的使用区别?
delegate 和 block 一般是用于两个对象一对一之间的通信交互,delegate 需要定义协议方法,代理对象实现协议方法,并且需要建立代理关系才可以实现通信。block 更加简洁,不需要定义繁琐的协议方法,但是如果通信事件比较多的话,建议使用 delegate。
Notification 主要用于一对多情况下通信,而且,通信对象之间不需要建立关系,但是使用通知,代码可读性差。
8. 控制器 ViewController 的 loadView、viewDidLoad、viewWillApear 和 viewDidUnload 分别是在什么时候调用?
loadView:当控制器的根视图 view 为空,且此 view 被访问时调用。
viewDidLoad:loadView 调用之后被调用。
viewWillApear:当控制器根视图 view 被添加到父视图上时调用。
viewDidUnload:iOS6.0 之前,当内存警告时,先卸载视图,再调用
viewDidUnload 来释放内存。
9.@synthesize 和 @dynamic 的区别?
@synthesize:系统自动生成 getter 和 setter 属性声明。
@dynamic:告诉编译器,属性的获取与赋值方法由用户自己实现,不自动生成。
10. 事件响应者链的概念?
响应者链表示一系列的响应者对象。事件被交由第一响应者对象处理,如果第一响应者不处理,事件被沿着响应者链向上传递,交给下一个响应者。一般来说,第一响应者是个视图对象或者其子类对象,当其被触摸后事件交由它处理,如果它不处理,事件会被传递给它的视图控制器对象(如果存在),然后是它的父视图对象(如果存在),以此类推,直到顶层视图。接下来会沿着顶层视图到窗口(UIWindow 对象),再到程序(UIApplication 对象)。如果整个过程都没有响应这个事件,该事件被丢弃。一般情况下,在响应者链中只要有对象处理事件,事件就停止传递。但有时候可以在视图的响应方法中根据一些条件判断来决定是否需要继续传递事件。
11.C 语言中的 static 变量和 static 函数有什么作用?
1)表示变量是静态存储变量,表示变量存放在静态存储区。
2)加在函数前面的时候表示该函数是内部连接,只在本文件中有效,别的文件中不能使用该函数。
12. 指针题
- 1)int a; //一个数值。
- 2)int *a; //一个指向数值的指针。
- 3)int **a; //一个指向指针的指针。
- 4)int a[10]; //一个有10个指针的数组,该指针是指向一个整型数的。
- 5)int *a[10]; //一个有10个指针的数组,该指针是指向一个整型数的。
- 6)int (*a)[10]; //一个指向有10个整型数数组的指针。
- 7)int (*a)(int); //一个指向函数的指针,该函数有一个整型参数并返回一个整型数。
- 8)int (*a[10])(int); //一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数。
13. 写一个 NSString 类的实现?
- +(id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding {
- NSString *obj;
- obj = [self allocWithZone:NSDefaultMallocZone()];
- obj = [obj initWithCString:nullTerminatedCString encoding:encoding];
- return autorelease(obj);
- }
14.Objective-C 与 C 如何混用?Objective-C 与 C++ 如何混用?
实现文件的扩展名. m 改成. mm 即可,但 cpp 文件必须只能使用 C/C++ 代码,而且 cpp 文件 include 的头文件中,也不能出现 Objective-C 的代码,因为 cpp 只能写 C++ 的代码。
15.Objective-C 中有私有方法和私有变量吗?
使用 private 修饰的全局变量是私有的变量。
Objective-C 在语法上没有设计私有的方法,不过可以通过延展在实现文件里定义方法作为私有的方法。但不是真正意义上的私有方法,也是可以调用的,只是外部不可见而已。
1. 下面关键字 const 有什么含义?
- const int a;
- int const a;
- const int *a;
- int * const a;
前两个的作用是一样的,a 是一个常整型数。
第三个意味着 a 是一个指向常整型数的指针(即整型数是不可修改的,但指针可以)。
第四个意味着 a 是一个指向整型数的常指针(即指针指向的整型数是可以修改的,但指针是不可修改的)。
2.C 语言中 extern 的作用,extern "C" 的作用?
1)extern 可以置于变量或者函数前,以标示变量或函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。
2)C++ 语言在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而 C 语言则不会,因此会造成链接时找不到对应函数的情况,此时 C 函数就需要用 extern "C" 进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间函数名。
3.Objective-C 是如何管理内存的?
Objective-C 语言是使用引用计数来管理一个对象的生命周期,当对象被其他 "人" 使用的时候引用计数加 1,不使用时减 1,当此对象的引用计数为 0 时,则对象被系统回收。
4. 什么是动态绑定(多态)?
动态绑定是面向对象特性之一多态的体现,声明一个变量,在运行的时候可以绑定不同的对象,比如在方法的参数中声明这样一个变量 UIView *view,运行的时候,我们可以根据不同的应用场景给 view 变量传入不同的对象,可以传递一个 UIButton 对象,也可以传入 UIImageView 对象。
5. 如何理解 delegate?
delegate,又称为委托或代理,它是一种设计模式。delegate 主要用于两个对象之间的通信交互,并且解除两个通信对象的耦合性,iOS 中大量使用了 delegate 设计,主要用于视图与使用对象之间的通信交互。
6.block 与函数有何异同?block 有何优点?
1)block 类似于 C 里面的函数指针,都可以作为参数进行传递,用于回调。但是 block 的实现可以定义在方法中,函数则不可以。
2)block 语法简洁,可以在方法中定义实现,这样可以访问方法中的局部变量,使代码更加的紧凑,结构化。
7. 为什么标准头文件都有类似以下的结构?
- #ifndef __INCvxWorksh
- #define __INCvxWorksh
- #ifdef __cplusplus
- extern "C" {
- #endif
- /*...*/
- #ifdef __cplusplus
- }
- #endif
- #endif /*__INCvxWorksh*/
显然,头文件中的编译宏 "#ifndef INCvxWorksh、#define INCvxWorksh、#endif" 的作用是防止该头文件被重复引用。
8.CocoaTouch 框架?
UIKit、Foundation、CoreGraphic、CoreAnimation
1)音频和视频:Core Audio、OpenAL、Media Library、AV Foundation
2)数据管理:Core Data、SQLite
3)图形和动画:Core Animation、OpenGL ES、Quartz 2D、Core Graphic
4)用户应用:Address Book、Core Location、Map Kit、Store Kit
9. 栈结构与队列的区别?
栈(stack):限定只能在表的一端进行插入和删除操作的线性表。
队列(queue):限定只能在表的一端插入和在另一端进行删除操作的线性表。
1)队列先进先出,栈先进后出。
2)对插入和删除操作的 "限定" 不同。
3)遍历数据速度不同。队列遍历数据的速度要快得多。
10.Objective-C 中有无多重继承?如何实现多重继承?
Objective-C 是没有多重继承的。
Cocoa 中所有的类都是 NSObject 的子类,多继承在这里是用 protocol 委托代理来实现的。
面向对象语言大部分都是单继承,例如:Java、C#。
C++ 支持多继承。
11.static 全局变量与普通的全局变量的区别?局部变量呢?函数呢?
1)static 全局变量与普通全局变量的区别:static 全局变量只初始化一次,防止在其他文件单元中被引用。
2)static 局部变量与普通局部变量的区别:static 局部变量只被初始化一次,下一次依据上一次结果值。
3)static 函数与普通函数的区别:static 函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝。
12. 什么是类目与延展?
类目:为已知的类增加新的方法。
延展:通知在本类的定义里使用类目来声明私有方法。
13.Objective-C 中的协议和 Java 中的接口区别?
协议定义的方法,可以设置可选实现和必须实现。
接口则是必须全部实现。
14. 在一个对象的方法里 self.name="object" 和 name="object" 有什么不同?
前者调用的是设置器方法,后者是普通赋值。
15. 单例设计模式的实现?为什么使用单例设计?
- static File *instance = nil;
- @implementation File
- //获取单例的方法
- +(id)shareInstance {
- @synthesize (self) {
- if(instance == nil) {
- instance = [[File alloc] init];
- }
- }
- return instance;
- }
- //覆写allocWithZone、copyWithZone、retain、release和autorelease方法,目的是限制这个类只创建一个对象
为什么使用单例设计?
1)单例设计是用来限制一个类只能创建一个对象,那么此对象中的属性可以存储全局共享的数据,所有的类都可以访问、设置此单例对象中的属性数据。
2)如果一个类创建的时候非常的耗费性能,那么此类如果能满足要求,可以设置为单例节约性能。
1. 层 CALayer 和 UIView 的区别是什么?
两者最大的区别是,图层不会直接渲染到屏幕上。UIView 是 iOS 系统中界面元素的基础,所有的界面元素都是继承自它,它本身是由 CoreAnimation 来实现的,它真正绘图的部分是由一个 CALayer 类来管理的。UIView 本身更像是一个 CALayer 的管理器。一个 UIView 上可以有多个 CALayer,每个 CALayer 显示一种东西,增强 UIView 的展现能力。
2. 什么是 GCD?
GCD 是 Apple 开发的一个多核编程的较新的解决方法。在 Mac OS X 10.6 雪豹中首次推出,并引入到 iOS4.0。GCD 是一个替代诸如 NSThread 等技术的很高效和强大的技术。GCD 完全可以处理诸如数据锁定和资源泄漏等复杂的异步编程问题。
3.TCP/UDP 的区别和联系?
1)TCP 的全称为传输控制协议,这种协议可以提供面向连接的、可靠的、点到点的通信。
2)UDP 的全称为用户数据报协议,它可以提供非连接的不可靠的点到多点的通信。
3)用 TCP 还是 UDP,需要看程序注重哪一个方面,需要可靠还是快速。
4.Socket 连接和 Http 连接的区别?
Http 连接:Http 连接就是所谓的短链接,即客户端向服务器发送一次请求,服务器响应后连接即会断掉。
Socket 连接:Socket 连接就是所谓的长连接,理论上客户端和服务器端一旦建立起连接将不会主动断掉。
5. 什么是 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 状态,完成三次握手。
6.frame 和 bounds 的区别?
frame 指的是:该 view 在父 view 坐标系统中的位置大小(参照点是父视图的坐标系统)。
bounds 指的是:该 view 在本身坐标系统中的位置和大小(参照点是本身的坐标系统)。
7. 如何理解 MVC 设计模式?
MVC 是一种架构设计,M 表示数据模型,V 表示视图,C 表示控制器。
数据模型:负责存储、定义、操作数据。
视图:用来展示数据给用户,和用户进行操作交互。
控制器:它是 M 与 V 的协调者,控制器获取数据,将数据交给视图去展示。
8. 控制器的 xib 是怎么加载的?
当 UIViewController 的 loadView 被调用时,在此方法中,通过 NSBundle 加载 xib,先通过控制器的类名作为 xib 的文件名加载此 xib 文件。如果找到此 xib 文件,则加载为 view 对象作为控制器的根视图,如果没有 xib 文件,则通过 alloc 创建一个 view 对象作为根视图。
9. 控制器如何处理系统内存不足警告?
内存不足时,系统会调用控制器 didReceiveMemoryWaring 方法通知控制器内存不足。iOS6.0 与 6.0 之前的处理方式不一样。
1)iOS6.0 之前:调用 didReceiveMemoryWaring 后,将 self.view 设置为 nil,并且再调用 viewDidUnload 方法,在此方法中我们应该释放子视图。
2)iOS6.0 之后:调用 didReceiveMemoryWaring 后,不再调用 viewDidUnload 方法,则应该在 didReceiveMemoryWaring 方法中手动将 self.view=nil,并且释放子视图。
10.iOS 中对象间有哪些通信方式?
代理 delegate、block、通知和 KVO。
11.block 在内存管理上的特点?需要注意循环引用,如何解决循环引用?
1)block 中使用了局部对象,则会将此对象 retain,引用了当前对象的属性或者方法,则会将当前对象 retain。
2)解决循环引用:将当前对象赋值给一个局部变量,并且使用__block 关键字修饰该局部变量,使用该变量访问当前对象的属性和方法。
12.Objective-C 中有线程池(线程队列)吗?NSOperationQueue 是如何管理线程的?
NSOperationQueue 是 Objective-C 的线程池,线程池中可以存放多个线程。
NSOperationQueue 可以管理线程的并发数,还可以管理线程间的优先级。
13.timer 的间隔周期准吗?为什么?怎样实现一个精准的 timer?
定时器 timer 一般都是准确的,但是当主线程有些时候难免会出现堵塞情况,这样就有可能导致定时器 timer 会延迟从而不准确。我们可以开发一个多线程,在此多线程上运行定时器,这样多线程只运行定时器,不会因堵塞而导致误差。
14.Http 协议的特点?GET 与 POST 的区别?什么是 Https 协议?
1)Http 协议是短链接,都是客户端主动发送请求,服务器做出响应,服务器响应之后,连接则断开。
2)GET 请求没有请求体,POST 含有请求体,请求参数可以放入请求体中,所以,POST 可以提交大量的数据给服务器,更加安全。
3)HTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议,它是一个安全通信通道,它基于 HTTP 开发,用于在客户计算机和服务器之间交换信息。它使用安全套接字层(SSL)进行信息交换,简单来说它是 HTTP 的安全版。
15.XML 数据的解析方式各有什么不同?JSON 解析有哪些框架?
XML 数据解析有两种方式:DOM 解析和 SAX 解析。
DOM 解析:必须完成 DOM 树的构造,在处理规模较大的 XML 文档时就很耗费内存,占用资源较多。
SAX 解析:与 DOM 不同的是,SAX 是用事件驱动模型,解析 XML 文档时每遇到一个开始或者结束标签、属性或一条指令时,程序就产生一个事件来进行相应的处理。因此,SAX 相对于 DOM 来说更适合操作大的 XML 文档。
JSON 解析:现在性能比较好的主要是第三方的 JSONKit 和 iOS 自带的 JSON 解析类,自带的 JSON 解析性能是最高的,但是只能是 iOS5 之后才可以使用。
1.tableView 是如何复用的?
如果屏幕上能显示 10 个单元格,则 tableView 只会创建 11 个单元格,也就是 n+1,当滑到第 12 个单元格时就会复用第 1 个单元格对象。tableView 中有个单元格池的概念,tableView 调用协议方法获取单元格时,先从池子中查找是否有可复用的单元格,如果有则复用,如果没有则创建一个单元格对象。
2. 如何优化 tableView 的滑动速度?
1)复用单元格。
2)使用不透明的视图,单元格中尽量少使用动画。
3)图片加载使用异步加载,并且设置图片加载的并发数。
4)滑动时不加载图片,停止滑动开始加载。
5)文字、图片可直接 drawInRect 绘制。
6)如非必要,减少 reloadData 全部 cell,只 reloadRowsAtIndexPaths。
7)如果 cell 是动态行高度,计算出高度后缓存。
8)cell 高度固定的话直接用 cell.rowHeight 设置高度。
3. 谈谈对 Runloop 的理解?
Run loops 是线程相关的基础框架的一部分。一个 run loop 就是一个事件处理的循环,用来不停的调度工作以及处理输入事件。使用 run loop 的目的是让你的线程在有工作的时候忙于工作,而没有工作的时候处于休眠状态。
4. 如何调用 drawRect 方法与 layoutSubView 方法?这两个方法的作用?
通过 setNeedsLayout 方法异步调用 layoutSubView 方法。
通过 setNeedsDisplay 方法异步调用 drawRect 方法。
drawRect 方法用于绘图,layoutSubView 方法用于布局子视图。
5.UIView 与 UIViewController 的关系?
每个控制器都有一个根视图,控制器 UIViewController 用来管理此视图的加载和显示。
6.iOS 中有哪些手势?
轻击、捏合、平移、轻扫、旋转和长按。
7.Http 和 Socket 的区别?
Http 是客户端用 Http 协议进行请求,发送请求时需要封装 http 请求头,并绑定请求的数据,服务器一般有 web 服务器配合(当然也非绝对)。Http 请求方式为客户端主动发起请求,服务器才能给响应,一次请求完毕后则断开连接,以节省资源。服务器不能主动给客户端响应(除非采用 http 长连接技术)。iPhone 主要使用的类是 NSURLConnection。
Socket 是客户端跟服务器直接使用 Socket 套接字进行连接,并没有规定连接后断开,所以客户端和服务器可以保持连接通道,双方都可以主动发送数据。一般在游戏开发或股票开发,这种要求即时性很强并且保持发送数据量比较大的场合使用。主要使用的类是 CFSocketRef。
8.storyboard 有什么特点?
storyboard 是 iOS5 新增的特性,是对 xib 的升级版本,引入了一个容器用于管理多个 xib 文件,和它们之间的跳转交互。
优点:不用再为每个控制器创建 xib 文件;可以使用静态 cell,当 cell 固定且不多时,使用起来比较方便。
缺点:storyboard 单个文件,不利于团队协作开发。
9. 如何打包静态库?
新建一个 Framework&Library 的项目,编译的时候会将项目中的代码文件打包成一个. a 静态库文件。
10.APP 发布的上架流程?
1)在苹果官网的开发者中心,新建一个 APP,填写此 APP 相关的一些描述信息。
2)下载安装发布证书。
3)选择发布证书,使用 Archive 编译发布包。
4)使用 Xcode 提交发布包。
11.iOS5 有哪些新特性?
iCloud、定制 UI、storyboard、ARC、CoreImage 滤镜、新增 JSON 解析类。
12.iOS6 有哪些新特性?
UIRefreshControl 水滴效果下拉刷新、UICollectionView 控件的使用、SLComposeViewController 新浪微博控件、PassKit 中 Passbook、AutoLayout 自动布局。
13、iOS7 有哪些新特性?
系统:全新的 UI 设计与交互;Control Center 控制中心;全新的多任务 Multitasking;AirDrop 共享文件;全新的 Safari 浏览器交互式体验。
SDK:动态 UIKit,新增了 UIDynamicItem 委托,用来为 UIView 制定动态行为;新增游戏引擎 Sprite Kit Framework 框架,类似于 Cocos2D。
14.ARC 有什么特点?
ARC 是编译器特性,iOS5.0 新添加的特性,使用 ARC 开发者不需要再 retain、release、autorelease,因为编译器会在合适的地方自动插入 retain、release。
ARC 不会因少 release 而导致内存泄漏,过度使用 release 导致程序崩溃,
ARC 可以产生更简洁的代码和更健壮的应用。
15.SVN、Git 协作开发,怎么防止代码文件冲突?
防止代码冲突:不要多人同时修改同一个文件。例如,A、B 都修改同一个文件,先让 A 修改,然后提交到服务器,然后 B 更新下来,再进行修改。
服务器上的项目文件 xcodeproj,仅让一个人管理提交,其他人只更新。防止此文件产生冲突。
1. 什么是 ARC?
ARC 是 automatic reference counting 自动引用计数,在程序编译时自动加入 retain/release。在对象被创建时 retain count+1,在对象被 release 时 count-1,当 count=0 时,销毁对象。程序中加入 autoreleasepool 对象会由系统自动加上 autorelease 方法,如果该对象引用计数为 0,则销毁。那么 ARC 是为了解决 MRC 手动管理内存存在的一些而诞生的。
MRC 下内存管理的缺点:
1)释放一个堆内存时,首先要确定指向这个堆空间的指针都被 release 了。(避免提前释放)
2)释放指针指向的堆空间,首先要确定哪些指向同一个堆,这些指针只能释放一次。(避免释放多次,造成内存泄露)
3)模块化操作时,对象可能被多个模块创建和使用,不能确定最后由谁释放。
4)多线程操作时,不确定哪个线程最后使用完毕。
虽然 ARC 给我们编程带来的很多好多,但也可能出现内存泄露。如下面两种情况:
1)循环参照:A 有个属性参照 B,B 有个属性参照 A,如果都是 strong 参照的话,两个对象都无法释放。
2)死循环:如果有个 ViewController 中有无限循环,也会导致即使 ViewController 对应的 view 消失了,ViewController 也不能释放。
2.block 一般用哪个关键字修饰,为什么?
block 一般使用 copy 关键之进行修饰,block 使用 copy 是从 MRC 遗留下来的 "传统",在 MRC 中,方法内容的 block 是在栈区的,使用 copy 可以把它放到堆区。但在 ARC 中写不写都行:编译器自动对 block 进行了 copy 操作。
3. 用 @property 声明的 NSString(或 NSArray,NSDictionary)经常
使用 copy 关键字,为什么?如果改用 strong 关键字,可能造成什么问题?
用 @property 声明 NSString、NSArray、NSDictionary 经常使用 copy 关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,他们之间可能进行赋值操作,为确保对象中的字符串值不会无意间变动,应该在设置新属性值时拷贝一份。
如果我们使用是 strong, 那么这个属性就有可能指向一个可变对象, 如果这个可变对象在外部被修改了, 那么会影响该属性。
copy 此特质所表达的所属关系与 strong 类似。然而设置方法并不保留新值,而是将其 "拷贝" (copy)。 当属性类型为 NSString 时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个 NSMutableString 类的实例。这个类是 NSString 的子类,表示一种可修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份 "不可变" (immutable) 的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是 "可变的" (mutable),就应该在设置新属性值时拷贝一份。
4.runloop、autorelease pool 以及线程之间的关系?
每个线程 (包含主线程) 都有一个 Runloop。对于每一个 Runloop,系统会隐式创建一个 Autorelease pool,这样所有的 release pool 会构成一个像 callstack 一样的一个栈式结构,在每一个 Runloop 结束时,当前栈顶的 Autorelease pool 会被销毁,这样这个 pool 里的每个 Object 会被 release。
5.@property 的本质是什么?ivar、getter、setter 是如何生成并添加到这个类中的?
"属性"(property) 有两大概念:ivar(实例变量)、存取方法 (access method=getter),即 @property = ivar + getter + setter。
例如下面的这个类:
- @interface WBTextView :UITextView
- @property (nonatomic,copy)NSString *placehold;
- @property (nonatomic,copy)UIColor *placeholdColor;
- @end
类完成属性的定以后,编译器会自动编写访问这些属性的方法 (自动合成 autosynthesis),上述代码写出来的类等效与下面的代码:
- @interface WBTextView :UITextView
- - (NSString *)placehold;
- -(void)setPlacehold:(NSString *)placehold;
- -(UIColor *)placeholdColor;
- -(void)setPlaceholdColor:(UIColor *)placeholdColor;
- @end
详细介绍见:
6. 分别写一个 setter 方法用于完成
和
- @property (nonatomic,retain)NSString *name
?
- @property (nonatomic,copy) NSString *name
retain 属性的 setter 方法是保留新值并释放旧值,然后更新实例变量,令其指向新值。顺序很重要。假如还未保留新值就先把旧值释放了,而且两个值又指向同一个对象,先执行的 release 操作就可能导致系统将此对象永久回收。
- -(void)setName:(NSString *)name{
- [name retain];
- [_name release];
- _name = name;
- }
- -(void)setName:(NSString *)name{
- [_name release];
- _name = [name copy];
- }
7. 说说 assign 和 weak,_block 和 _weak 的区别?
assign 适用于基本数据类型,weak 是适用于 NSObject 对象,并且是一个弱引用。
assign 其实也可以用来修饰对象,那么为什么不用它呢?因为被 assign 修饰的对象在释放之后,指针的地址还是存在的,也就是说指针并没有被置为 nil。如果在后续内存分配中,刚巧分到了这块地址,程序就会崩溃掉。而 weak 修饰的对象在释放之后,指针地址会被置为 nil。
是用来修饰一个变量,这个变量就可以在 block 中被修改。
- _block
: 使用_block 修饰的变量在 block 代码块中会被 retain(ARC 下,MRC 下不会 retain)。
- _block
_weak: 使用_weak 修饰的变量不会在 block 代码块中被 retain。
8. 请说出下面代码是否有问题,如果有问题请修改?
- @autoreleasepool {
- for (int i=0; i<largeNumber; i++) {
- Person *per = [[Person alloc] init];
- [per autorelease];
- }
- }
内存管理的原则:如果对一个对象使用了 alloc、copy、retain,那么你必须使用相应的 release 或者 autorelease。咋一看,这道题目有 alloc,也有 autorelease,两者对应起来,应该没问题。但 autorelease 虽然会使引用计数减一,但是它并不是立即减一,它的本质功能只是把对象放到离他最近的自动释放池里。当自动释放池销毁了,才会向自动释放池中的每一个对象发送 release 消息。这道题的问题就在 autorelease。因为 largeNumber 是一个很大的数,autorelease 又不能使引用计数立即减一,所以在循环结束前会造成内存溢出的问题。
解决方案如下:
- @autoreleasepool {
- for (int i=0; i<100000; i++) {
- @autoreleasepool {
- Person *per = [[Person alloc] init];
- [per autorelease];
- }
- }
- }
在循环内部再加一个自动释放池,这样就能保证每创建一个对象就能及时释放。
9. 请问下面代码是否有问题,如有问题请修改?
- @autoreleasepool {
- NSString *str = [[NSString alloc] init];
- [str retain];
- [str retain];
- str = @"jxl";
- [str release];
- [str release];
- [str release];
- }
这道题跟第 8 题一样存在内存泄露问题,
1)内存泄露 ;
2)指向常量区的对象不能 release。
指针变量 str 原本指向一块开辟的堆区空间,但是经过重新给 str 赋值,str 的指向发生了变化,由原来指向堆区空间,到指向常量区。常量区的变量根本不需要释放,这就导致了原来开辟的堆区空间没有释放,造成内存泄露。
10. 什么情况下使用 weak 关键字,相比 assign 有什么不同?什么情况使用 weak 关键字?
1)在 ARC 中,在有可能出现循环引用的时候,往往要通过让其中一端使用 weak 来解决。比如 delegate 代理。
2)自身已经对它进行一次强引用,没有必要再强引用一次,此时也会使用 weak,自定义控件属性一般也使用 weak。
不同点:
1)weak 此特性表明该属性定义了一种 "非拥有关系"。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特性与 assign 一样,然而在属性所指的对象遭到销毁时,属性值也会清空。而 assign 的 "设置方法" 只会执行针对 "纯量类型" (scalar type,例如 CGFloat 或 NSlnteger 等) 的简单赋值操作。
2)assign 可以用非 OC 对象,而 weak 必须用于 OC 对象。
11. 内存管理语义 (assign、strong、weak 等的区别)
1)assign "设置方法" 只会执行针对 "纯量" 的简单赋值操作。
2)strong 此特性表明该属性定义了一种 "拥有关系"。为这种属性设置新值时,设置方法会先保留新值,并释放旧值,然后再将新值设置上去。
3)weak 此特性表明该属性定义了一种 "非拥有关系"。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特性同 assign 类似,然而在属性所指的对象遭到销毁时,属性值也会清空。
4)unsafe_unretained 此特性的语义和 assign 相同,但是它适用于 "对象类型",该特性表达一种 "非拥有关系",当目标对象遭到销毁时,属性值不会自动清空,这一点与 weak 有区别。
5)copy 此特性所表达的所属关系与 strong 类似。然而设置方法并不保留新值,而是将其 "拷贝"。当属性类型为 NSString * 时,经常用此特性来保护其封装性,因为传递给设置方法的新值有可能指向一个 NSMutableString 类的实例。这个类是 NSString 的子类,表示一种可以修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份 "不可变" 的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是 "可变的",就应该在设置新属性值时拷贝一份。
来源: http://www.tuicool.com/articles/JZzEVfb