iOS-新东方面试总结

新东方面试总结:

一面:

自我介绍磕磕巴巴,好歹面试官没有听进去
Angular 组件生明周期
uiview的生命周期
说下你对http的了解
TCP/UDP有什么区别
Ios多线程 你了解多少
你在appApp做了哪些优化
响应式编程了解吗?有哪些技术支持响应式编程? iOS层面有哪些技术实现方案?
做项目最有挑战性的地方 怎么解决
App启动过程
有没有用flutter进行
Afnetwoking ,sdwebimage ,yymodul, fmdb源码 没说出来
怎么用jenkins进行自动化测试
用什么工作测试ui界面

二面:

自我介绍
Oc底层怎么使用的 表象考察 runtime
断点续传 多线程端点续传
Ios23种设计模式
怎么理解面向对象
怎么设计一个多线程抢票软件
怎么下载一个大的资源文件包

小总结:
对于面试的问题,思考太浅薄
对技术知识回复逻辑不够清晰
说话语速太快,没有跟面试官有什么互动
不要跟hr透喽太多生活信息 家人 周末动向

接下来我将一一进行解答:

angular生命周期:

iOS-新东方面试总结_第1张图片
image.png

angular组件的一生: 创建-> 变更->销毁

创建:
constructor:组件创建时
ngonchange: 当组件属性发生变化,系统就会回调ngonchange函数;
ngoninit: 当ngonchange第一次执行完,系统会调用ngoninit函数;

变更:
ngaftercontentviewinit: 将内容投影进组件试图后调用
ngaftercontentviewchecked: 每次完成被投影组件内容的变更检测之后调用。
ngafterviewinit:  初始化完父组件/子组件的内容后调用
ngafterviewchecked: 每次完成父组件/子组件内容变更检测后调用

销毁:
ngondestroy:当angular向一个组件发送销毁指令后

uiview的生命周期:

load函数执行前:

代码创建: viewwithnibname:函数
storyboard创建: viewinitcoder:函数
xib创建的话: aweakfrom:函数

load函数执行后:

viewdidload-> viewwillappear-> viewdidappear->viewwilldisappear->viewdiddisappear->viewunload->dealloc

-补充viewcontroller生命周期:

load-> viewdidload-> viewwillappear-> viewdidappear->viewwilldisappear->viewdiddisappear->viewunload->dealloc

说下你对http的了解

参考链接1: https://blog.csdn.net/yicixing7/article/details/79320821

概念

http是一种基于TCP/IP通信协议、位于应用的一种超文本传输控制协议。

工作过程

  1. http协议左营cs架构,http客户端通过URL向http服务器发送请求,http服务器向http客户端相应请求

http的特点

  1. 无连接协议: 每一次http服务器只允许有一个请求,相应请求后会立即关闭会话;
  2. 无状态协议: http是一种无状态协议,即每一请求完成不会进行状态保存,后续如果需要进行消息传递必须从头开始重传。

http报文

http报文分两种: 请求报文 | 相应报文

请求报文

  • 概念:

http客户端向服务度啊发送的请求内容成为请求报文

  • 请求报文组成 : 请求行+请求头+空客待扩展区域+请求数据
     请求行组成: 请求方法 url http版本
     请求头:常用的: 1.  contenttype:客户端可以接收的接收的数据类型 ; 2. Accept-Language:当前语言环境;3.Accept-Encoding:支持的压缩的格式 ; 4. http1.1 引进了 Connection: 是否保持长链接;5. Cookie: 客户 端访问的密钥

响应报文

http服务端向回复的内容成为响应报文

  • 响应报文 : http版本+状态码+状态描述信息+响应数据+空客待扩展区域+请求数据

http的弊端或者是问题:

  1. 数据明文传输不安全 2.不校验通信方的身份,容易被伪装,如抓包 3. 无法验证数据的完整性,可能已经被篡改。

TCP/UDP有什么区别

-概念

tcp: tcp是一种可连接的、可靠的、基于字节流,位于传输层的控制协议;传输过程需要直到源主机和目标地址;
udp: udp是一种无连接、不可靠、基于用户报,位于传输层的控制协议;源主机无需直到谁接收消息,谁关心谁接收

-各自的短板:
tcp: 占用cpu资源、存在延迟性

由于在连接的时候需要进行三次握手、传输过程会进行拥塞控制、流量控制,会占用cpu资源一定的资源,相对来说存在延迟性;
udp: 无法规避丢包问题
由于不关心谁接收,它会直接方法,期间不会进行拥塞控制、流量控制,那么在网路哦不好的情况下,丢包后果无法去规避。

-使用场景:

  1. 当我们需要大数据传输,并且对数据的可靠性要求比较高时我们使用tcp;
  2. 当我们需要少数据传输,实时性、效率比较高时,我们使用udp

iOS多线程 你了解多少?

多线程的设计思想来源与操作系统

iOS层面多线程的实现方案

pthread

