iOS面试建议

定时器相关的问题

  • 定时器的模式问题是被问的最多的

UIScrollView(UITableView) 拖动时执行的是 UITrackingRunLoopMode,会导致暂停定时器,等恢复为 NSDefaultRunLoopMode 时才恢复定时器。
所以如果需要定时器在UIScrollView 拖动时也不影响的话,建议添加到UITrackingRunLoopModeNSRunLoopCommonModes 中:

NSTimer *timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode: UITrackingRunLoopMode]; ///< 或者 NSRunLoopCommonModes
  • 自动添加到当前NSRunLoop的方式,这种方式会导致滑动过程中定时器失效的问题,解决方式就是用(1)的方式设定NSRunLoop模式
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(test) userInfo:nil repeats:YES];
  • 定时器相关API的含义,没用过的可能会误解
[myTimer invalidate]; // 废弃定时器 ,是永久的停止,移除定时器对象
[myTimer setFireDate:[NSDate distantFuture]]; // 关闭定时器;遥远的将来才能触发,功能相当于关闭
[myTimer setFireDate:[NSDate distantPast]]; // 开启定时器;很久很久以前就触发了,功能相当于开启
  • GCD中的延时执行,相当于定时效果
dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC);
dispatch_after(timer, dispatch_get_main_queue(), ^(void) {
    NSLog(@"GCD-----%@",[NSThread currentThread]);
});
  • NSRunLoop结合起来用,定时器是一种中断源,知道这个的,基本上做得比较底层了,在实际工作中,还没怎么遇到
@property (nonatomic ,strong)dispatch_source_t timer;//  注意:此处应该使用强引用 strong
{
    //0.创建队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    //1.创建GCD中的定时器
    /*
     第一个参数:创建source的类型 DISPATCH_SOURCE_TYPE_TIMER:定时器
     第二个参数:0
     第三个参数:0
     第四个参数:队列
     */
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

    //2.设置时间等
    /*
     第一个参数:定时器对象
     第二个参数:DISPATCH_TIME_NOW 表示从现在开始计时
     第三个参数:间隔时间 GCD里面的时间最小单位为 纳秒
     第四个参数:精准度(表示允许的误差,0表示绝对精准)
     */
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);

    //3.要调用的任务
    dispatch_source_set_event_handler(timer, ^{
        NSLog(@"GCD-----%@",[NSThread currentThread]);
    });

    //4.开始执行
    dispatch_resume(timer);

    //
    self.timer = timer;
}

此处注意一定要强引用定时器 ,否则定时器执行到}后将会被释放,无定时效果。
GCD定时器时间非常精准,最小的定时时间可以达到1纳秒,所以用在非常精确的定时场合。

多线程相关问题

  • 串行队列和并行队列概念,同步执行和异步执行概念
NSLog(@"开始");
dispatch_sync(dispatch_get_main_queue(), ^{
    NSLog(@"进行中");
});
NSLog(@"结束");

这段代码:只会打印第一句:开始,然后主线程就卡死了。
能回答这个问题并作出解释,说明对这个问题了解比较透彻了。

相对基础一点的问题:比较容易混淆
(1)dispatch_queue_t queue = dispatch_queue_create ( "com.dispatch.serial" , DISPATCH_QUEUE_SERIAL );是串行队列还是并行队列?
dispatch_queue_t queue = dispatch_queue_create ( "com.dispatch.serial" , DISPATCH_QUEUE_CONCURRENT );是串行队列还是并行队列?
(2)dispatch_get_main_queue()是串行的还是并行的?
(3)dispatch_get_global_queue()是串行的还是并行的?
(4)dispatch_sync()是同步执行还是异步执行?
(5)dispatch_async()是同步执行还是异步执行?

  • n个异步任务都执行完毕后再执行下一步的场景

图片很大,需要分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(), ^{
    // 合并图片
});
  • 任务间依赖的场景

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

//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];
  • iOS中多线程技术的种类以及选择

(1)NSOperation & NSOperationQueue :是对GCD的对象化封装,并且有cancel功能,推荐使用
(2)CGD:至少要知道模板型使用方式

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{   
    // 耗时的操作   
    dispatch_async(dispatch_get_main_queue(), ^{   
        // 更新界面   
    });   
});

(3)NSThread:控制力更强一点,比较底层了,用得不多。一些常用的方法可以问问,比如start,cancel,sleepForTimeInterval等等。
(4)NSObject就有的方法performSelectorInBackground,swift中这个方法被取消了
(5)pthread,知道这个的,c应该不错

  • 线程同步方式,在实际编程中遇到不多,但是概念比较重要

