一、基础面试题
1. #import 跟 #include、@class有什么区别?#import<> 跟 #import""又什么区别?
- #import 和 #include 都能完整的包含某个文件的内容,#import 能防止同一个文件被包含多次
- @class 仅仅声明一个类名,并不会包含类的完整声明;@class还能解决循环包含的问题
- #import<> 用来包含系统自带的文件,#import" " 用来包含自定义的文件
2. 属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?
- readwrite:读写特性,同时生成getter 和 setter 方法的声明和实现
- .readonly:只读特性,只生成 getter 方法的声明和实现
- assign:set 方法的实现直接赋值,用于基本数据类型
- retain:set 方法的实现是 release 旧值, retain 新值,用于 OC 对象类型
- copy : set 方法的实现是 release 旧值,copy 新值 ,用于 NSString、block 等类型
- nonatomic:非原子性,set 方法的实现不加锁,不安全,性能高(atomic 性能低,atomic 通过锁定机制来确保其原子性,但只是读/写安全,不能绝对保证线程的安全,当多线程同时访问的时候,会造成线程不安全,可以是线程锁来保证线程的安全)
3. 写一个setter方法用于完成@property (nonatomic,retain)NSString *name,写一个setter方法用于完成@property(nonatomic,copy)NSString *name.
1> @property (nonatomic, retain) NSString *name;
- (void)setName:(NSString *)name
{
if (_name != name) {
[_name release];
_name = [name retain];
}
}
2> @property(nonatomic, copy) NSString *name;
- (void)setName:(NSString *)name
{
if (_name != name) {
[_name release];
_name = [name copy];
}
}
4. 对于语句NSString*obj = [[NSData alloc] init]; ,编译时和运行时obj分别是什么类型?
- 编译时是NSString类型
- 运行时是NSData类型
5. 常见的object-c的数据类型有那些, 和C的基本数据类型有什么区别?如:NSInteger和int
- OC常见的数据类型:NSString、NSArray、NSDictionary、NSData、NSNumber等
- OC对象需要手动管理内存,C的基本数据类型不需要管理内存
- NSInteger 是基本数据类型,并不是NSNumber 的子类,当然也不是NSObject的子类
- NSInteger 是基本数据类型 Int 或者 Long 的别名(NSInteger 的定义 typedef long NSInteger),它的区别在于NSInteger 会根据系统是 32 位还是64 位来决定其本身是 int 或者是 long。
6. id 声明的变量有什么特性?
- id 声明的变量指向任何 OC 对象
7. Objective-C如何对内存管理的,说说你的看法和解决方法?
- 每个对象都有一个引用计数器,每个新对象的计数器是1,当对象的引用计数为0时,就会被销毁
- 通过 retain 可以让引用计数器 +1 ,release 可以让引用计数器 -1
- 还可以通过 autorelease 管理内存
- 如果是 ARC,编译器会自动生成管理内存的代码
注意:不管是 MRC 还是 ARC 都是在编译时完成的
8. 内存管理的几条原则时什么?按照默认法则.哪些方法生成的对象需要手动释放?在和property结合的时候怎样有效的避免内存泄露?
- 只要调用了 alloc、copy、new 方法产生的新对象,都必须在最后调用一次 release 或者是 autorelease
- 只要调用了 retain ,都必须在最后调用一次 release 或者 autorelease
- @property 如果用 copy 或者 retain ,就需要对不再使用的属性做一次 release 操作
9. 看下面的程序,三次NSLog会输出什么?为什么?
NSMutableArray* ary = [[NSMutableArray array] retain];
NSString *str = [NSString stringWithFormat:@"test"];
[str retain];
[ary addObject:str];
NSLog(@"%ld", (unsigned long)[str retainCount]);
[str retain];
[str release];
[str release];
NSLog(@"%ld", (unsigned long)[str retainCount]);
[ary removeAllObjects];
NSLog(@"%ld", (unsigned long)[str retainCount]);
结果:-1、-1、-1。-1代表没有引用计数或者引用计数非常大,因为str 是字符串,字符串在常量区,没有引用计数。引用计数为 -1,这可以理解为 NSString 实际上是一个字符串常量,是没有引用计数的(或者它的引用计数是一个很大的值(使用 %lu 可以打印查看)),对它做引用计数操作实际上没有任何影响
10. OC中创建线程的方法是什么?如果指定在主线程中执行代码?如何延时执行代码?
1> 创建线程的方法有:NSThread、CGD、NSOperation
2> 主线程中执行代码
[self performSelectorOnMainThread: withObject: waitUntilDone:];
[self performSelector: onThread:[NSThread mainThread] withObject: waitUntilDone:];
dispatch_async(dispatch_get_main_queue(), ^{
});
3> 延时操作
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
});
[self performSelector: withObject: afterDelay:];
[NSTimer scheduledTimerWithTimeInterval: target: selector: userInfo: repeats:];
11.浅拷贝与深拷贝的区别?
- 浅拷贝:对指针进行拷贝,不会产生新的对象
- 深拷贝:对指针和指针指向的内容进行拷贝,会生成新的对象
12.分类的作用是什么?实现类别和继承有什么区别?
- 分类可以在不修改原有类模型的基础上扩充方法
- 分类只能扩充方法,不能扩充成员变量;继承可以扩充方法和成员变量
- 继承会产生新的类
13. 分类和扩展的区别?
- 分类是有名称的,类扩展是没有名称的
- 分类只能扩充方法,不能扩充成员变量;类扩展可以扩充方法和成员变量
- 类扩展一般写在 .m 文件中,用来扩充私有的方法和成员变量
14.OC 中的协议和 Java 中的接口概念有什么不同?
- Java 的接口中声明的方法必须都实现
- OC 中 protocol 中声明的方法并一定要实现
15.什么是 KVC 和 KVO?
- KCV 是键值编码,可以通过一个字符串的 key(属性名)修改对象的属性的值
- KVO 是键值监听,可以监听一个对象属性值的改变
16.代理的作用是什么?
- 两个对象之间传递数据和消息
- 解耦,拆分业务逻辑
17.OC 中可修改和不可修改的类型?
- mutable 是可以变类型,比如 NSMutableArray ,可以动态添加元素
- immutable 是不可变类型,比如 NSArray, 固定的存储空间,不能添加元素
18.为什么说 OC 是动态运行时语言?
- 动态绑定:对象类型在运行时才能真正确定
- 多态性(不同对象以自己的方式去响应相同的消息的能力)
- 消息机制
19.通知和协议有什么不同之处?
- 通过 NSNotification 可以给多个对象传递数据和消息
- 通过 protocol 只能给一个对象传递数据和消息
20.什么是推送消息?
- 本地推送:程序内部弹出的通知到用户设备
- 远程推送:有推送服务器推送通知到用户设备
21.什么是多态?
- 多态:父类指针指向子类对象
22.怎么理解单例?
- 单例:保证程序运行过程中,永远只有一个对象实例
- 作用:全局共享一份资源、节省不必要的内存开销
23.怎么理解响应链?
- 事件响应链:包括点击事件、画画刷新事件等。
- UIResponder 有一个 nextResponder 属性,通过该属性可以组成一个响应者链,事件或消息在其路径上进行传递
- 如果 UIResponder 没有处理传给它的事件,会将未处理的消息转发给自己的 nextResponder
24.frame 和 bounds 有什么区别?
- frame:以父控件的左上角为坐标原点
- bounds:以控件本身的左上角为坐标原点
25.方法和选择器有什么不同?
- selector:是一个方法的名称,通过 selector 可以找到方法地址,进而调用这个方法
- method:是一个组合体,包含名字和实现
26.OC 的垃圾回收机制?
- OC 1.0没有垃圾回收
- OC 2.0有垃圾回收,但只能用在mac上
- iOS 中有 ARC机制,是编译器特性,垃圾回收是运行时特性
27.什么是NSOperation queue?
- 用来存放 NSOperation 对象的队列,可以用来异步执行一些操作
- 一般可以用在网络请求等耗时操作
28.什么是懒加载(延迟加载)?
- 延迟加载:比如控制器的 view ,在第一次用到 view 时才会调用 loadView方法进行创建
29.是否在一个控制器中嵌入两个 tableView 控制器?
- 技术角度上,一个控制器添加两个list 是没有问题的
30.一个 tableView 是否可以关联两个不同的数据源?
- 从对象属性上分析,tableView只有一个dataSource属性。当然,真要使用2个不同的数据源,还是有其他办法解决的
31.什么时候用 NSMutableArray?什么时候用NSArray?
- 当数组元素需要动态添加或者删除时用可变数组
- 当数组元素固定不变是用不可变数组
32.在应用中可以创建多少autorelease对象,是否有限制?
- 没有限制
33.如果我们不创建内存池,是否有内存池提供给我们?
- 系统会默认会不定时地创建和销毁自动释放池
34.什么时候需要在程序中创建内存池?
- 用户自己创建的数据线程,则需要创建该线程的内存池
35.什么时候内存计数会增加?
- 当做一次 retain 或者是 copy 操作的时候,内存引用计数都会增加1
36.类NSObject的那些方法经常被使用?
- NSObject是Objetive-C的基类,其由NSObject类及一系列协议构成。
- NSObject 常见的类方法有:alloc、class、 description 对象方法init、dealloc、– performSelector:withObject:afterDelay:等经常被使用
37.什么是简便构造方法?
- 简便的构造方法一般由 Cocoa Touch 框架提供,如 NSNumber 的 + numberWithBool: + numberWithChar: + numberWithDouble: + numberWithFloat: + numberWithInt:
- Foundation 下部分类均有简便构造方法,我们可以通过简便构造方法获取系统给我们创建好的对象,并且不需要手动释放。
38.如何使用Xcode设计通用应用?
- 使用MVC模式设计应用,其中Model层完成脱离界面,即在Model层,其是可运行在任何设备上,在controller层,根据iPhone与iPad(独有UISplitViewController)的不同特点选择不同的viewController对象。在View层,可根据现实要求,来设计,其中以xib文件设计时,其设置其为universal。
39.在Objetive-C什么时原子关键字?
- atomic:原子性,会对 setter 方法的实现进行加锁
40.UIView的动画效果有那些?
有很多,如
UIViewAnimationOptionCurveEaseInOut
UIViewAnimationOptionCurveEaseIn
UIViewAnimationOptionCurveEaseOut
UIViewAnimationOptionTransitionFlipFromLeft
UIViewAnimationOptionTransitionFlipFromRight
UIViewAnimationOptionTransitionCurlUp
UIViewAnimationOptionTransitionCurlDown
41.在iPhone应用中如何保存数据?
- 属性列表
- NSUserDefault
- 键值归档(NSKeyedArchiver、NSCoding)
- SQLite 数据库
- Core Data
42.什么是NSManagedObject模型?
- NSManagedObject 是 NSObject 的子类 ,也是 Core Data 的重要组成部分,它是一个通用的类,实现了Core Data 模型层所需的基本功能,用户可通过子类化 NSManagedObject,建立自己的数据模型。
43.什么是谓词?
谓词是通过NSPredicate,是通过给定的逻辑条件作为约束条件,完成对数据的筛选。
predicate = [NSPredicate predicateWithFormat:@"customerID == %d",n];
a = [customers filteredArrayUsingPredicate:predicate];
44.OC 有多继承吗?没有的话用什么代替?
- OC 是单继承,没有多继承
- 可以用分类或者是协议来代替多继承
45.OC 有私有方法吗?私有变量呢?
- OC 没有类似 @private 的修饰词来修饰方法,只要写在 .h 文件中,就是公共方法
- 如果不在 .h 文件中声明,只在 .m 文件中实现,或在 .m 文件的 Class Extension 里面声明,那么基本上和私有方法差不多,可以使用类扩展 来增加私有方法和私有变量
- 使用 @private 修饰的全局变量是私有变量
46.关键字 const 什么含义?
const int a;
int const a;
const int *a;
int const *a;
int * const a;
int const * const a;
1.前面两个的作用是一样的:a 是一个常整形数
2.第三、四个意味着 a 是一个指向常整型数的指针(整型数是不可修改的,但是指针可以)
3.第五个意思:a 是一个指向整型数的常指针(指针指向的整型数是可以修改的,但是指针是不可修改的)
4.最后一个意思:a 是一个指向常整型数的常指针(指针指向的整型数是不可修改的,同时指针也是不可修改的)
47.static 的作用?
- static 修饰的函数是一个内部函数,只能在本文件中调用,其他文件不能调用
- static 修饰的全局变量是一个内部变量,只能在本文件中使用,其他文件不能使用
- static 修饰的局部变量只会初始化一次,并且在程序退出时才会回收内存
48.线程和进程的区别?
- 一个应用程序对应一个进程,一个进程帮助程序占据一块存储空间。也有多个进程应用(如浏览器)
- 要想在进程中执行任务,进必须开启线程,一个线程代表一个任务
- 一个进程中允许开启多条线程,也就是可以同时执行多个任务
49.堆和栈的区别?
- 堆空间的内存是动态分配的,一般存放对象,并且需要手动释放内存
- 栈空间的内存由系统自动分配,一般存放局部变量等,不需要手动管理内存
50.为什么很多内置的类,如TableView 的delegate 的属性是 assign 而不是 retain?
- tableView 的代理一般都是它所属的控制器,控制器会对它内部的 view 做一次 retain 操作
- 假设 tableView 也对代理做一次 retain 操作,那么久会出现循环 retain 问题
51.定义属性,什么时候用 copy、assign、retain?
- copy:NSString、Block 等类型
- assign:非 OC 对象类型,基本数据类型(两个对象相互引用的时候,一端用 retain 一端用 assign)
- retain:OC对象类型
52.对象是什么时候被释放的?
- 每个对象都有一个引用计数器,每个新对象的引用计数器都是1,当对象引用计数器为0时,就会被销毁
53.tableView的重用机制?
- 这里只是简述:将离开屏幕的cell放到缓存池,重新拿来显示到屏幕的其他位置(其他自己详细描述)
54.ViewController 的loadView、viewDidLoad、viewDidUnload分别是什么时候调用的,在自定义ViewCointroller时在这几个函数中应该做什么工作?
- loadView:但第一次使用控制器的view时,会调用 loadView 方法创建 view。 一般在这里自定义 view
- viewDidLoad:当控制器的 view 创建完毕是回调用,也就是在 loadView 后调用。一般在这里添加子控件、初始化数据
- viewDidUnload:当控制器的 view 因为内存警告被销毁是调用。一般在这里回收跟界面相关的资源(界面都会销毁了,跟界面相关的资源肯定不要了)
55.ViewController的didReceiveMemoryWarning是在什么时候调用的?默认的操作是什么?
- 当程序接收到系统内存警告时,就有可能调用控制器的 didReceiveMemoryWarning 方法
- 它的默认做法是:当控制器的 view 不在窗口上显示时, 就会直接销毁,并且调用 viewDidUnload 方法
56.怎么理解 MVC ,在Cocoa 中MVC 是怎么实现的?
- M:model,模型 ,封装数据
- V:view,视图界面,负责展示数据
- C:Controller,控制器,负责提供数据给界面
57.self. 跟 self -> 有什么区别?
- self. 是调用 get 方法或者是 set 方法
- self 是当前本身,是一个指向当前对象的指针
- self -> 是直接访问成员变量
58.id、nil 代表什么?
- id 类型的指针可以指向任何 OC 对象
- nil 代表空值(空指针的值)
59.如何对 iOS 设备进行性能测试?
- Timer Profile
二、iOS-内存管理
1. 什么情况使用 weak 关键字,相比 assign 有什么不同?
- 什么时候使用 weak 关键字?
- 在 ARC 中,在有可能出现循环引用的时候,往往要通过让其中一端使用 weak 关键字来解决,如:delegate 代理属性
- 自身已经对它进行过一起强引用,没有必要再强引用一次,此时也会使用 weak 关键字,自定义 IBOutlet 控件属性一般也使用 weak ;当然也可以使用 strong 。
- 不同点:
- weak 此特性表明该属性定义一种 “非拥有关系”。为这种属性设置新值时,设置的方法既不保留新值,也不释放旧值。此特质同 assign 类似,然而在属性所指的对象遭到摧毁时,属性值也会清空,而 assign 的设置方法只会针对纯量类型(CGFloat、NSInteger)的简单赋值操作。
- assign 可以用 非 OC对象,为 weak 必须用于 OC 对象
2.如何让自己的类用 copy 修饰符?如何重写带 copy 关键字的 setter?
- 若想让自己自定义的对象具有copy功能,则需要实现 NSCopying 协议。如果自定的对象分为可变版本和不可变版本,则需要同时实现 NSCopying 和 NSMutableCopying 协议。
具体步骤:
声明该类遵从 NSCopying 协议,实现 NSCopying 协议。该协议只有一个方法:
- (id)copyWithZone:(NSZone *)zone;
注意:一提到让自己的类用 copy 修饰符,我们总是想覆写copy方法,其实真正需要实现的却是 “copyWithZone” 方法。
- 重写带 copy 关键字的 setter 例如:
- (void)setName:(NSString *)name {
_name = [name copy];
}
3.深拷贝与浅拷贝
- 浅拷贝只是针对指针的拷贝,拷贝后两个指针指向同一个内存空间。
- 深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。
- 但对象中存在指针成员时,除了在复制对象时需要考虑自定义拷贝构造函数,还应该考虑以下两种情况:1.当函数的参数为对象时,实参传递给形参的实际上是实参的一个拷贝对象,系统自动通过拷贝构造函数实现;2.当函数的返回值为一个对象时,该对象实际上是函数内对象的一个拷贝,用于返回函数调用处。copy 方法:如果是非可扩展类对象,则是浅拷贝。如果是可扩展类对象,则是深拷贝。mutableCopy 方法:无论是可扩展对象还是不可扩展对象,都是深拷贝。
持续更新。。。。 欢迎指导