相对于nsthread 来说相对比较底层,一纯c语言的api接口,它的底层bsd内核定义的多线程模版。它优点是相对nsthread、nsoperation来说性能会好点;相对于gcd来说性能差不多,gcd是基于mach内核线程,mach是bsd的内层,在线程的调度和执行以及对多核资源利用率都是最好;

nsthread

nsthread 是苹果早期实现多线程的技术方案
它的优点: 相对gcd 和nsoperation来说是轻量级,内部提供很多工具类,比如获取或者设置当前线程的状态很长使用,如 我们可以获取当前线程是否是主线,是否多线程,是否被取消,是否已经完成,可以将线程取消或者停止。
它的缺点: 这种方法需要管理线程的生命周期、同步、加锁问题,会导致一定的性能开销。

nsoperation

nsoperation 基于gcd 封装的,使用更加面向对象,灵活简单,它的工作原理将一个operation添加到指定的nsoperationqueue里,开发者不用管理线程的生命周期,在控制多线程执行顺序的需求方面实现简单,通过指定线程的依赖关系达成需求。
nsoperation主要适合一些大型、复杂、需要设置线程依赖关系场景里用的比较多;在小型、简单需求、不需要设置依赖关系时就是大才小用,通常之中情况使用gcd实现,代码量小、效率高,不需要我们进行线程的生命周期处理。

gcd

gcd是中央控制调度,是apple为了解决多线程不能充分多核cpu资源引进的一种新型、简单的多线程技术实现方案。它的工作路程根nsoperation一样都将一个任务放进一个串行或者并发的队列里面,然后指定其同步/异步的执行。
gcd的核心内容是队列: 串行、并发队列、主队列、全局队列; 除此之外,gcd还提供了很多使用的函数如: 栏栅函数解决异步线程按顺序执行的需求; 信号量函数: 保证线程执行顺序,同事可以保证系统共享资源的安全性,通过设置单次最大访问量实现;延迟函数: 执行多长时间后执行某个任务的场景下用;只执行一次函数:通常我们需要全局、应用整个生命周期只存在一个实例变量时用这个函数,线程安全,不用我们去管理它的生命周期;快速迭代函数: 我们遇到需要,快读执行多次代码时使用;

注意: 从pthread、nathread 、gcd再到nsoperation是从越来越庞大、使用灵活同事也会出现一些问题:

  1. gcd的主队列导致线程死锁:

  2. 任务block存在循环引用问题

等等

你在appApp做了哪些优化?怎么优化?

1. app启动时间优化

介绍app启动的流程、可以优化的过程一个是didfinishluach到第一个主界面加载的这个时间优化发难,另一个是可执行文件main启动前优化 ,两个方面的优化如下:

可执行文件main启动前优化:

我们直到程序 分类热启动和冷启动,热启动就是程序已经完成了main函数的调用,处于后台进入前台,我们主要关注冷启动,冷启动过程:
大致分为三大步:

  • apple为我们提供了dlyd动态链接器,它的主要工作就是装载mach-o文件(可执行文件+动态库),分两小步:
  1. 第一步dyld动态链接器会递归加载当前可执行文件需要的动态库;
  2. 第二部dyld完成可执行文件、动态库的装载之后,调用objc_setup函数,开始进行runtime的初始化工作
  • rumtime初始化阶段,分为4小步
  1. 调用map+images函数对可执行文件内容进行解析和处理
  2. 调用load_image函数通汇回调它内部call_objc_load函数,主要是递归加载所有的class和categary对应的load 函数;
  3. 初始化objc在runtime的数据结构,初始化类、和一些实例化对象;
  4. 加载一些c++静态文件;
  5. 开始回调main函数
  • main函数阶段
  1. 首先dyld动态链接器将可执行文件和动态库加载到内存;
  2. runtime负责加载objc定义的数据;
  3. 所有初始化工作结束后,dyld就会调用main函数;
  4. main内部调用UIApplicationMain函数一直到applicationdidfinishedlanuch函数。

冷启动过程的优化:

  1. dyld会加载动态链接库,所有我们尽可能减少使用动态链接库
  2. rumtime会一次回调每个类和分类的load方法,所有不要习惯将一些页面的初始化工作放在load函数;
  3. runtime会加载一些c++文件,所以我们尽量在开发过程中使用c++静态文件

didfinishluach到第一个主界面加载这个过程优化:

  1. 减少不必要的网络请求,将一些不必要的请求在合适的时机使用;
  2. 减少初始化响应第三方sdk,这个时候会进行sdk初始化,会消耗一定的时间;
  3. 减少类似版本版本、热加载补丁代码等

2. 内存优化

使用instrument工具里leaks进行内存泄漏分析,使用time_profile找到程序中最耗时的那一部分

3. UI重用优化

table怎么优化 : 1.重用标示 2. 预先统一设置一个固定的高度2. 缓存cell的高度 3. 缓存cell的数据

界面卡顿优化