(1)NSLock方式

   [xxxlock lock] //上锁

  同步代码块

  [xxxlock unlock]//解锁

(2)NSCondition方式

   [xxxCondition lock] //上锁

  同步代码块

  [xxxCondition unlock]//解锁

(3)@synchronized( 同一对象) 一般是self;这个使用方便,但是很耗资源

   @synchronized(self){

  线程执行代码;

  }

(4)OSSpinLock自旋锁,atomic关键字,GCD串行队列,循环锁NSRecursiveLockpthreadmutex,信号量等等

本地存储,本地缓存

  • 沙盒的目录结构,使用场合
    Application:存放程序源文件,上架前经过数字签名,上架后不可修改
    Documents: 保存应⽤运行时生成的需要持久化的数据,iTunes同步设备时会备份该目 录。例如,游戏应用可将游戏存档保存在该目录
    tmp: 保存应⽤运行时所需的临时数据,使⽤完毕后再将相应的文件从该目录删除。应用 没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时 不会备份该目录
    Library/Caches: 保存应用运行时⽣成的需要持久化的数据,iTunes同步设备时不会备份 该目录。⼀一般存储体积大、不需要备份的非重要数据,比如网络数据缓存存储到Caches
    Library/Preference: 保存应用的所有偏好设置,如iOS的Settings(设置) 应⽤会在该目录中查找应⽤的设置信息。iTunes同步设备时会备份该目录

  • 数据持久化方案
    (1)plist属性列表存储(如NSUserDefaults
    (2)文件存储(如二进制数据写入文件存储,通过NSFileManager来操作将下载起来的二进制数据写入文件中存储)
    (3)NSKeydeArchiver归档存储, === 这个要实现NSCoding协议,model要实现哪两个函数?这点在实际使用中也可能忘记
    (4)数据库SQLite3存储(如FMDB、Core Data)=== 直接用SQL语句和CoreData的区别,CoreData的“坑”
    (5)KeyChain,用户名密码 === 代码怎么实现?需要导入哪几个系统framework

  • SDWebImage的原理,或者其他图片缓存库
    (1)从内存中(字典)找图片(当这个图片在本次程序加载过),找到直接使用;
    (2)从沙盒中找,找到直接使用,缓存到内存。
    (3)从网络上获取,使用,缓存到内存,缓存到沙盒。

  • YYCache的原理,或者其他缓存库的原理
    (1)内存缓存
    (2)硬盘缓存
    (3)key-value的方式,支持对象
    (4)本质还是sqlite数据库和NSFile文件系统;20K阈值,内容少用数据库,内容多用文件,综合性能最高
    (5)更新逻辑:设定时间和体积。队列方式,最新使用的,新加入,需要优先的放队列首部。更新时,先从队列尾部删除

  • NSURLCache、NSURLRequest本身的缓存机制,AFNetworking用的是这一套。==== 这个用得不多,了解这些细节的不多,比较难

(1)获得全局缓存对象(没必要手动创建)

NSURLCache *cache = [NSURLCache sharedURLCache]; 

(2)设置内存缓存的最大容量(字节为单位,默认为512KB)

- (void)setMemoryCapacity:(NSUInteger)memoryCapacity;

(3)设置硬盘缓存的最大容量(字节为单位,默认为10M)

- (void)setDiskCapacity:(NSUInteger)diskCapacity;

(4)硬盘缓存的位置:沙盒/Library/Caches

(5)取得某个请求的缓存

- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request; 

(6)清除某个请求的缓存

- (void)removeCachedResponseForRequest:(NSURLRequest *)request;

(7)清除所有的缓存

- (void)removeAllCachedResponses;
NSURLRequestUseProtocolCachePolicy // 默认的缓存策略(取决于协议)

NSURLRequestReloadIgnoringLocalCacheData // 忽略缓存,重新请求

NSURLRequestReloadIgnoringLocalAndRemoteCacheData // 未实现

NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData // 忽略缓存,重新请求

NSURLRequestReturnCacheDataElseLoad// 有缓存就用缓存,没有缓存就重新请求

NSURLRequestReturnCacheDataDontLoad// 有缓存就用缓存,没有缓存就不发请求,当做请求出错处理(用于离线模式)

NSURLRequestReloadRevalidatingCacheData // 未实现

Http协议header字段,比如max-age,ETag,Last-Modified等字段的含义
  • UIWebView,WKWebView清理缓存的机制?
    WKWebView从iOS8推出,但是清理缓存的API要从iOS9开始

属性修饰符

  • block中修饰外面变量的修饰符? __block

  • 打破引用循环的关键字? weak;会自动设为nil,防止崩溃;如果能解释清楚自动设nil的原理,是高手

  • 默认的关键字?strong

  • nonatomic? 非线程安全,加快速度。

  • atomic? 对setter加锁,用@synchronized加锁,耗性能;对getter不加锁,不能做到“真正的线程安全”

  • assign、weak、unsafe_unretained的区别? assign用于基础类型,“如果用于对象,不会设为nil,会导致野指针,会带来崩溃”

  • copy?NSString,NSArray,NSDictionary,NSSet等。引用计数对这些集合类型无意义

block引用循环

  • 解决的方案weakSelf
 __weak __typeof(self)weakSelf = self;
[self.context performBlock:^{
     __strong __typeof(weakSelf)strongSelf = weakSelf; 
    [strongSelf doSomething];
    [strongSelf doMoreThing];
} ];
  • strongSelf的原因? 为了防止事情还没做完,weakSelf就变成了nil

  • block不需要用weakSelf的场合?
    动画的时候不需要,比如

self.alpha = 0;
[UIView animateWithDuration:0.2 animations:^ {
    self.alpha = 1;
}]

runtime动态特性

  • NSString *obj = [[NSSData alloc]init] ,obj在编译时和运行时分别是什么类型的对象?
    编译时是NSString, 运行时是NSSData的一个实例
  1. 字典转模型的原理?第三方库?
    YYModel
    属性列表,class_copyPropertyList

  2. 不埋点统计,怎么做到? 热更新JSPatch的原理?
    方法交换 Method Swizzling class_getInstanceMethod() method_exchangeImplementations()

  3. 如何给类别category添加属性?
    关联对象
    objc_setAssociatedObject objc_getAssociatedObject

  4. 如何在不创建类的前提下调用类的方法?用URL处理函数调用
    NSClassFromString()这个函数可以把URL中的字符串转化为本地定义的类
    performSelector方法执行相应的方法

Native和H5的交互方式

(1)截取URL,定义scheme,做相应处理
(2)JavaScriptCore框架jsContext,使用注入的方法
(3)WKWebView的注入方式

第三方库WebViewJavascriptBridge使用的是截取URL的方式,对UIWebViewWKWebView都适用

深复制,浅复制

NSArray *array = @[@"a", @"b", @"c", @"d"];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
  1. copyArrayarray的地址是否一样? 一样
  2. mCopyArrayarray的地址又是否一样? 不一样
  3. 改变mCopyArray里面的元素内容,是否会刻变array的内容? 不改变
  4. copymutableCopy的拷贝操作有何不同?
    copy浅拷贝,只是指针的复制,而内容未复制;
    mutableCopy是深拷贝,复制内容,新分配一段内存;

iOS架构

MVC
MVVM
MVP
VIPER

NSArray的实现方式?

指针的数组

需要区分流量来自哪个渠道,怎么做?

提升表格性能的方法?

(1)无用的网络请求及时取消
(2)表格cell重用
(3)提前算好cell的高度
(4)圆角不要用cornerRadius

Https和Http的区别?

Https == http + socket + TLS
iOS9开始,XCode默认用Https
如何继续用Http?在plist中将某个字段打开
企业版账号发布时,ipa包可以http的,但是那个plist文件是需要https的,不然不能自动安装程序

bitCode

从iOS9开始
好处是降低安装包的大小
苹果后台根据用户手机,只下传必要的图片

在ViewDidLoad中设置frame有什么问题?

UIImageView实现圆角的方法?

(1)Qurarz
(2)layerCornerRadius
(3)用path

连接蓝牙要注意些什么?

iOS中提供一个单例用于蓝牙相关的函数
(1)广播,用于扫描设备,选中特定设备
(2)建立点对点连接
(3)协议一般开头是兼容微信的头部,然后是自己的头部,然后是数据
(4)数据要按照一定的大小进行分包,每次传输的大小是受限的
(5)数据是NSData的,转化为有意义的自定义类型时要注意大端和小端字节序的问题
(6)传输时有奇偶校验的事情,要跟firmware端的约定好
(7)丢包重传,定时重连,空中升级等等都是比较令人头疼的内容

Object-C的一些容易误解的特性

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

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

推荐阅读更多精彩内容

  • 史上最全的iOS面试题及答案 iOS面试小贴士———————————————回答好下面的足够了----------...
    Style_伟阅读 2,344评论 0 35
  • 多线程、特别是NSOperation 和 GCD 的内部原理。运行时机制的原理和运用场景。SDWebImage的原...
    LZM轮回阅读 2,001评论 0 12
  • iOS面试小贴士 ———————————————回答好下面的足够了------------------------...
    不言不爱阅读 1,959评论 0 7
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,121评论 29 470
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139