面试总结-答案

440 阅读20分钟

Swift

  1. Swift中struct和class有什么区别?
classstruct
引用类型值类型
允许被继承不允许被继承
需要初始化不需要初始化
引用类型是指针拷贝,值类型是对象拷贝
swift中Class和Struct的区别
  1. Swift中的方法调用有哪些形式?

在 Swift 中,除了 Static Dispatch,还有 Dynamic Dispatch(动态调用,被调用的函数在 runtime 才能被确认),而 Dynamic Dispatch 实现在方式又有 V-Table Dispatch、Witness Table Dispatch 和 objc_msgSend。 用类本身的对象调用协议方法的时候,像我们上面发现的一样,该怎么派发还是怎么派发,跟正常的方法调用没有区别;但是当用协议对象调用协议方法的时,不管是结构体还是类,所有的方法都是使用一种基于 Witness Table 的形式派发
Swift 中的方法调用

  1. Swift和OC有什么区别?

来一次有侧重点的区分Swift与Objective-C

  1. 从OC向Swift迁移的时候遇到过什么问题?

  2. 怎么理解面向协议编程?

面向对象和面向协议的的最明显区别是对抽象数据的使用方式,面向对象采用的是继承,而面向协议采用的是遵守协议。在面向协议设计中,Apple建议我们更多的使用 值类型 (struct)而非 引用类型 (class)。 有一个很好的例子说明了面向协议比面向对象更符合某些业务需求。其中有飞机、汽车、自行车三种交通工具(均继承自父类交通工具);老虎、马三种动物(均继承父类自动物)
Swift 中的面向协议编程
面向协议编程与 Cocoa 的邂逅
Swift-面向协议编程-组件化
来一次有侧重点的区分Swift与Objective-C

OC语法

  1. Block是如何实现的?Block对应的数据结构是什么样子的?__block的作用是什么?它对应的数据结构又是什么样子的?

    • block本质上是一个OC对象,它内部也有isa指针,这个对象封装了函数调用地址以及函数调用环境(函数参数、返回值、捕获的外部变量等)。
    • Block 底层数据结构就是一个main_block_impl_0结构体对象,其中有block_impl__main_block_desc_0两个结构体对象成员。
    • __block用于捕获block外部变量,编译器会将 block 变量包装成一个对象(struct __Block_byref_age_0(byref:按地址传递))
  2. GCD中的Block是在堆上还是栈上?

  3. NSCoding协议是干什么用的?

NSCoding 是一个简单的协议,有两个方法: -initWithCoder:encodeWithCoder:。遵循NSCoding协议的类可以被序列化和反序列化,这样可以归档到磁盘上或分发到网络上。
NSCoding / NSKeyed​Archiver

  1. KVO的实现原理

当一个对象使用了KVO监听,iOS系统会修改这个对象的isa指针,改为指向一个全新的通过Runtime动态创建的子类,子类拥有自己的set方法实现,set方法实现内部会顺序调用willChangeValueForKey方法、原来的setter方法实现、didChangeValueForKey方法,而didChangeValueForKey方法内部又会调用监听器的observeValueForKeyPath:ofObject:change:context:监听方法。
iOS底层原理总结 - 探寻KVO本质

  1. NSOperation有哪些特性比着GCD有哪些优点,它有哪些API?

直接使用GCD效率确实会更高效,NSOperation会多一点开销,但是通过NSOperation可以获得依赖,优先级,继承,键值对观察这些优势,相对于多的那么一点开销确实很划算,鱼和熊掌不可得兼,取舍在于开发者自己 多线程NSOperation 与 GCD的区别

  1. NSNotificaiton是同步还是异步的,如果发通知时在子线程,接收在哪个线程?

同步,同步和异步都是相对于发送通知所在的线程的。发布通知的时候若在子线程中,当然了,接收方法触发的也是在子线程中
NSNotification,看完你就都懂了
NSNotification是同步还是异步?

UI

  1. 事件响应链是如何传递的?

由离用户最近的view向系统传递。initial view –> super view –> ..... –> view controller –> window –> Application –> AppDelegate
iOS 中事件的响应链和传递链
iOS 事件响应链机制

  1. 什么是异步渲染?

