iOS面试题分析,10分钟适配

2019-09-11 16:07栏目:专项工作
TAG:

问题来源:

iOS面试

self.tableView.estimatedRowHeight = 0;self.tableView.estimatedSectionHeaderHeight = 0;self.tableView.estimatedSectionFooterHeight = 0;

Model层:
  • ###### 数据持久化存储方案有哪些?
 - plist(XML属性列表归档) - 偏好设置 - NSKeydeArchiver归档 - SQLite3(数据库,关系型数据库,不能直接存储对象,要编写一些数据库的语句,将 对象拆开存储) - Core Data(对象型的数据库,把内部环节屏蔽)
  • ###### 沙盒的目录结构是怎样的?各自一般用于什么场合?

    - Application:存放程序源文件,上架前经过数字签名,上架后不可修改- Documents:保存应⽤运行时生成的需要持久化的数据,iTunes同步设备时会备份该目 录。例如,游戏应用可将游戏存档保存在该目录- tmp:保存应⽤运行时所需的临时数据,使⽤完毕后再将相应的文件从该目录删除。应用 没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时 不会备份该目录 - Library/Caches:保存应用运行时⽣成的需要持久化的数据,iTunes同步设备时不会备份 该目录。⼀一般存储体积大、不需要备份的非重要数据 - Library/Preference:保存应用的所有偏好设置,iOS的Settings 应⽤会在该⺫录中 查找应⽤的设置信息。iTunes同步设备时会备份该目录 
    
  • ###### SQL语句问题:inner join、left join、right join的区别是什么?

 - 内连接:inner join 或者 join (显示的是左右表都有完整字段值的记录) - 左外连接:left outer join (保证左表数据的完整性)
  • ###### sqlite的优化

    • 不知道
  • ###### 网络通信用过哪些方式(100%的人说了AFNetworking...)

  • 使用苹果自带类 NSURLCollection,xcode7已经被NSURLsession替代或者使用第三方框架,AFNetworking,最好封装一下。

