18个iOS开发面试问题
问题1
在UITableViewCell构造函数上:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
什么是reuseIdentifier用来?
这个reuseIdentifier用于指示单元格可以在UITableView。例如,当单元格看起来相同,但内容不同时。这个UITableView的内部缓存UITableViewCell带着reuseIdentifier"并允许在dequeueReusableCellWithIdentifier;叫做。通过重用表单元格的滚动性能,表视图的性能更好,因为不需要创建新的视图。
问题2
解释原子和非原子合成性质的区别?
原子和非原子是指属性的setters/getters是否会原子地读取和写入属性的值。当在属性上使用原子关键字时,对它的任何访问都将是“同步的”。因此,对getter的调用将被保证返回一个有效值,但是这会带来较小的性能损失。因此,在某些情况下,非原子用于提供对属性的更快访问,但在罕见的情况下,有可能出现争用条件导致属性为零(当一个值从另一个线程设置,旧值从内存中释放,但新值尚未完全分配到该属性的内存位置时)。
问题3
解释复制和保留的区别?
保留对象意味着保留计数增加1。这意味着对象的实例将被保存在内存中,直到它的保留计数下降到零为止。该属性将存储对此实例的引用,并与保留该实例的其他任何人共享相同的实例。复制意味着对象将被复制值复制。它不与任何其他人共享。
问题4
目标C中的方法是什么?你为什么要使用它?
方法swizzling允许在运行时为类调度表中的不同实现切换现有选择器的实现。Swizzling允许您编写可以在原始方法之前和/或之后执行的代码。例如,可能是为了跟踪方法执行所占用的时间,或者是插入日志语句。
#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
不运行、不活动、活动、背景和暂停执行状态之间有什么区别?
不跑步的:该应用程序尚未启动或正在运行,但被系统终止。
不活动:该应用程序运行在前台,但目前没有接收事件。(不过,它可能正在执行其他代码。)当应用程序转换到另一种状态时,它通常只在这种状态下停留很短的时间。
活跃:该应用程序运行在前台,并接收事件。这是前台应用程序的正常模式。
背景:该应用程序在后台,并执行代码。大多数应用程序在被暂停的过程中都会短暂地进入这个状态。但是,请求额外执行时间的应用程序可能会在这种状态下停留一段时间。此外,直接启动到后台的应用程序将进入此状态,而不是非活动状态。
暂停:该应用程序在后台,但没有执行代码。系统会自动将应用程序移动到此状态,并且在此之前不会通知它们。当应用程序挂起时,它会留在内存中,但不会执行任何代码。当出现内存不足的情况时,系统可能会在没有通知的情况下清除挂起的应用程序,以便为前台应用程序腾出更多的空间。
问题6
什么是类别,什么时候使用?
类别是一种在不扩展类的情况下向类添加其他方法的方法。它经常用于添加相关方法的集合。一个常见的用例是在Cocoa框架中的类中添加额外的方法。例如,将异步下载方法添加到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更新都必须在主线程上完成。在上面的代码中,警告文本的更新可能发生在主线程上,也可能不会发生,因为全局调度队列无法保证。因此,应该修改代码以始终在主线程上运行UI更新。
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
.之间的区别是什么?viewDidLoad和viewDidAppear?
您应该使用哪一个从远程服务器加载数据以在视图中显示?
viewDidLoad在加载视图时调用,无论是从xIB文件、故事板还是以编程方式在loadView. viewDidAppear每次在设备上显示视图时调用。使用哪一个取决于数据的用例。如果数据相当静态且不太可能更改,则可以将其加载到viewDidLoad并被缓存。但是,如果数据定期更改,则使用viewDidAppear装它更好。在这两种情况下,应该在后台线程上异步加载数据,以避免阻塞UI。
问题9
在编写UITableViewController哪个显示从远程服务器下载的图像?
这在IOS中是一个非常常见的任务,这里的一个好答案可以涵盖大量的知识。问题中的重要信息是,图像是远程托管的,下载可能需要时间,因此,当需要“考虑”时,您应该讨论:
只有当单元格滚动到视图中时,即当cellForRowAtIndexPath叫做。
在后台线程上异步下载映像,以免阻塞UI,这样用户就可以继续滚动。
当图像下载到一个单元时,我们需要检查该单元格是否仍然在视图中,或者它是否已被另一条数据重复使用。如果它已被重用,那么我们应该丢弃图像,否则我们需要切换回主线程来更改单元上的图像。
其他好的答案可在下方评论讨论离线缓存图像,在下载图像时使用占位符图像。
问题10
什么是协议,您如何定义自己的协议,以及什么时候使用协议?
协议类似于Java的接口。它定义了一个类在采用协议时必须/可以实现的所需方法和可选方法的列表。任何类都可以实现协议,然后其他类可以根据协议方法向该类发送消息,而不知道该类的类型。
@protocol MyCustomDataSource
- (NSUInteger)numberOfRecords;
- (NSDictionary *)recordAtIndex:(NSUInteger)index;
@optional
- (NSString *)titleForRecordAtIndex:(NSUInteger)index;
@end
一个常见的用例是为UITableView或UICollectionView.
问题11
什么是KVC和KVO?给出一个使用KVC设置值的例子。
KVC代表键值编码。它是一种机制,可以在运行时使用String来访问对象的属性,而不必在开发时静态地知道属性名称。KVO代表键值观测并允许控制器或类观察属性值的更改。
假设有一项财产name在课堂上:
@property (nonatomic, copy) NSString *name;
我们可以使用KVC访问它:
NSString *n = [object valueForKey:@"name"]
我们可以通过发送消息来修改它的值:
[object setValue:@"Mary" forKey:@"name"]
问题12
什么是区块,它们是如何使用的?
块是一种定义单个任务或行为单元的方法,而不必编写整个Object-C类。在封面下,块仍然是目标C对象。它们是语言级别的特性,允许在Object-C中支持lambdas和闭包等编程技术。创建块使用^ { }语法:
myBlock = ^{
NSLog(@"This is a block");
}
可以这样调用它:
myBlock();
它本质上是一个函数指针,它还具有一个签名,可用于在编译和运行时执行类型安全。例如,可以将具有特定签名的块传递给如下方法:
- (void)callMyBlock:(void (^)(void))callbackBlock;
如果希望向块提供某些数据,可以更改签名以包括它们:
- (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. */
}];
GCD或中央调度是Object-C的一个现代特性,它提供了一组丰富的方法和API,以支持常见的多线程任务。GCD提供一种在主线程、并发队列(任务并行运行)或串行队列(任务以FIFO顺序运行)上调度任务的方法。
dispatch_queue_t myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(myQueue, ^{
printf("Do some work here.\n");
});
ps;iOS开发交流技术群:欢迎你的加入,不管你是大牛还是小白都欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长
问题14
应答器链是什么?
当某个事件发生在视图中,例如触摸事件时,该视图将将该事件激发到UIResponder对象关联到UIView。第一UIResponder是UIView本身,如果它不处理事件,那么它会继续沿着链一直持续到UIResponder处理事件。这条链将包括UIViewControllerS,家长UIViewS及其相关UIViewControllerS,如果没有一个处理该事件,则UIWindow被问到它是否能够处理它,最后如果它不能处理事件,则UIApplicationDelegate被问到了。
如果你有机会把这个画出来,给面试官留下深刻印象是值得的:
image.png问题15
使用代表和通知?
两者都用于向感兴趣方发送值和消息。一个代表是一对一的交流,是苹果公司推广的一种模式。在……里面代表团类引发事件将具有代表并且通常会期望它实现一些protocol。这个委托类然后可以调用_GATE_s协议方法。
通知允许类跨整个应用程序向任何感兴趣方广播事件。因此,广播类不需要知道有关此事件的侦听器的任何信息。通知在帮助分离应用程序中的组件方面非常有用。
ps;iOS开发交流技术群:欢迎你的加入,不管你是大牛还是小白都欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长
[NSNotificationCenter defaultCenter]
postNotificationName:@"TestNotification"
object:self];
问题16
在编写UI时,您的偏好是什么?XIB文件、故事板或编程版UIView?
这是没有正确或错误的答案,但这是一个很好的方式,看看你是否理解的好处和挑战的每一种方法。以下是我听到的常见答案:
故事板和XIB非常适合快速生成符合设计规范的UI。对于产品经理来说,他们也很容易直观地看到屏幕上有多远。
故事板还能很好地代表通过应用程序的流,并允许对整个应用程序进行高级别的可视化。
故事板的缺点是,在团队环境中,它们很难协同工作,因为它们是一个单一的文件,合并变得很难管理。
故事板和XIB文件也会受到重复的影响,很难更新。例如,如果所有按钮都需要看起来完全相同,并且突然需要改变颜色,那么在故事板和xibs之间这样做可能是一个很长/很困难的过程。
程序化构造UIView它可以是冗长乏味的,但它可以允许更大的控制,也可以更容易地分离和共享代码,它们也可以更容易地进行单元测试。
大多数开发人员都会建议将所有3种代码组合在一起,这样共享代码才有意义,然后才是可重用的。UIViewS或Xib档案。
问题17
如何安全地将私有用户数据脱机存储在设备上?应采取哪些其他安全最佳做法?
同样,没有正确的答案,但这是一个很好的方式,看看一个人已经挖了多少iOS安全。如果你是在与一家银行面谈,我几乎肯定会希望有人对此有所了解,但所有公司都需要认真对待安全问题,以下是我希望在回答中听到的最理想的话题清单:
如果数据非常敏感,那么它就不应该离线存储在设备上,因为所有设备都是可破解的.
密钥链是安全存储数据的一种选择。然而,它的加密是基于设备的密码。用户不会被迫设置引脚,因此在某些情况下,数据甚至可能不会被加密。此外,用户的密码可能很容易被黑。
更好的解决方案是使用类似于sql密码这是一个完全加密的SQLite数据库。加密密钥可以由应用程序强制执行,并与用户的密码分离
其他安全最佳做法包括:
仅通过SSL/HTTPS与远程服务器通信。
如果可能的话,在应用程序中实现证书钉扎,以防止中间人对公共WiFi的攻击。
通过覆盖敏感数据清除内存中的敏感数据。
确保正在提交的数据的所有验证也在服务器端运行。
问题18
什么是MVC,它是如何在IOS中实现的?
你经历过哪些陷阱?有什么替代MVC的方法吗?
MVC代表模型,视图,控制器。它是一种设计模式,它定义了在实现用户界面时如何分离逻辑。在iOS中,Apple提供UIView作为所有_View_s的基类,UIViewController提供支持控制器中的事件。视点并更新视点当数据发生变化时。这个模型表示应用程序中的数据,可以使用NSObject,包括数据收集,如NSArray和NSDictionary.
人们遇到的一些陷阱是臃肿的。UIViewController而不是将代码分离成超出MVC格式的类。