我们不能在非主线程将内容绘制到layer的context上,但是我们可以将需要绘制的内容绘制在一个自己创建的跑private_context上。通过CGBitmapContextCreate()可以创建一个CGCentextRef,在异步线程使用这个context进行绘制,最后通过CGBitmapContextCreateImage()创建一个CGImageRef,并在主线程设置给layer的contents,完成异步绘制。
iOS 异步绘制

  1. layoutsubviews是在什么时机调用的?

    • init初始化不会触发layoutSubviews
    • addSubview会触发layoutSubviews
    • 设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化
    • 滚动一个UIScrollView会触发layoutSubviews
    • 旋转Screen会触发父UIView上的layoutSubviews事件
    • 改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件

    layoutSubviews 调用时机

  2. 一张图片的展示经历了哪些步骤?

    • 1).从磁盘读取原始压缩的图片数据(png/jpeg格式等等)缓存到内存
    • 2).CPU解压成未压缩的图片数据 (imageBuffer)
    • 3).渲染图片(会生成frameBuffer,帧缓存,最终显示到手机屏幕)

    按照经典的MVC架构,UIImage扮演model角色,负责承载图片数据,UIImageView充当View的角色,负责渲染和展示图片。系统提供接口非常的简单,这中间隐藏了解码的过程。
    iOS图像最佳实践总结
    图片的解压缩到渲染过程

  3. 什么是离屏渲染,什么情况会导致离屏渲染?

指的是在GPU在当前屏幕缓冲区以外开辟一个缓冲区进行渲染操作.

如果要在显示屏上显示内容,我们至少需要一块与屏幕像素数据量一样大的frame buffer,作为像素数据存储区域,而这也是GPU存储渲染结果的地方。如果有时因为面临一些限制,无法把渲染结果直接写入frame buffer,而是先暂存在另外的内存区域,之后再写入frame buffer,那么这个过程被称之为离屏渲染。

当设置了以下属性时,会触发离屏渲染:

- shouldRasterize(光栅化)
- masks(遮罩)
- shadows(阴影)
- edge antialiasing(抗锯齿)
- group opacity(不透明)

关于iOS离屏渲染的深入研究
iOS-离屏渲染详解

  1. CoreAnimation这个框架的作用什么,它跟UIKit的关系是什么?

Core Animation是iOS和OS X上图形渲染和动画的基础结构,可用于为视图和应用程序的其他可视元素设置动画。Core Animation的实现逻辑是将大部分实际绘图工作交给专用图形硬件加速渲染,以实现高帧率和流畅的动画,而不会给CPU带来负担并降低应用程序的速度。

下图描述了CoreAnimation与UIKit框架的关系 Core Animation总结
Core Animation总结

引用计数

  1. ARC方案的原理是什么?它是在什么时候做的隐式添加release操作?

引用计数(Reference Count)是一个简单而有效的管理对象生命周期的方式
当我们创建一个新对象的时候,它的引用计数为 1,当有一个新的指针指向这个对象时,我们将其引用计数加 1,当某个指针不再指向这个对象是,我们将其引用计数减 1,当对象的引用计数变为 0 时,说明这个对象不再被任何指针指向了,这个时候我们就可以将对象销毁,回收内存。
ARC 的工作原理大致是这样:
当我们编译源码的时候,编译器会分析源码中每个对象的生命周期,然后基于这些对象的生命周期,来添加相应的引用计数操作代码。所以,ARC 是工作在编译期的一种技术方案
简述ARC 以及 ARC 实现的原理

在变量的作用域结束时,自动添加release函数进行释放
ARC原理探究

  1. 循环引用有哪些场景,如何避免?
    • 计时器NSTimer
    • block
    • delegate

处理方法:
定时器(NSTimer):NSTimer经常会被作为某个类的成员变量,而NSTimer初始化时要指定self为target,容易造成循环引用(self->timer->self)。 另外,若timer一直处于validate的状态,则其引用计数将始终大于0,因此在不再使用定时器以后,应该先调用invalidate方法

block的使用:block在copy时都会对block内部用到的对象进行强引用(ARC)或者retainCount增1(非ARC)。在ARC与非ARC环境下对block使用不当都会引起循环引用问题, 一般表现为,某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身,简单说就是self.someBlock = Type var{[self dosomething];或者self.otherVar = XXX;或者_otherVar = …};出现循环的原因是:self->block->self或者self->block->_ivar(成员变量)