1.在开发的时候可以创建一个工具类,继承自我们的AFN中的请求管理者,再控制器中真正发请求的代码使用自己封装的工具类。2.这样做的优点是以后如果修改了底层依赖的框架,那么我们修改这个工具类就可以了,而不用再一个一个的去修改。3.该工具类一般提供一个单例方法,在该方法中会设置一个基本的请求路径。4.该方法通常还会提供对GET或POST请求的封装。5.在外面的时候通过该工具类来发送请求6.单例方法:(instancetype)shareNetworkTools{ static XMGNetworkTools *instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // 注意: BaseURL中一定要以/结尾 instance = [[self alloc] initWithBaseURL:[NSURL URLWithString:@"http://120.25.226.186:32812/"]]; }); return instance;}
  • ###### 如何处理多个网络请求并发的情况
 - 使用GCD 信号量 - 使用NSOperation 添加依赖
  • ###### 在网络请求中如何提高性能
 - 通过异步请求,开启子线程
  • ###### 在网络请求中如何保证安全性

  • 尽量不要操作同一块内存,可以使用加锁的方式,AFNetworking是线程安全的做了处理

设置工程中的UITableViewUICollectionViewUIScrollViewcontentInsetAdjustmentBehavior属性,如下:

网上的一些答案:

语言与基础知识:

1.内存中的栈和堆的区别是什么?那些数据在栈上,哪些在堆上?

1.栈区:由编译器自动分配释放,存放函数的参数值,局部变量等值。其操作方式类似于数据结构中的栈。2.堆区:一般由程序员分配释放,若程序员不释放,则可能会引起内存泄漏。注堆和数据结构中的堆栈不一样,其类是与链表。操作系统iOS 中应用程序使用的计算机内存不是统一分配空间,运行代码使用的空间在三个不同的内存区域,分成三个段:“text segment “,“stack segment ”,“heap segment ”。

2.#define和const定义的变量,有什么区别

define宏定义和const常变量区别:1.define是宏定义,程序在预处理阶段将用define定义的内容进行了替换。因此程序运行时,常量表中并没有用define定义的常量,系统不为它分配内存。const定义的常量,在程序运行时在常量表中,系统为它分配内存。2.define定义的常量,预处理时只是直接进行了替换。所以编译时不能进行数据类型检验。const定义的常量,在编译时进行严格的类型检验,可以避免出错。3.define定义表达式时要注意“边缘效应”,例如如下定义: #define N 2+3 //我们预想的N值是5,我们这样使用N int a = N/2; //我们预想的a的值是2.5,可实际上a的值是3.5

ag真人,3.什么情况下会出现内存的循环引用

计时器NSTimer一方面,NSTimer经常会被作为某个类的成员变量,而NSTimer初始化时要指定self为target,容易造成循环引用。 另一方面,若timer一直处于validate的状态,则其引用计数将始终大于0。记得释放blockblock在copy时都会对block内部用到的对象进行强引用或者retainCount增1。在ARC与非ARC环境下对block使用不当都会引起循环引用问题,一般表现为,某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身,简单说就是self.someBlock = ^{[self dosomething];或者self.otherVar = XXX;或者_otherVar = ...};block的这种循环引用会被编译器捕捉到并及时提醒。委托delegate在委托问题上出现循环引用问题已经是老生常谈了,本文也不再细讲,规避该问题的杀手锏也是简单到哭,一字诀:声明delegate时请用assign或者weak,千万别手贱玩一下retain或者strong,毕竟这基本逃不掉循环引用了!

4.block中的weak self,是任何时候都需要加的么?

一般表现为,某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身,简单说就是self.someBlock = ^{[self dosomething];或者self.otherVar = XXX;或者_otherVar = ...};

5.GCD的queue,main queue中执行的代码,一定是在main thread么?

不一定,如果queue是自己创建的那就在子线程,main queue中的一定是在main thread中的

6.NSOperationQueue有哪些使用方式不知道

7.NSThread中的Runloop的作用,如何使用?

RunLoop是维持一个线程一直保持运转的,是线程的基本组成成分,RunLoop中至少有一种model model中又至少有事件源 timer事件, ob 其中的一个 

8..h文件中的变量,外部可以直接访问么?(注意是变量,不是property)

不能,需要写变量的get方法 而属性已经直接给我们自动生成了

9.讲述一下runtime的概念,message send如果寻找不到相应的对象,会如何进行后续处理 ?runtime是oc的运行时机制,其中最重要的是他的消息机制,

RunTime 运行机制 :运行时候的一些机制>最重要的是消息机制>方法调用的本质就是让对象发送消息 只有对象能够发送消息,所以使用objc_开头,就算是 类方法也是类对象在发送消息 :发送消息的过程是runtime库会根据isa指针找到对应的 类 在类和父类的方法列表中找 如果在最顶类中也没有找到的话,会报方 法找不到这个错 <oc 给了我们三个拯救的机会 Method resolution :调用 + resolveClassMethod:sel + resolveInstanceMethod:sel  Fast forwarding  Normal forwarding >>一些项目中能用的技术 使用runtime交换方法:系统类 的方法功能不够;1使用继承类,重写方法 2使用runtime交换方法 :使用分类,只有分类才能给系统的类添加方法,并且通过添加的这个方法来进行方法交换,交换步骤在分类的load 方法中调用, 通过class_getClassMethod 获取方法地址, 通过 method_exchangeImplementations 交换方法注意的是 在方法交换后如果你在实现自己的方法的时候,要记住系统的方法已经被我们换掉了,所以调用我们自己的方法就代表调用系统的方法 使用runtime动态添加方法:如果一个类方法非常多,加载类到内存的时候也比较消耗资源,可以使用runtime动态添加方法来解决 <经典面试题:有没有使用performSelector,其实主要想问你有没有动态添加过方法。> :

10.TCP和UDP的区别是什么?

TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据、速度慢,建立连接需要开销较多。UDP:面向非连接、传输不可靠、用于传输少量数据、速度快。

11.MD5和Base64的区别是什么,各自场景是什么?

md5 用户密码存储 文件校验base64 公开的代码加密 url加密

12.二叉搜索树的概念,时间复杂度多少?

采用二叉树链表作为存储结构,每个左节点均小于父节点,每个右节点均大于父节点O
if (@available(iOS 11.0, *)){ _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; }

架构:

哪些类不适合使用单例模式?即使他们在周期中只会出现一次。

Notification的使用场景是什么?同步还是异步?

简单介绍一下KVC和KVO,他们都可以应用在哪些场景?

- KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知- KVC是KeyValueCoding的简称,它是一种可以直接通过字符串的名字来访问类属性的机制。而不是通过调用Setter、Getter方法访问

总的来说所有继承与Scrollview 及其子类都需要设置 contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever ,每个设置很麻烦,没关系。由于UIView及其子类都遵循UIAppearance协议,我们可以进行全局配置:

以下答案是个人理解,如果有问题欢迎指正。

APP相关:

如何添加一个自定义字体到工程中

如何制作一个静态库/动态库,他们的区别是什么?

Configuration中,debug和release的区别是什么?

简单介绍下发送系统消息的机制

// AppDelegate 进行全局设置 if (@available(iOS 11.0, *)){ [[UIScrollView appearance] setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever]; }
  • 数据持久化存储方案有哪些?
UI:

系统如何寻找到需要响应用户操作的那个Responder

逐层向上抛事件,如果到UIwindow都没有可以处理的报方法找不到异常

多屏幕尺寸的适配

要么使用xib的自动布局,autolayout或者使用屏幕宽度来设置margin也可以比较简单,还有种奇葩的是根据判断机器型号来的

UIButton的父类是什么?UILabel呢?

UIController UIView

push view controller 和 present view controller的区别

描述下tableview cell的重用机制

Tableview会去缓存池中去取绑定标示的cell,(如果不清楚缓存机制,那么就会导致数据展示混乱),自定义不等高cell是常见的tableview处理手段,比较好的做法是在cell的model中重新定义一个height的变量,在setmodel的时候我们就应该吧需要的高度计算好,然后在tableview的rowHeight方法中取出model中的height设置,还有其他的方法,如果是在rowHeight方法中计算,这种方式不可用,会是的tableView卡顿

UIView的frame和bounds的区别是什么

Frame的0,0在父控件上,而bounds是在自身上
注意:

调用系统相册时列表内容发生偏移可以参考这篇文章 iOS11 系统适配中遇到的问题UIImagePickerController

iOS 11重新调整了导航栏的元素,强制将leftButtonsrightButtons位置往屏幕中央靠了一些,在这之前通过添加一个UIBarButtonSystemItemFixedSpace 把宽度设为负数以调整按钮的边距

 //调整按钮边距// UIBarButtonItem* spaceItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];// //将宽度设为负值// spaceItem.width= -5;// [items addObject:spaceItem];

iOS 11如上设置是无效的如果你无法接受系统给设定的位置,可以试试下面的方法

#pragma mark 导航栏 添加文字按钮- (NSMutableArray<UIButton *> *)addNavigationItemWithTitles:(NSArray *)titles isLeft:isLeft target:target action:action tags:(NSArray *)tags{ NSMutableArray * items = [[NSMutableArray alloc] init]; //调整按钮位置// UIBarButtonItem* spaceItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];// //将宽度设为负值// spaceItem.width= -5;// [items addObject:spaceItem]; NSMutableArray * buttonArray = [NSMutableArray array]; NSInteger i = 0; for (NSString * title in titles) { UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom]; btn.frame = CGRectMake(0, 0, 30, 30); [btn setTitle:title forState:UIControlStateNormal]; [btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside]; btn.titleLabel.font = SYSTEMFONT; [btn setTitleColor:KWhiteColor forState:UIControlStateNormal]; btn.tag = [tags[i++] integerValue]; [btn sizeToFit]; //设置偏移 if  { [btn setContentEdgeInsets:UIEdgeInsetsMake(0, -10, 0, 10)]; }else{ [btn setContentEdgeInsets:UIEdgeInsetsMake(0, 10, 0, -10)]; } UIBarButtonItem * item = [[UIBarButtonItem alloc] initWithCustomView:btn]; [items addObject:item]; [buttonArray addObject:btn]; } if  { self.navigationItem.leftBarButtonItems = items; } else { self.navigationItem.rightBarButtonItems = items; } return buttonArray;}

此法实属障眼法,并不完美,通过设置内容偏移,让按钮视觉上看起来位置改变了,实际位置并没有发生变化,这可能导致按钮部分区域响应点击事件。若追求完美,可以试着自定义UIButton重写hitTest方法尝试改变点击区域。若有其他完美的办法请联系我更新。

在IOS11,原有的NSLocationAlwaysUsageDeion被降级为NSLocationWhenInUseUsageDeion。因此,在原来项目中使用requestAlwaysAuthorization获取定位权限,而未在plist文件中配置NSLocationAlwaysAndWhenInUseUsageDeion,系统框不会弹出。建议新旧key值都在plist里配置,反正我试下来是没有问题,唯一的区别是使用requestAlwaysAuthorization获取权限 IOS11系统弹框会把几种权限级别全部列出,供用户选择,显然更人性化了。快去更新你的info.plist

 <!-- 位置 --> <key>NSLocationUsageDescription</key> <string>获取地理位置,精准推送服务</string> <!-- 在使用期间访问位置 --> <key>NSLocationWhenInUseUsageDescription</key> <string>获取地理位置,精准推送服务</string> <!-- 始终访问位置 --> <key>NSLocationAlwaysUsageDescription</key> <string>App需要您的同意,才能始终访问位置</string> <!-- iOS 11访问位置 --> <key>NSLocationAlwaysAndWhenInUseUsageDeion</key> <string>App需要您的同意,才能始终访问位置</string>

iPhone X 变化最大的是头部 & 底部非iPhone X :StatusBar 高20pt,NavigationBar 高44pt,底部TabBar高49ptiPhone X:StatusBar 高44pt,NavigationBar 高44pt,底部TabBar高83pt所以,之前项目里写死的 ±49 ±64 都要出问题,如果你之前抽离出来使用的是宏,那问题不大,如果不是,开始搬砖吧少年。送你几个宏,来日好好撸,莫偷懒

#define kStatusBarHeight [[UIApplication sharedApplication] statusBarFrame].size.height#define kNavBarHeight 44.0//注意:请直接获取系统的tabbar高度,若没有用系统tabbar,建议判断屏幕高度;之前判断状态栏高度的方法不妥,如果正在通话状态栏会变高,导致判断异常,下面只是一个例子,请勿直接使用!#define kTabBarHeight kAppDelegate.mainTabBar.tabBar.frame.size.height#define kTopHeight (kStatusBarHeight + kNavBarHeight)

替换 64pt →kTopHeight替换 49pt →kTabBarHeight

答案在这:适配iPhone X Push过程中TabBar位置上移

这样可以解决大部分因位置导致的适配问题

最后是几道场景题,也是我最喜欢问的:

发送10个网络请求,然后再接收到所有回应之后执行后续操作,如何实现?

实现一个第三方控件,可以在任何时候出现在APP界面最上层

实现一个最简单的点击拖拽功能。

上面那个拖拽之外,如果在手放开时,需要根据速度往前滑动呢?

如何减小一个应用程序的尺寸?

如何提高一个性用程序的性能?

不同版本的APP,数据库结构变化了,如何处理?

  • revise by 简书.lovepeijun
  • 题目来至知乎:来源地址

//本人自己添加的一些Block 链式编程

请关注点❤️,持续更新……
1.SQLite32.Preference3.Plist4.Coredata5.NSKeyedArchive
iOS 超级码农交流群:538549344 技术大牛在等你来提问

以上属于臭码农原创,若有雷同属巧合,如有错误望指正,转载请标明来源和作者。by:臭码农

  • 沙盒的目录结构是怎样的?各自一般用于什么场合?

参考:

1.应用程序包:只读,不会被iTurns同步,存放应用程序本身包括资源文件和可执行文件等2.Document:会被iTurns同步,保存应用程序的数据文件,保存的是不可再生的数据3.Documents/Inbox:会被iTurns同步,保存其他应用程序请求当前当前程序打开的文件4.Library:会被iTurns同步,除了Caches,苹果建议用来存放默认设置和其他的状态信息5.Library/Caches:不会被iTurns同步,主要是缓存文件,用户使用过程中缓存的都可以保存在这个目录中,保存可再生文件,比如网络请求的数据。删除缓存文件一般会把这个文件删除6.Library/Preferences:会被iTurns同步,保存NSUserDefault的应用程序偏好配置信息文件,是一个plist文件7.tmp:不会被iTurns同步,存放临时文件,保存的是应用程序再次启动的时候不需要的文件,系统内存不足的时候就会去自动去清理他
  • SQL语句问题:inner join、left join、right join的区别是什么?
left join 返回包括左表中的所有记录和右表中联结字段相等的记录 right join 返回包括右表中的所有记录和左表中联结字段相等的记录inner join 只返回两个表中联结字段相等的行<这块不是很懂>
  • sqlite的优化
SQLite数据库文件读写操作,频繁打开关闭是很耗时和浪费资源,一些sql执行语句可以先缓存到内存中,然后依次性执行。数据排序查询语句的形式<这块不是很懂>
  • 网络通信用过哪些方式(100%的人说了AFNetworking...)
TCPHTTPHTTPSUDPSocket
  • 如何处理多个网络请求并发的情况参考:
用信号量,dispatch_semaphore_t
  • 在网络请求中如何提高性能
1.减少请求带宽-JSON和XML是常见的请求与响应提的编码方式。压缩模式的效率在很大程序上取决于待压缩的数据,通常情况下JSON更高效2.降低请求延迟3.避免网络请求-利用缓存机制,缓存的内容就不要再次请求了<不是很懂>
  • 在网络请求中如何保证安全性

参考:

1.用户post请求,不直接暴露参数信息2.重要的数据,要加密,常见的MD5,AES3.非重要的数据,要签名4.利用token校验时效性
  • 内存中的栈和堆的区别是什么?那些数据在栈上,哪些在堆上?
栈:编译器自动分配释放,存放函数的参数值,局部变量的值堆:由程序猿管理释放,存放静态变量,字符常量,资源,编译运行时的数据
  • #defineconst定义的变量,有什么区别
define:无类型校验、无分配内存、使用的话内存上多次拷贝、预处理的时候展开const:有类型校验、有分配内存、使用的话内存上一次拷贝、编译运行阶段使用
  • 什么情况下会出现内存的循环引用
1.NSTimer-他的target是self的时候,要手动停止定时器2.Block-retain circle3.delegate
  • block中的weak self,是任何时候都需要加的么?

版权声明:本文由ag真人发布于专项工作,转载请注明出处:iOS面试题分析,10分钟适配