问题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设计模式的文章有如下:

iOS 架构

iOS_架构模式

另外,现在有一些比如MVVC的设计模式使用ReactiveCocoa。

问题19

项目经理报告程序崩了,你咋办?

首先这种情况下,开发人员没有获得足够的信息,第一步要做的事获得关于崩溃的更多详细信息。可以通过采访,错误重现等方式收集更多信息。

要注意:

  • 设备型号
  • 版本
  • 最好有报错log
  • 另外,如果导致问题的bug有很多,要注意和产品经理沟通,排优先级。

问题20

什么是autoLayout?如果说一个constraint坏了 是啥意思?

给UI一个限制 来布局UI,可以节省适配的效率。

iOS BAT面试对答题