代理(delegate):在委托问题上出现循环引用问题已经是老生常谈了,规避该问题的杀手锏也是简单到哭,一字诀:声明delegate时请用assign(MRC)或者weak(ARC),千万别手贱玩一下retain或者strong,毕竟这基本逃不掉循环引用了!

  1. 为什么当我们在使用block时外面是weak 声明一个weakSelf,还要在block内部使用strong再持有一下?

大家都会利用__weak typeof(self) weakSelf = self;来解决循环引用,这样完成之后,大家肯定会觉得这样写不完善,应该还有一个__strong,那么为什么会要用这个__strong呢?对的就是防止*“提前释放”*
iOS: Block的循环引用

  1. Autoreleasepool是实现机制是什么?它是什么时候释放内部的对象的?它内部的数据结构是什么样的?当我提到哨兵对象时,会继续问哨兵对象的作用是什么,为什么要设计它?

autorelease 的本质就是延迟调用 release 方法
单个 autoreleasepool 的运行过程可以简单地理解为 objc_autoreleasePoolPush() 、[obj release] 和 objc_autoreleasePoolPop(void *) 三个过程。
释放时间: 等到自动释放池销毁的时候才释放
iOS -- Autorelease & AutoreleasePool
内部结构:

  • 是以栈为结点通过双向链接的形式组合而成
  • 是和线程一一对应的

autoreleasepool的实现原理
浅谈 AutoreleasePool 的实现原理

  1. 哪些对象会放入到Autoreleasepool中?

alloc, copy, mutableCopy 和 new这些方法会被默认标记为 __attribute((ns_returns_retained)) ,以这些方法创建的对象,编译器在会在调用方法外围要加上内存管理代码retain/release,所以其在作用域结束的时候就会释放,而不以这些关键字开头的方法,会被默认标记为__attribute((ns_returns_not_retained)),编译器会在方法内部自动加上autorelease方法,这时创建的对象就会被注册到自动释放池中,同时其释放会延迟,等到自动释放池销毁的时候才释放。
iOS -- Autorelease & AutoreleasePool

  1. weak的实现原理是什么?当引用对象销毁是它是如何管理内部的Hash表的?(这里要参阅weak源码)

weak的原理在于底层维护了一张weak_table_t结构的hash表,key是所指对象的地址,value是weak指针的地址数组
weak 关键字的作用是弱引用,所引用对象的计数器不会加1,并在引用对象被释放的时候自动被设置为 nil
对象释放时,调用clearDeallocating函数根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entryweak表中删除,最后清理对象的记录。
iOS底层原理:weak的实现原理

weak的实现原理:
1、初始化时:runtime会调用objc_initWeak函数,初始化一个新的weak指针指向对象的地址。
2、添加引用时:objc_initWeak函数会调用 objc_storeWeak()函数, objc_storeWeak() 的作用是更新指针指向,创建对应的弱引用表。
3、释放时,调用clearDeallocating函数。clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry从weak表中删除,最后清理对象的记录。

iOS内存管理

Runtime

  1. 消息发送的流程是怎样的?

1、编译器将消息发送转化成'objct_msgSend(id , SEL, ...)',通过汇编代码 一步步处理最终会走到这个方法lookUpImpOrForward(最新的源码)
2、先判断当期那对象是否为nil,是则直接返回nil
3、在运行时去执行时,该对象(实例或类)会先通过isa指针指向对应的类(类或元 类)
4、通过SEL签名在cache_t中进行查找,有则返回
5、没有再去method_list中进行查找,有则添加到缓存中,并回调
6、没有就通过super_class找到父类,继续进行查找,一直循环遍历,直到根类NSObject
7、以上都未能找到,则进行动态解析,最后进入消息转发

Runtime 之 消息发送流程解析

  1. 关联对象时什么情况下会导致内存泄露?

循环引用

  1. 消息转发的流程是什么? Runtime 之 消息发送流程解析
    iOS 消息发送与转发详解

  2. category能否添加属性,为什么?能否添加实例变量,为什么?

