iOS笔试题

下面的代码输出什么?

@implementation Son : Father

- (id)init {
    self = [super init];
    if (self) {
        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));
    }
    return self;
}

@end

参考答案:

// 输出
NSStringFromClass([self class]) = Son
NSStringFromClass([super class]) = Son

参考解释:
这个题目主要是考察关于Objective-C中对self和super的理解。我们都知道:self是类的隐藏参数,指向当前调用方法的这个类的实例。那super呢?
很多人会想当然的认为“super和self类似,应该是指向父类的指针吧!”。这是很普遍的一个误区。其实 super是一个 Magic Keyword,它本质是一个编译器标示符,和self 是指向的同一个消息接受者!他们两个的不同点在于:super会告诉编译器,调用class 这个方法时,要去父类的方法,而不是本类里的。
上面的例子不管调用[self class]还是[super class],接受消息的对象都是当前 Son *xxx 这个对象。
当使用self调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用super时,则从父类的方法列表中开始找。然后调用父类的这个方法。

图片很大,需要分3次下载,然后合并才能用,应该怎么做?

参考答案:
通过dispatch_group_t来实现,将每部分图片下载请求放入到Group中,将合并图片的操作放在dispatch_group_notify中实现。
参考代码:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{ /*下载图片Part1 */ });
dispatch_group_async(group, queue, ^{ /*下载图片Part2 */ });
dispatch_group_async(group, queue, ^{ /*下载图片Part3 */ }); 
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    // 合并图片
});

参考解释:
本题是多线程的一种应用场景,能说出做法就算过关;如果能用代码表达,说明做过,经验丰富。也可以追问,上面的queue是串行队列还是并行队列?dispatch_get_main_queue()是串行队列还是并行队列?两者有什么区别?分别适用什么场景?

下面的代码存在什么问题?原因是什么?怎么解决?

@property (nonatomic, strong) HttpRequestHandler *handler;
@property (nonatomic, strong) NSData *data;

self.handler = [httpRequestHandler sharedManager];
[self.handle downloadData:^(id responseData) {
    self.data = responseData;
}];

参考答案:
循环引用
self强引用handler,handler强引用block,block强引用self,形成循环
采用weak self的方法解决
参考代码:

@property (nonatomic, strong) HttpRequestHandler *handler;
@property (nonatomic, strong) NSData *data;

self.handler = [httpRequestHandler sharedManager];

__weak typedof(self) weakSelf = self;
[self.handle downloadData:^(id responseData) {
    __strong typeof(weakSelf)strongSelf = weakSelf;
    strongSelf.data = responseData;
}];

参考解释:

  • block的引用循环问题在实际开发过程中比较常见。能找出这个问题,就算过关。
  • 能说出具体原因,并能从代码上消除引用循环,那就更好了。
  • 直接用weakSelf也是可以的,有strongSelf配合更好。
  • 如果能够回答出weakSelf是为了解决引用循环,strongSelf是为了防止事情没做完提前释放,更好
  • 如果知道ReactiveCocoa这个第三方库提供了一种更优雅的做法,那就更好
@property (nonatomic, strong) HttpRequestHandler *handler;
@property (nonatomic, strong) NSData *data;

self.handler = [httpRequestHandler sharedManager];

@weakify(self)
[self.handle downloadData:^(id responseData) {
    @strongify(self)
    strongSelf.data = responseData;
}];

以下代码在主线程调用,结果是什么?

NSLog(@"开始");
dispatch_sync(dispatch_get_main_queue(), ^{
    NSLog(@"进行中");
});
NSLog(@"结束");

参考答案:
只会打印第一句:开始,然后主线程就卡死了。
参考解释:
同步任务会阻塞当前线程,然后把 Block 中的任务放到指定的队列中执行,只有等到 Block 中的任务完成后才会让当前线程继续往下运行。那么这里的步骤就是:打印完第一句后,dispatch_sync
立即阻塞当前的主线程,然后把 Block 中的任务放到 main_queue
中,可是 main_queue
中的任务会被取出来放到主线程中执行,但主线程这个时候已经被阻塞了,所以 Block 中的任务就不能完成,它不完成,dispatch_sync
就会一直阻塞主线程,这就是死锁现象。导致主线程一直卡死。

有3 个任务:A: 从服务器上下载一张图片,B:给这张图片加个水印,C:把图片返回给服务器。如何实现?

参考答案:
使用NSOperation的addDependency方法
参考代码:

//1.任务一:下载图片
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"下载图片");
}];

//2.任务二:打水印
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"打水印");
}];

//3.任务三:上传图片
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"上传图片");
}];

//4.设置依赖
[operation2 addDependency:operation1];      //任务二依赖任务一
[operation3 addDependency:operation2];      //任务三依赖任务二

//5.创建队列并加入任务
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperations:@[operation3, operation2, operation1] waitUntilFinished:NO];

参考解释:
能够设置任务间的依赖,是NSOperation的特色,比较适合这个场景。当然,使用dispatch的串行队列也可以达到同样效果。
能想到这个方法就算过关,能写出代码,说明经验丰富。

SDWebImage原理是什么?或者说缓存的原理是什么?

参考答案:

  1. 从内存中(字典)找图片(当这个图片在本次程序加载过),找到直接使用;
  2. 从沙盒中找,找到直接使用,缓存到内存。
  3. 从网络上获取,使用,缓存到内存,缓存到沙盒。

如何以UIWebView显示www.apple.com网页的内容?

参考答案:

  1. 新建UIWebView,添加到view中;
  2. 写好地址为”http://www.apple.com“的NSURLRequest;
  3. webview 设置好delegate,调用加载方法,加载该NSURLRequest。在delegate方法中检查加载状态

