收集一些 iOS 面试的题目
收集了一些网上比较常见的面试题
问题1
在UITableViewCell 构造方法中
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
reuseIdentitfier
是做什么的?
指明一个cell可以重用。比如,cell结构看起来一样,但是内容不太一样。UITableView会使用reuseIdentifier
在内存中维持一个内部的缓存,并且在dequeueReusableCellWithIdentifier:
方法被调用时,重用cell。通过重用机制,table的性能会更好,因为不用重新创建cell。
问题2
Atomic 和 Nonatomic的synthesized变量的区别?
这两个属性决定了变量的getter/setter是否可以原子性的去读写变量。
- atomic:对变量的读取时同步的。就是说一个get操作保证会返回一个有效的值,但这样会影响性你能。
- nonatomic:异步读取。效率更好,但是在某些情况下会造成返回值为nil(在多个线程同事对变量进行读写操作时)
在平常的开发中,一般使用nonatomic的情况比较多,因为效率好,而很时候线程安全不用太多考虑。
问题3
copy和retain的区别
retain一个对象,会使其引用计数器+1。这意味着这个对象会一直保存在内存中,直到其引用计数减为0。引用这个对象的其他对象/变量会共享这个变量。也就是说一个改了,另一个和跟着变。
Copy意味着这个对象再被引用时将被克隆一份,而不与其他引用它的对象共享。
问题4
OC中方法swizzling 是怎么用的,为什么用?
Swizzling允许一个当前存在的selector的实现在运行时的class dispatch table中变为另一个不同的实现。swizzling允许在原方法执行前或执行后 运行一段代码。比如追踪时间方法中加入log:
#import "UIViewController+Log.h"
@implementation UIViewController (Log)
+ (void)load {
static dispatch_once_t once_token;
dispatch_once(&once_token, ^{
SEL viewWillAppearSelector = @selector(viewDidAppear:);
SEL viewWillAppearLoggerSelector = @selector(log_viewDidAppear:);
Method originalMethod = class_getInstanceMethod(self, viewWillAppearSelector);
Method extendedMethod = class_getInstanceMethod(self, viewWillAppearLoggerSelector);
method_exchangeImplementations(originalMethod, extendedMethod);
});
}
- (void) log_viewDidAppear:(BOOL)animated {
[self log_viewDidAppear:animated];
NSLog(@"viewDidAppear executed for %@", [self class]);
}
@end
问题5
not-runiing,inactive,active,background,suspended这几种状态的区别?
- Not running:App没有启动或者已经挂掉
- Inactive: App在前台运行,但是目前无法接受事件。比如载入中...
- Active: App在前台运行并可以接受事件,这是一个App最正常的状态。
- Background: App在后台运行,可以跑代码。大部分在这个阶段的App都即将会被挂起进入suspended状态。此阶段可能还会运行一些尚未完成的事物。
- Suspended:App在后台被挂起,无法执行代码,状态会被保存,直到下次被唤醒,或者被系统杀死。
问题6
什么时候用到Category?
Category用来在不同扩展原类的情况下,给一个类增加方法。一本用来给一个类增加附加的个性化的方法,比如给UIImage增加异步下载的方法。
问题7
找出以下代码中的错误,并改正:
@interface MyCustomController : UIViewController
@property (strong, nonatomic) UILabel *alert;
@end
@implementation MyCustomController
- (void)viewDidLoad {
CGRect frame = CGRectMake(100, 100, 100, 50);
self.alert = [[UILabel alloc] initWithFrame:frame];
self.alert.text = @"Please wait...";
[self.view addSubview:self.alert];
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
sleep(10);
self.alert.text = @"Waiting over";
}
);
}
@end
所有的UI操作都必须在主线程中进行。上述代码中的操作有可能无法在主线程中被执行。因为global dispatch队列无法保证获取主线程。所以需要做如下修改:
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
sleep(10);
dispatch_async(dispatch_get_main_queue(), ^{
self.alert.text = @"Waiting over";
});
});
问题8
viewDidlLoad和viewDidAppear的区别?
- viewDidLoad在view被加载完成后被调用,可以使Xib,storyboard或者是代码。
- viewDidAppear是view展现在设备上时被调用。
以上两个代理使用哪个取决于你的数据。如果数据是静态的,可以在viewDidLoad或cached被加载。
如果数据是动态的且经常变动,一般会放在viewDidAppear中加载。
无论如何,加载数据应避免卡主主线程。
问题9
当你使用UITableViewController来展示一个图片从服务器下载的表格时,你需要考虑什么?
主要需要考虑的是,图片下载是一个耗时操作,考虑时应注意一下要点:
只有在表格滚动到可视范围内时,再下载图片; 也就是说在
cellForRowAtIndexPath
被调用时,再下载图片。使用异步方式下载图片,异步下载应在后台线程中进行,以免卡主UI所使用的主线程;这样用户可以不间断的进行滚动。
当一个cell的图片下载完成后,我们需要检查cell是否还在view中可见或者是被其他数据重用的。如果cell被重用了,我们需要取消放弃图片,否则我们需要切换到主线程来改变cell的图片。
另外可以谈一下图片缓存。比如第三方类库WDImage的图片缓存机制。
问题10
什么事protocol?怎样定义?什么时候用?
protocol 类似JAVA的interface(接口),定义的时候需要写明必要和可选的方法,这些方法在其他的类准守这个protocol时必须或者可选则行的去实现。任何的类都可以实现一个protocol,其他的类可以发消息给这个类而不用去直到具体的类的类型。
@protocol MyCustomDataSource
- (NSUInteger)numberOfRecords;
- (NSDictionary *)recordAtIndex:(NSUInteger)index;
@optional
- (NSString *)titleForRecordAtIndex:(NSUInteger)index;
@end
最常用的是为UITableView或UICollectionView提供 DataSource时
问题11
什么是KVC和KVC?举例使用KVC来set一个值。
KVC,Key-Value-Coding。KVC的意义是,使一个对象的变量可以在运行时通过一个string key被获取,而不用知道具体的变量名称。
KVO,Key-Value-Observing。可以使一个controller或者类 观察到某一个类的变量的变化。
举例:
假设某一个类有一个变量 name
@property (nonatomic, copy) NSString *name;
我们可以通过KVC调用它:
NSString *n = [object valueForKey:@"name"]
我们可以更改它:
[object setValue:@"Mary" forKey:@"name"]
问题12
什么事block,怎么用?
Block是一种定义单个任务或者模块的方式,这种方式不需要写整个的OC类。事实上,block也是一种OC对象。这一种语言层面的特点使得类似于lambas和closure的编程技术可以在OC中使用。创建block使用^{ }语法。
myBlock = ^{
NSLog(@"This is a block");
}
他可以被调用:
myBlock();
此外,block也可以是一个确保运行时和编译类型安全的签名。比如,可以传送一个带签名的block给一个方法:
- (void)callMyBlock:(void (^)(void))callbackBlock;
还有,其他方法可以向block传送数据
- (void)callMyBlock:(void (^)(double, double))block {
...
block(3.0, 2.0);
}
问题13
iOS提供了怎样的多线程机制?
-
NSThread
创建了一个新的低级别线程,可以通过start
方法启动
NSThread* myThread = [[NSThread alloc] initWithTarget:self
selector:@selector(myThreadMainMethod:)
object:nil];
[myThread start];
-
NSOperationQueue
允许创建一个线程池来同步执行NSOperation
,NSOperation
也可以让NSOperationQueue
调用mainQueue
来调用组线程
NSOperationQueue* myQueue = [[NSOperationQueue alloc] init];
[myQueue addOperation:anOperation];
[myQueue addOperationWithBlock:^{
/* Do something. */
}];
- GDC Grand Central Dispatch 是OC比较新的一种多项城API。GDC可以支持队列化任务并在另一个主线程中派发。任务可以并发也可以按照FIFO进行顺序执行。
dispatch_queue_t myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(myQueue, ^{
printf("Do some work here.\n");
});
问题14
什么是 Responder Chain?
当我们在使用微信等工具,点击扫一扫,就能打开二维码扫描视图。在我们点击屏幕的时候,iphone OS获取到了用户进行了“单击”这一行为,操作系统把包含这些点击事件的信息包装成UITouch和UIEvent形式的实例,然后找到当前运行的程序,逐级寻找能够响应这个事件的对象,直到没有响应者响应。这一寻找的过程,被称作事件的响应链,如下图所示,不用的响应者以链式的方式寻找
响应者
在iOS中,能够响应事件的对象都是UIResponder的子类对象。UIResponder提供了四个用户点击的回调方法,分别对应用户点击开始、移动、点击结束以及取消点击,其中只有在程序强制退出或者来电时,取消点击事件才会调用。
问题15
delegate 和 notification的区别是设么?
二者都是iOS中用来发送值或者消息到某模块的。delegate用来传递一对一消息,协议有Apple制定。在delegate中,类有一些变量并且一般会实现/调用某些protocal
Notification 允许类似广播的方式来传递信息,范围可以使整个App。而发出广播消息者不需要了解接受者的详细信息。这一特点经常用来解耦。
[NSNotificationCenter defaultCenter]
postNotificationName:@"TestNotification"
object:self];
问题16
你在写UI,Xib,Storyboards或代买写UIview的时候有啥习惯或者喜好?
这里没有固定的答案,可以从各个方式的特点来说
Xib和Storyboard 比较适合快速的写一些UI,并且很适合产品经理快速搭建UI
但是Xib和Storyboard在维护起来比较麻烦
*代码写界面比较灵活容易维护,但是代码量比较大,写界面速度比较慢。
问题17
怎样安全的去保存用户离线数据?
- 如果数据非常的敏感,那么我们的建议是不要离线储存
- keychian是一个选择,但是在用户没有设置密码的时候,数据还是容易泄露
- SQLCipher是一个好的好的选择,他是一个加密的SQLite数据库。
- 使用SSL/HTTPS
- 数据物价,提供备份或者服务器储存备份
问题18
什么事MVC,iOS如何实现?
Model,View,Controller,一种设计模式把逻辑层、数据层和UI分开。iOS提供了UIView 作为View的基类。UIViewContrller作为Controller,监听view中的时间,在数据发生变化的时候更新UI。Model泛指App的各种数据,可以使用NSObject来实现,包括NSArray和NSDictionary。
有些开发者喜欢滥用UIViewController,而不顾MVC设计模式。
关于MVC设计模式的文章有如下:
https://www.objc.io/issues/1-view-controllers/lighter-view-controllers/
https://speakerdeck.com/trianglecocoa/unburdened-viewcontrollers-by-jay-thrash
https://programmers.stackexchange.com/questions/177668/how-to-avoid-big-and-clumsy-uitableviewcontroller-on-ios
另外,现在有一些比如MVVC的设计模式使用ReactiveCocoa。
问题19
项目经理报告程序崩了,你咋办?
首先这种情况下,开发人员没有获得足够的信息,第一步要做的事获得关于崩溃的更多详细信息。可以通过采访,错误重现等方式收集更多信息。
要注意:
- 设备型号
- 版本
- 最好有报错log
- 另外,如果导致问题的bug有很多,要注意和产品经理沟通,排优先级。
问题20
什么是autoLayout?如果说一个constraint坏了 是啥意思?
给UI一个限制 来布局UI,可以节省适配的效率。