能,利用Objective-C的动态特性,在运行时动态添加属性,动态绑定,达到category中添加属性的目的
为Category添加属性
不能,在Objective-C提供的runtime函数中,确实有一个class_addIvar()函数用于给类添加成员变量,这个函数只能在“构建一个类的过程中”调用。一旦完成类定义,就不能再添加成员变量了。经过编译的类在程序启动后就被runtime加载,没有机会调用addIvar。
iOS分类动态添加实例变量的思考 5. 元类的作用是什么?

  • Objective-C中的对象是对C的结构体的封装
  • 所有的对象都有一个isa指针,指向对象所属的类,类也是一个对象,类对象的isa指针指向类的元类
  • 类描述了对象的特点,如成员变量、方法列表等,元类描述了类的特点,如类的类方法等
  1. 类方法是存储到什么地方的?类属性呢?

    • 对象方法、属性、成员变量、协议信息存放在class对象中
    • 类方法存放在meta-class对象中
    • 成员变量的具体值,存放在instance对象
      iOS底层原理-OC对象的分类
  2. 讲几个runtime的应用场景

[iOS] runtime 的使用场景--实战篇
iOS runtime运行时的作用和应用场景

Runloop

  1. 讲一下对Runloop的理解?

从字面意思看就是运行循环,其实内部就是do-while循环,这个循环内部不断地处理各种任务(比 如Source,Timer,Observer)
一个线程对应一个RunLoop,主线程的RunLoop默认已经启动,子线程的RunLoop得手动启动(run方法)
RunLoop只能选择一个Mode启动,如果当前Mode中没有任何Source,Timer,Observer,那么就直接退出RunLoop
浅谈一下对runloop的理解 2. 可以用Runloop实现什么功能? - 开启一个常驻线程(让一个子线程不进入消亡状态,等待其他线程发来的消息,处理其他事件) - 在子线程中开启一个定时器 - 在子线程中进行一些长期监控 - 可以控制定时器在特定模式下运行 - 可以让某些事件(行为,任务)在特定模式下执行 - 可以添加observer监听RunLoop的状态,比如监听点击事件的处理(比如在所有点击事件前做一些处理)

浅谈一下对runloop的理解

性能优化

  1. 对TableView进行性能优化有哪些方式?
    • 最常用的就是cell的重用, 注册重用标识符
    • 避免cell的重新布局
    • 提前计算并缓存cell的属性及内容
    • 使用局部更新
    • 减少cell中控件的数量
    • 缓存行高
    • 使用不透明视图
    • cell动画和绘制
    • 减少视图的数目
    • 不要阻塞主线程
    • cell内部图片处理

iOS-UITableView性能优化

  1. Xcode的Instruments都有哪些调试的工具?
项目详情
1.Blank创建一个空的模板,你可以自定义的添加各种工具。
2.Activity Monitor可以只用这个模板,研究系统工作负载和虚拟内存大小的关系
3.Allocations将Allocations和VM跟踪器加到跟踪文档中,使用该工具可以监视内存和对象的内存分配方式和情况。
4.CocoaLayout是一种Cocoa布局工具 ,可以应用于iOS模拟器和Cocoa桌面应用,但是不能和连接的iOS设备一起使用。观察NSLayoutConstraint对象的改变,帮助我们判断什么时间什么地点的constraint是否合理
5.Core Animation将CoreAnimation加入到跟踪文档中,可以测量ios设备上每秒的CoreAnimation帧数,这可以帮助你理解内容是如何渲染到屏幕上的,(图形性能)这个模块显示程序显卡性能以及CPU使用情况。
6.CoreData将CoreData数据提取、缓存缺失和存储加入到跟踪文档中,使用这个工具可以检测应用程序中数据的存储交互。
7.Counters收集使用时间或基于事件的抽样方法的性能监控计数器(PMC)事件。

INSTRUMENTS调试工具的使用

  1. 讲一下你做过的性能优化的事情。

简历+面试题

  1. 如何检测卡顿,都有哪些方法?
    • FPS
    • RunLoop
    • 子线程Ping

iOS卡顿监测方案总结

  1. 缩小包体积有哪些方案?

减小iOS App或者静态库体积
iOS 缩小 ipa 大小