分两种情况: 1. 主线程出现耗时操作,因为主线成是在主队列里面,祝队列只允许上一个出队列的任务完成,下一个任务才能进行。这个我们就将耗时操作放在后台线程处理就行; 2. 第二种是由于我们开发技术不精湛,不了解图像绘制原理导致,这时候我们优化需要分两步,第一步了解界面显示原理,第二部根据显示原理进行优化:
卡顿出现的原理:
当我们进行滚动时候,每秒都是可能有几十帧图片展示,它展示的逻辑时,当滚动时,系统通过runloop扑获你的滚动事件,这时系统会向app发送一个ondisplaylink函数,里面是任务让app在主线程将需要绘制的内容交给cpu,cpu收到手首先看是否层级试图如果是层级视图,cpu按视图层级迭代计算一个视图的尺寸和透明度,然后将计算好的视图以及它们的绘制要求告诉给gcp,gcp负责进行绘制,每会完一帧数据就会放到缓存区里,等待显示器去取。最终上屏。界面卡顿的原因是gcp计算视图尺寸的速度和gpu进行合成、交换、渲染的速度都跟不然当前屏幕取得速度,根据屏幕设计标准,没秒至少显示25帧数据,当要求高度高的gpu、cpu无法提供响应的能力。原因是视图层级太多、视图属性太多,导致cpu计算量太大,gpu绘制慢导致错过了交付给显示器,这时显示没有收到新的帧数据就会显示其上一帧数据,由此我们认为是卡顿。

站在cpu角度优化:

  1. 较少属视图的层次和不同高度的视图,这样1是让cpu迭代计算次数变多,2是单词计算内容变多;
  2. 尽量少使用视图的属性frame、bounds、transform,会导致cpu重新计算
  3. 尽量给视图同一设置一个高度,cpu在计算有兼容器,极速啊次数减少;

4. 动画优化

  1. 先了解iOS中界面绘制原理

使用instrument中的annimation去进行测试

5. 耗电优化

造成耗电原因: 1. cpu process 2. networking 3.locaction service 4. graphics

我们开发中常用的优化:

location 方面的优化

  1. 如果只是需要快速确定用户位置,最好用CLLocationManager的requestLocation方法。定位完成后,会自动让定位硬件断电
  2. 如果不是导航应用,尽量不要实时更新位置,定位完毕就关掉定位服务
  3. 需要后台定位时,尽量设置pausesLocationUpdatesAutomatically为YES,但是尽量做成加入用户处于一种不太可能移动的情况下 我就暂时将定位服务关闭,利用系统的陀螺仪判断用户是否有加速度,没有的就暂时关闭。

graphics

说下你对面向对象的理解

面相对象是向现实世界的延伸,每个人都有自己的理解,我通常对比面向过程去理解面向对象,发现它们两者站的高度不同最终处理事情的方式也就不一样,面向过程是站在执行者的角度思考这件事怎么一步一步去完成,而面向对象是站在组织者的角度,它考虑是让谁去做这件事比较合适。以对象为核心,以消息为驱动去实现一件事情。
面向对象的三大特点: 继承,多态,封装,我是我这样理解的: 假如我是天使,我最想让我拥有一种技能,可以造人,首先我要只要一个人需要什么思想,什么血肉,一个鼻子需要多少泥土,然后我就开始造人,但是我一个一个造人最后发现,这么愚蠢的人类哈哈,然后我想让别人给我一起去造人,但是我怕他们偷了我造人的核心技术,比如每个器官需要什么手法什么质量去捏,然后我只告诉他们,我可以造不同的人,他们把人的特征传给我就可以,我就可以造,这个过程我称它为封装,但是最后我发现,离造人数目标相差换是太远,我想到了为什么不可以,一生二,而生多这种方式,这个时候我想想到了模块,造人全部用模版去造,最后我发现效率高啦,但是质量很低,每个人都很相似,为了让每个人都有自己独特的特征,我允许每个造人的代理呢可以对造人自己稍微改造,这个过程就是多态。

谈谈你对block的理解

概念

block原身是c语言里的必报函数,oc里的block就是c语言里闭包函数的实现;

内部主要数据结构

通过clong指令( clong -rewrite-objc + 源文件) 就可以看到block的在实质,在底层它是一个结构体,主要包括6个各部: isa:block也是一个对象,oc里每个对象都有一个isa指针; flag: 是指block的标识,reserver: 保留变量用的;discribtion函数: 标示当前block的主要信息,主要信息是: size,copy指针,description指针;invoke指针: 指向block的c函数实现;varibales: 指block从外部capture 过来的变量区;

3种block以及对应的内存实现

  1. 全局block,即 NSCorcreateGlobalBlock,不会获取外部的变量 :
  2. 栈block,即 NSCorcreateStackBlock ,不会获取外部的变量,任务执行完就会被销毁掉:
  3. 堆block,即 NSCorcreateMallocBlock ,会获取外部的变量:arc情况下默认创建在栈区,当引用计数为0时,才会被销毁 ;

block在arc常见的问题:

  1. 循环引用
    解决方案: mrc: 用__block ; arc: 用__weak

你可能感兴趣的:(iOS-新东方面试总结)