参考代码:

UIWebView *webView = [[UIWebView alloc]initWithFrame:self.view.frame];
[self.view addSubview:webView];
NSString *urlStr = @"http://www.apple.com";
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:urlStr]];
[webView loadRequest:request];

参考解释:
只要能说出做法就算过关,能写出代码更好。UIWebView的基本用法,目前在Hybrid架构下,H5的比重越来越高。

NSString *obj = [[NSData alloc]init] ,obj在编译时和运行时分别是什么类型的对象?

参考答案:
编译时是NSString, 运行时是NSSData的一个实例
参考解释:
Object-C是动态语言,编译时和运行时类型可以不一样。不过平时不要这样用。平时用的多的是id,可以代表任何继承自NSObject的类,也涉及到强制转换。

根据下面代码片段,回答相应问题

NSArray *array = @[@"a", @"b", @"c", @"d"];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
  1. copyArray与array的地址是否一样?
  2. mCopyArray和array的地址又是否一样?
  3. 改变mCopyArray里面的元素内容,是否会刻变array的内容?
  4. copy和mutableCopy的拷贝操作有何不同?

参考答案:

  1. 一样;
  2. 不一样;
  3. 不改变
  4. copy浅拷贝,只是指针的复制,而内容未复制;
    mutableCopy是深拷贝,复制内容,新分配一段内存;

网友Coulson_Wang的说法是正确的,对于不可变对象,copy也是深拷贝。
这一点,平时也用到。一般返回值是不可变对象,但是具体做事的时候是可变对象,返回的时候,用copy函数就好了,这是一种习惯。

比如,连接两个数组的函数:

- (nonnull NSArray *)concatArray1:(nonnull NSArray *)array1 andArray2:(nonnull NSArray *)array2 {
    NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array1];
    
    for (id object in array2) {
        [mutableArray addObject:object];
    }
    
    return [mutableArray copy];   // 这是习惯用法,返回一个不可变的深拷贝给外部调用者
}

按照下面这样的例子使用:

NSArray *array = [self concatArray1:@[@8,@7,@8] andArray2:@[@"a", @"c",@"q"]];
NSLog(@"%@", array);

输出的结果,数组成员类型是NSObject(NSNumber和NSString混合),可以看调试截图:

8,7,8,a,c,q
数组内容.png

根据下面的代码,回答相应的问题:

IQuery.h

@protocol IQuery  
  
@required  
- (void)query:(NSString*) sql;  
  
@optional  
- (void)helloWorld;   
  
@end 

DBQuery.h

#import <Foundation/Foundation.h>  
#import "IQuery.h"  
  
@interface DBQuery : NSObject <IQuery>  
  
- (void)test:(id<IQuery>) obj;

@end 
  1. @required 表示什么意思?
  2. @optional 表示什么意思?
  3. “@interface DBQuery : NSObject <IQuery> ”中的<IQuery>表示什么意思?
  4. “- (void)test:(id<IQuery>) obj;”中的id<IQuery>表示什么意思?

参考答案:

  1. 必须实现的方法
  2. 可选实现的方法
  3. DBQuery遵循IQuery协议,会根据要求实现IQuery协议中的方法。其中- (void)query:(NSString*) sql; 必须实现;- (void)helloWorld; 根据实际情况,可以实现,也可以不实现。
  4. id表示obj是实现了IQuery协议的任意类型

参考解释:

id在实际中用得还是非常多的,比如代理模式中的delegate一般都是id类型,是Object-C动态特性的一种应用。面向协议的编程也非常普遍。协议还可以表示一种类型,用在函数参数中。

根据下面的代码回答问题

NSTimer *myTimer = [NSTimer timerWithTimeInterval:3.0 target:self selector:@selector(timerFired:) userInfo:nil repeats:NO];

[[NSRunLoop  currentRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode];
  1. 在滑动时,定时器会怎么样?怎么改进?
  2. [myTimer invalidate]; 是什么意思?
  3. [myTimer setFireDate:[NSDate distantFuture]]; 是什么意思?
  4. [myTimer setFireDate:[NSDate distantPast]]; 是什么意思?

参考答案:

  1. 滑动时定时器会停止;将定时器的模式改为NSRunLoopCommonModes就可以让定时器在滑动时正常触发。
  2. 取消定时器 ,是永久的停止,移除定时器对象
  3. 关闭定时器
  4. 开启定时器

参考解释:

定时器的使用还是比较常用的,苹果给的API名字不够人性化,容易造成一定的误解。

参考文章

iOS 面试常见问题最全梳理

2016第一份IOS笔试

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容

  • GCD -Grand Central Dispatch GCD包含于libdispatch.dylib,系统默认加...
    志城阅读 585评论 0 0
  • 1.#import跟#include、@class有什么区别?#import<>跟#import”"又什么区别? ...
    23d7c1910238阅读 144评论 0 1
  • 转载原文链接 面试能力要求:精通iphone的UI开发,能熟练操作复杂表视图,熟练使用图层技术, 可以自定义UI控...
    Lonely__M阅读 7,625评论 2 24
  • 《儒林外史》读来总是觉得怪怪的,如此好的选题,好的故事,作者又是一代名士,文学修养与张岱、冒襄在伯仲之间,按说应写...
    维扬之水阅读 980评论 0 2
  • 我站起身还没来得及反应过来,就被他紧紧抱住动弹不得,第一次被人箍在怀里,瞬间懵了并不知所措,我的左手依旧拿着手机...
    45度向阳阅读 178评论 0 0