计算机相关

  1. 项目编译的流程是什么?手机上的应用程序自点击图标开始到首屏内容展示都经历了哪些步骤?

编译流程:
xcode编译过程
浅谈iOS编译过程
深入浅出iOS编译

启动流程:
iOS-APP的启动流程和生命周期 2. 对于基本数据类型,一般是存储到栈中的,它有没有可能存在堆上,什么情况下会存储到堆上? 3. 数据库中的事务是什么意思?

事务是一系列作为一个逻辑单元来执行的操作集合。它是数据库维护数据一致性的单位,它将数据库从一致状态转变为新的一致状态,说的简单一点就是,如果一组处理步骤要么全部发生要么一步也不执行,我们称该组处理步骤为一个事务。这样就保证了数据始终一致的状态,不至于破坏数据的完整性、可靠性。一个事务执行以后,DBMS会自动检查数据库中数据的一致性。
数据库中事务是什么意思 4. 使用过什么数据库(我回答的Sqlite,Realm),Realm在使用时有哪些注意事项,如何实现批量操作?
iOS Sqlite数据库的使用
juejin.cn/post/684490…

  1. LRU算法是否了解,如何实现一套LRU算法

实现常见缓存算法和LRU
Swift实现LRU缓存淘汰算法

  1. 知道哪些设计模式,怎么理解设计模式的作用?

iOS设计模式详解

  1. 如果有1000万个Int类型的数字,如何对他们排序?

如何对1千万个整数进行快速排序

  1. 设计一套数据库方案,实现类似微信的搜索关键词能快速检索出包含该字符串的聊天信息,并展示对应数量(聊天记录的数据量较大)。

数据结构与算法

  1. 什么是Hash表,什么是Hash碰撞,解决Hash碰撞有什么方法?
  2. 如何遍历二叉树?
  3. 简述下快速排序的过程,时间复杂度是多少?
  4. 有一个整数数组,如何只遍历一遍就实现让该数组奇数都在前面,偶数都在后面?
  5. 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
  6. 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。leetcode 7
  7. 有红. 黄. 蓝三种颜色的气球。在牛客王国,1个红气球+1个黄气球+1个蓝气球可以兑换一张彩票。 2个红气球+1个黄气球可以兑换1个蓝气球。 2个黄气球+1个蓝气球可以兑换1个红气球。 2个蓝气球+1个红气球可以兑换1个黄气球。 现在牛牛有a个红气球,b个黄气球, c个蓝气球,牛牛想知道自己最多可以兑换多少张彩票。

简历相关问题

  1. Lottie实现动画效果的原理是什么?

Lottie动画使用及原理分析 2. OClint实现静态分析的原理是什么,它是如何做到的?

Clang、Infer 和 OCLint ,做静态分析
OCLint静态代码检测实践

  1. MVVM和MVC有什么区别?

iOS面试题:MVVM和MVC的区别

  1. 静态库和动态库的区别是什么?

iOS动态库和静态库的区别

  1. 了解Flutter吗?它有没有使用UIKit?它是如何渲染UI的?

Flutter渲染流程简析

  1. 二进制重排的核心依据是什么?

iOS基于二进制重排的启动优化
基于二进制文件重排的解决方案 7. 如何设计一套切换主题的方案? iOS 实现快速切换主题详细教程 8. AVPlayer和IJKPlayer有什么区别?用IJKPlayer如何实现一个缓存视频列表每条视频前1s的内容? [58 同城 iOS 客户端视频的实现](toutiao.io/posts/c776q…

  1. 类似微博的短视频列表,滑动停留播放,如何实现?

[iOS]仿微博视频边下边播之封装播放器

  1. 使用python做过哪些事?如何理解脚本语言?

软技能

  1. 做过哪些工作职责之外的事情?
  2. 经历过最难的一次业务开发是什么样的,最终怎么解决的?
  3. 最近有学习什么新技术吗?有何收获?
  4. 你最擅长iOS哪方面的知识?怎么体现出来的?
  5. 常用哪些开源库,有没有研究过他们的原理?
  6. 如何保持个人成长?

流程型问题

  1. 请做下自我介绍。
  2. 你有什么问题要问我的吗?
  3. 为什么离职?
  4. 对下份工作的期望是什么样的?

原文链接