iOS面试题总结(持续更新)
过段时间打算跳槽,找了一些面试题来做,在这里做个总结方便review,希望能对要面试的童鞋有帮助。
以下为面试题:
运行以下代码会有什么结果
NSString *str1 = @"str1";
NSString *str2 = [NSString stringWithFormat:@"str1"];
NSString *str3 = @"str1";
NSLog(@"str1 == str2 --- %d", str1 == str2);
NSLog(@"str1 == str3 --- %d", str1 == str3);
NSLog(@"str1 isEqualToString str2 --- %d", [str1 isEqualToString:str2]);
NSLog(@"str1 isEqualToString str3 --- %d", [str1 isEqualToString:str3]);
第一眼看这道题,只能确定使用isEqualToString:来比较字符串是比较每一个字符,所以isEqualToString肯定是true,而在OC里使用==号用于判断是否指向同一个地址,那么问题就来了,使用字面量创建的字符串与调用方法创建的有什么区别呢?
实践出真知,老老实实敲代码,打上断点来一探究竟
可以看到使用字面量创建的字符串为常量字符串,而用方法创建的则是指针字符串。常量字符串会在app销毁后释放,在app存在期间会一直存在,且相同的常量字符串都指向同一个地址。
运行结果就如下了
2. 以下方式创建的timer有什么区别
[NSTimer scheduledTimerWithTimeInterval:.f repeats:YES block:^(NSTimer * _Nonnull timer) {
//创建一个timer并且在当前的runloop中执行。
}];
[NSTimer scheduledTimerWithTimeInterval:.f repeats:NO block:^(NSTimer * _Nonnull timer) { }];
//timer加入到runloop才能fire成功
[[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:.f] interval:.f repeats:YES block:^(NSTimer * _Nonnull timer) { }];
//创建timer必须加入到run loop才能执行
[NSTimer timerWithTimeInterval:.f target:self selector:@selector(performTimer:) userInfo:nil repeats:YES]
我之前对timer的理解就是指定timer启动的时间、是否重复执行,是否立刻执行或手动fire。再深入一点就是可以将timer加入到不同的runloop,这样就能在scrollview滑动的时候也不影响timer执行了。查资料发现,NSTimer在repeats为YES的状态下会对target强引用,并且在没有invalidate的情况下是不会释放的,因此使用timer的时候就可能会出现循环引用的情况。例如,控制器A强引用timer,同时timer的target为A,这就产生了循环引用,当控制器被pop后,该控制器也不会销毁,就会造成内存泄漏。所以在使用timer的时候就需要在适当的时机来释放timer。仅仅是invalidate依然会造成循环引用,只能把timer置为nil才可以。拿之前的例子来说,就需要在控制器的生命周期来做这件事,viewWillAppear创建timer,在viewWillDisappear将timer置为nil。
3. 如有需求“一段文字中的指定位置插入一张图片”,请写出实现思路。
可以利用富文本NSAttributeString与NSTextAttachment来实现,先找到要插入图片的位置,然后利用NSTextAttachment来包装图片,最后用NSTextAttachment来生成NSAttributeString即可。
4. WebView内存管理问题说说自己的经验和看法
UIWebView本来就有内存泄漏的问题,只能通过一些手段来减少内存泄漏,并不能完全的解决,要解决的办法就是使用WKWebView。优化的方法如下:
(1) 收到内存警告时清除缓存
- (void)applicationDidReceiveMemoryWarning:(UIApplication*)application
{
[[NSURLCache sharedURLCache] removeAllCachedResponses];
}
(2)释放webView时
self.webView.delegate = nil;
[self.webView loadHTMLString:@"" baseURL:nil];
[self.webView stopLoading];
[self.webView removeFromSuperview];
[[NSURLCache sharedURLCache] removeAllCachedResponses];
[self.webView release];
(3) webViewDidFinishLoad时
[[NSUserDefaults standardUserDefaults] setInteger: forKey:@"WebKitCacheModelPreferenceKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
5. RunLoop和线程的关系
通常情况下线程在执行完代码后就会销毁,RunLoop其实就是事件处理循环,只有当接受到退出事件时才会退出。在iOS开发中,RunLoop与线程是一一对应的关系,一个RunLoop对应一个线程。需要注意的是只有主线程会在默认状态下创建RunLoop,其他的辅助线程需要自己显示的调用
[NSRunLoop currentRunLoop]来获得与当前线程绑定的RunLoop(ps:如果RunLoop不存在则创建一个新的)。创建出来的RunLoop需要在其中添加有Timer/Source/Observer或者march port,不然RunLoop会销毁。
6. ARC通过什么方式管理内存
不只是ARC,MRC也是利用引用计数来进行内存管理的,只是ARC管理就不需要自己来Release和Retain。系统会在自动释放池结束时,对没有强引用的对象统一进行释放。
7. 使用Block时,什么情况会造成循环引用,如何解决?
因为block会对所有在block中使用到的对象进行强引用(capture),所以当block被一个对象持有,同时这个对象又在Block中被使用时就会出现强引用。解决方式就是在Block中只用弱引用,代码如下
__weak typeof(self)weakSelf = self;
void (^block)(void) = ^{
NSLog(@"%@", weakSelf);
}
还有一种方式是主动打破循环引用,将调用的block置为nil
8.使用synthesize和dynamic分别有什么作用
@synthesize的作用:为Property指定生成要生成的成员变量名,并生成getter和setter方法。用途:对于只读属性,如果同时重新setter和getter方法,就需要使用synthesize来手动合成成员变量,代码如下
@interface Person : NSObject @property (nonatomic, assign, readonly) NSInteger age; @end @implementation Person
@synthesize age = _age;
- (void)setAge:(NSInteger)age
{
_age = age;
} - (NSInteger)age
{
return _age;
}
@end
@dynamic的作用:告诉编译器,不用为指定的Property生成getter和setter。使用方式:当我们在分类中使用Property为类扩展属性时,编译器默认不会为此property生成getter和setter,这时就需要用dynamic告诉编译器,自己合成了,代码如下
@interface Person (Extension) @property (strong, nonatomic) NSString *name; @end @implementation Person (Extension)
@dynamic name; - (void)test
{
NSLog(@"%@", self.name);
} @end
9. runtime如何通过Selector找到对应的IMP地址?(分别考虑类方法和实例方法)
这就要从类的结构来说了,先来看下面这张官方给出的
。
10. initialize和load的区别
initialize会在Class第一次收到消息时调用,父类会比子类先调用,如果子类没有重新实现initialize方法,此方法会在子类接受消息时被多次调用。load方法会在类被加载到运行时环境中时调用,在整个运行时期间都只会调用一次。
11. 如何申明私有变量和私有方法?以及外部如何调用
申明私有变量总的来说有3种方式,一种是在@interface中利用@private 关键字来申明,第二种方式是在@implementation声明。私有方法声明的话,就只能够在@implementation中声明了。访问私有变量可以通过提供getter和setter方法,KVO中key使用成员变量名也可以访问,调用私有方法只能通过暴露方法,或者是利用runtime,以及NSObject提供的方法performSelector系列的方法。
12.以下代码运行结果
@interface Student : Person @end @implementation Student - (instancetype)init
{
self = [super init];
if (self) {
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
} @end
运行结果都为Student,原因是self表示此方法从自己的方法表开始找,super则表示方法先从父类的方法表里找,因为class方法两个类都没有实现,最终方法的都是会NSObject中找到,所以结果都是调用的类名Student。
14. 用代码实现一个冒泡算法(明天来)
15. readwrite,readonly, assign,retain, copy, nonatomic,strong的作用
readwrite表示此属性可以读写,会自动生成getter与setter
readonly表示此属性只可读,外部只能方法getter方法
assign在MRC中用于表示引用计数不用加一,以及用于除类之外的声明。在ARC中用于除了类之外的声明
retain在MRC中表示引用计数加一,在ARC中表示强引用
copy在MRC中不会影响调用copy方法的对象的引用计数,在ARC中表示在setter方法中会调用传入对象的copy方法,常用于需要不可变对象的属性NSString、NSArray等
atomic表示属性读写的原子性,然而并不能保证线程安全
nonatomic则不保证线程安全
16. 请写出UIViewController的生命周期
init->viewDidLoad->ViewWillAppear->ViewDidappear->viewWillDisappear->viewDidDisappear->dealloc
17. 请写出一个单例实现
利用dispatch_once,其他的实现方式可以重写allocWithZone方法
+ (instancetype)sharedInstance
{
static Student *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
18.UIView相关
19. 当前维护的App的崩溃率是多少?怎么追踪并解决的?线上崩溃如何解决的?
崩溃率这个就不谈了,开发过程中遇到的崩溃问题主要查看崩溃的栈信息,利用异常断点来解决。线上崩溃的话,就是利用dSYMS文件来符号化苹果的崩溃日志来解决了
20. 什么是事件响应链?当用户与iPhone的触屏产生互动时?都发生了什么?事件是如何传递的?
讲响应者链条前,需要知道iOS中事件响应是基于UIResponder对象的及子类,包括UIResponder的子类UIView、UIViewController、UIWindow、UIApplication,当iOS App接收到触摸事件时,UIKit会自动的找到最合适的第一响应者。没有处理的事件会沿着当前激活状态的响应者链条传递下去。
如下图所示,这是app中默认的事件响应链条,如果在UILabel上触发了为处理的事件,那么这个事件会传递给label的父视图UIView,然后是UIWindow对象。对于根视图而言,事件会先传递给UIViewController,然后才是window。如果UIWindow也没有处理,那就会传递给UIApplication,application也未处理的话,如果application的代理对象是UIResponder子类并且没有出现在之前的响应者链条中。
当用户触摸屏幕时,UIKit会根据默认规则来找到第一事件响应者,此规则是基于hit-testing来决定的。UIKit会在touch发生的view的视图层级中比较touch location与View 的bounds。 hitTest:withEvent:方法会遍历整个视图层级找到最深层次的包含此次触摸的子视图,这个子视图就会是第一事件响应者。
21.RunLoop是什么? 使用RunLoop的目的是什么?何时使用?使用要注意些什么?
RunLoop是一个事件处理的循环,这个循环会不停的从一个地方收到事件,收到事件就做相应的处理,只有收到退出事件时,这个循环才会退出。
在iOS的开发中,主线程的RunLoop会自动创建,辅助线程的RunLoop只有在主动获取时才会被创建。
RunLoop由RunLoopMode构成,RunLoopMode又由Timer/Source/Observer构成。RunLoop同时只能够运行在一个Mode下,app主线程的 RunLoop 里有两个预置的 Mode:kCFRunLoopDefaultMode 和 UITrackingRunLoopMode。当TableView处于滑动过程中时,RunLoop的mode为UITrackingRunLoopMode,其余时间Mode为:kCFRunLoopDefaultMode。
在app开发中默认用到RunLoop的地方有:NSTimer、NSObject提供的performSelectorOnMainThread:withObject:waitUntilDone:方法。当我们使用NSTimer在指定时间执行时,其实是在RunLoop中添加这个timer,并在到达指定的时间点后执行回调。NSObject执行perform等方法的时候同样是在指定时间来执行那个回调,只是在执行perform方法是当前线程必须要存在RunLoop才行,不然无效。
系统中使用RunLoop的地方有AutoReleasePool,RunLoop会在每一次进入RunLoop时创建自动释放池,然后在RunLoop进入waiting状态时释放旧的释放池并重新创建自动释放池,最后在ExitRunLoop时释放自动释放池。
在日常的iOS开发中,默认创建的Timer是添加在kCFRunLoopDefaultMode模式下的,所以在滑动TableView时,RunLoop会切换为UITrackingRunLoopMode,timer会被暂停。要想Timer能够在UITrackingRunLoopMode下正常运行有两种办法,一是将Timer分别添加到以上两种Mode中,二是将 Timer 加入到顶层的 RunLoop 的 “commonModeItems” 中。”commonModeItems” 被 RunLoop 自动更新到所有具有”Common”属性的 Mode 里去。
22.说说你对线程和进程的理解?
总的来说,进程是程序分配资源的最小单元,线程是程序运行的最小单元,进程可以有多个线程组成。
23.对大量数据列表有什么优化方案?
优化1. 利用UITableView重用cell的机制
优化2. 分批次异步加载数据
优化3. 缓存高度
优化4. 将耗时操作放在异步线程来做
24.平时工作中使用的动画库有哪些?
faceBook的pop动画、
25.objc实现多重继承
oc不支持多重继承,只支持多层继承。要变相的实现多重继承,可以利用protocol来实现
26.数组查找平衡点
int findBalancePoint(int a[], int n)
{
if (n == ) {
return -;
}
int leftSum = ;
int rightSum = ;
for (int i = , j = n - ; ; i++, j--) {
leftSum += a[i];
rightSum += a[j];
if (i < j) {//继续加
continue;
}else{
if (leftSum == rightSum) {//相等
if (i == j) {//奇数个
return i + ;
}else{//偶数个
return n;
}
}else{//不等
return -;
}
}
}
return -;
} int main(int argc, const char * argv[]) {
@autoreleasepool { int a[] = {-, , , , -, , };
int b[] = {, , , , , }; int found1 = findBalancePoint(a, );
int found2 = findBalancePoint(b, );
NSLog(@"%i %i", found1, found2); }
return ;
}
iOS面试题总结(持续更新)的更多相关文章
- 一些有意思的面试题(持续更新) .C语言编程技巧札记
一些有意思的面试题(持续更新) http://blog.csdn.net/wangyuling1234567890/article/details/38565239 C语言编程技巧札记 http:// ...
- 【前端面试】Vue面试题总结(持续更新中)
Vue面试题总结(持续更新中) 题目参考链接 https://blog.csdn.net/weixin_45257157/article/details/106215158 由于已经有很多前辈深造VU ...
- iOS系列教程 目录 (持续更新...)
前言: 听说搞iOS的都是高富帅,身边妹子无数.咱也来玩玩.哈哈. 本篇所有内容使用的是XCode工具.Swift语言进行开发. 我现在也是学习阶段,每一篇内容都是经过自己实际编写完一遍之后,发现 ...
- Zookeeper 面试题(持续更新、吐血推荐)
文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...
- SpringCloud 面试题 (持续更新、吐血推荐)
文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...
- web前端面试题(持续更新)
此文是我本人在面试的时候遇到的问题和一些同学遇到的问题加资料上面的问题的总结.(将会持续更新,因为未有满意工作) 面试时有几点需要注意: 1.面试题目:根据你的等级和职位的变化,入门级到大神级,广度和 ...
- 史上最全的Unity面试题(持续更新总结。。。。。。) 包含答案的Unity面试题
这个是我刚刚整理出的Unity面试题,为了帮助大家面试,同时帮助大家更好地复习Unity知识点,如果大家发现有什么错误,(包括错别字和知识点),或者发现哪里描述的不清晰,请在下面留言,我会重新更新,希 ...
- iOS 小知识点(持续更新)
1.如何通过代码设置Button title的字体大小 设置Button.titleLabel.font = [UIFont systemFontOfSize:<#(CGFloat)#> ...
- iOS开发网络资源整理-持续更新
本文记录iOS开发相关的网络社区和博客 1.objc中国 网址:http://objccn.io 简介:onevcat创建,项目的成立源于国内 Objective-C 社区对 objc.io 的翻译活 ...
- 收藏的iOS技术站点汇总(持续更新ing)
大牛博客 objc.io PS:经典,内容深而广 objc中国 NSHipster PS:非常多小细节 NSHipster 中文版 唐巧的技术博客 PS:LZ是唐巧的脑残粉- OneV's Den 王 ...
随机推荐
- 性能测试工具LoadRunner01-性能测试基础
什么是性能测试? 在一定的约束条件下(指定的软件.硬件.网络环境等)对产品按一定的性能指标进行测试,确定系统能承受的最大负载压力,解决性能瓶颈.给用户最好的体验. 性能测试流程? 什么时候开始性能测试 ...
- Collections练习之按照字符串长度进行排序
不多说,直接上干货! 代码需求 想从 [abcde, cba, aa, zzz, cba, nbaa] 变成 [aa, cba, cba, zzz, nbaa, abcde] CollectionsD ...
- JavaScript Date学习实例:获取3分钟前的时间“hhmmss”格式
上一篇博客分享了Date对象的理论知识,今天正好看到一段相关的代码,可以继续深化,通过实例加强复习Date 题目:获取3分钟前的时间,并且显示格式是hhmmss 以下是看到的代码 var time=n ...
- php防止重复提交问题总结
用户提交表单时可能因为网速的原因,或者网页被恶意刷新,致使同一条记录重复插入到数据库中,这是一个比较棘手的问题.我们可以从客户端和服务器端一起着手,设法避免同一表单的重复提交. 1.使用客户端脚本 提 ...
- fastjson的json字符串转List
1.代码 gameListStr = "[{"gameId":"1","gameName":"哈哈"},{& ...
- WinPcap抓取数据包
#WinPcap和Libpcap的最强大的特性之一,是拥有过滤数据包的引擎. 它提供了有效的方法去获取网络中的某些数据包,这也是WinPcap捕获机制中的一个组成部分. 用来过滤数据包的函数是#
- 为什么document.write()会清空原来的内容
为什么document.write()会清空原来的内容: 可能很多朋友都遇到过这样的情况,那就是使用document.write()函数向网页中写内容的时候,会把文档中的原来的内容给清空,这一点对于初 ...
- Win7无线路由Win8/8.1开启网络承载DOS命令笔记本电脑当无线路由器
以下废话,先吐槽几句 这个功能其实在Win7+系统都内置了,不要再用什么某豹.某大师.某Soft之类的开启无线网络,这些软件都是骗你们安装一些垃圾软件的. 另外吐槽 某度wifi.某数字wifi都是垃 ...
- Value cannot be null. Parameter name: source
下图主要想说.net抛错后的优先级, 错误1是根本原因,排第一位: 错误2里的方法包含了错误1,排第二位: 错误3就是整个Action了. 类似这样的错误,按照这样的顺序来解决bug,相信很受用.
- linux常用安装命令(ubuntu)
安装 net-tools 安装命令 sudo apt install net-tools 安装ssh sudo apt-get install openssh-server 查看是否安装成功 sudo ...