iOS 基础面试

  • iOS底层原理

    • 对象底层原理
      • Objective-C底层实现是C/C++代码。OC对象基于C/C++的结构体,Class为指向了objc_class类型的结构体的指针。
      • OC对象分为三种:实例对象(instance对象) ,类对象(class对象),元类对象(meta-class对象)
      • 系统会为一个NSObject对象分配最少16个字节的内存空间。一个指针变量所占用的大小(64bit占8个字节,32bit占4个字节)class_getInstanceSize和malloc_size
      • 对象的isa指针指向哪里?instance对象的isa指针指向class对象,class对象的isa指针指向meta-class对象,meta-class对象的isa指针指向基类的meta-class对象,基类自己的isa指针指向自己。
      • OC的类信息存放在哪里?成员变量的具体值存放在实例对象(instance对象);对象方法,协议,属性,成员变量信息存放在类对象(class对象);类方法信息存放在元类对象(meta-class对象)。
    • 指针与内存的一些相关面试
      • 深拷贝与浅拷贝
        • 浅拷贝就是拷贝后,并没有进行真正的复制,而是复制的对象和原对象都指向同一个地址
        • 深拷贝是真正的复制了一份,复制的对象指向了新的地址
        1. copy: 对于可变对象为深拷贝,对于不可变对象为浅拷贝
        2. mutableCopy:始终是深拷贝
      • 说一下iOS内存分区情况
        • bss段( bss segment )、数据段(data segment)、代码段(code segment/text segment)、堆(heap)、栈 (stack heap)
        • 堆是用于存放进程运行中被动态分配的内存段
        • 栈又称堆栈, 是用户存放程序临时创建的局部变量
    • Weak 弱引用
      • 什么情况使用weak关键字,相比assign有什么不同
        • assign 适用于基本数据类型如int,float,struct等值类型,不适用于引用类型。因为值类型会被放入栈中,遵循先进后出原则,由系统负责管理栈内存。而引用类型会被放入堆中,需要我们自己手动管理内存或通过ARC管理。
        • weak 适用于delegate和block等引用类型,不会导致野指针问题,也不会循环引用,非常安全。
      • Runtime 如何实现 weak 属性
        • Runtime维护了一个weak表,用于存储指向某个对象的所有weak指针。weak表其实是一个hash(哈希)表,Key是所指对象的地址,Value是weak指针的地址(这个地址的值是所指对象指针的地址)数组。
    • Block 的原理
      • block本质: block本质是一个oc对象,它内部也有个isa指针,block内部封了函数调用及函数调用的oc对象.
      • __weak和__block区别
        • 修饰类型:__weak修饰对象不能基本数据类型
        • __weak 需添加__strong 解决外部释放内部还要持有问题。__block需要手动赋值nil,非arc
        • __block对象可以在block中被重新赋值,__weak不可以;__block可以让block修改局部变量,__weak不能
      • 如何解决循环引用
        • __weak block持有一个weak 对象在释放的时候可以打破彼此强引用
        • __Blcok 将当前对象通过__block来改变存储范围,将self的引用地址存放在堆中,在block最后设置为nil
        • 传值 obj是一个参数,参数存放在栈中,block执行后就给释放掉。
      • block的修饰词为什么是copy?使用block有哪些使用注意?
        • 复制到堆上,存活时间更长久,更好的使用它,注意循环引用等.
      • block在修改NSMutableArray,需不需要添加_block?
        • 不需要,因为是使用它,不是修改它,能不用_block就不要用_block,因为会生成更多东西.
    • AutoreleasePool 原理
      • autoreleasePool应用,autoreleasePool 在何时被释放?
        • RunLoop 的释放池会等待Runloop即将进入睡眠或者即将退出的时候释放一次、手动添加的大括号外会被释放。
        • for循环中线程一直在做事情,Runloop不会进入睡眠对象无法及时释放,造成瞬时内存占用过大,如处理较大图片等。解决办法,每次循环时都手动创建一个局部释放池,及时创建,及时释放。
    • Runloop 的原理
      • Runloop其实就是一个do-while循环,每次循环一圈,都会判断一次retVal,决定是否结束循环,继续执行循环外的代码。 处理事件:点击、定时器 ,observ, block,GCD, mach_msg()线程休眠:内核操作
      • Runloop 应用,定时器不受滑动事件影响,添加至runloop的comomodel中, tracking,2种模式,
      • Runloop 和线程的关系:Runloop和线程是一一对应保存在全局的字典里面。线程(非主线程)刚创建时并没有Runloop,当你需要时创建,线程结束时Runloop销毁。
      • 苹果不允许直接创建 RunLoop,你只能在线程内部获取,它提供了两个自动获取的函数:CFRunLoopGetMain() 和 CFRunLoopGetCurrent()。
    • Runtime原理
      • 消息转发原理
        • 一个用C、汇编写的运行时系统来动态得创建类和对象、进行消息传递和转发。
        • 动态方法解析 resolveInstanceMethod 返回实现新方法
        • 备用接收者 forwardingTargetForSelector 指定某个类接收
        • 完整消息转发 methodSignatureForSelector
      • runtime应用场景
        • 关联对象(Objective-C Associated Objects)给分类增加属性, 实现set和get建立链接
        • (Method Swizzling)方法添加和替换和KVO实现
        • 消息转发(热更新)解决Bug(JSPatch)
        • 实现NSCoding的自动归档和自动解档
        • 实现字典和模型的自动转换(MJExtension)
    • 组件化
      • url-block、protocol-class(和 url-controller 类似)、target-action
      • 缺点.增加代码的冗余,组件化颗粒度越细,中间代码越多、增加项目复杂度
    • LLDB指令
      • exp打印值、修改值
      • image list命令用来查看工程中使用的库
    • load和initialize的区别
      • load是根据函数地址直接调用、initialize是通过objc_msgSend调用
      • load是runtime加载类、分类的时候调用(只会调用一次)
      • initialize是类第一次接收到消息的时候调用, 每一个类只会initialize一次(如果子类没有实现initialize方法, 会调用父类的initialize方法, 所以父类的initialize方法可能会调用多次)
    • 基础篇:iOS生命周期_lessmker的博客-CSDN博客_ios 生命周期
  • 性能优化以及架构

    • ①性能优化方面:
    • tableView的优化 ->
      • runloop如何优化tableView
      • cell重用
      • 提前计算高度
    • 界面卡顿原理 -> iOS 优化(一)-CPU和GPU
    • 因为苹果使用双缓冲区,根据上图,当垂直信号过来之后,但是GPU还没有渲染完成,就会出现掉帧(卡顿)显现
    • 预排版 缓存tableView cell 的高度
    • 预解码 & 预渲染 预解码 SDWebImage 或YYImage 中有是先用
    • 异步渲染 使用core Graphic合成位图
    • app 性能分析 ->
      • 线程使用、 I/O操作 、 CPU使用分析、
      • 内存
        • 日常如何检查内存泄露
      • 启动
      • SDK注册较为耗时的可以使用异步并发加载,部分二级页才用到的SDK可以采用懒加载的形式。
      • 防止启动时有过多的串行接口操作,尽量精简。
      • 避免启动后出现过多的耗性能操作,例如频繁读写IO,数据解码等耗时方法的调用。
        1. APP启动时间应从哪些方面优化?
      • 原生页面
      • 编译打包
          1. 如何降低APP包的大小
      • APP稳定性
    • 项目优化
    • ②架构方面:
    • 设计模式:
      • iOS有哪些常见的设计模式
      • 单例会有什么弊端?
        • 1、由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
        • 2、单例类的职责过重,在一定程度上违背了“单一职责原则”。
        • 3、滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。
      • MVVM, 针对vue为 div, model 和vue示例, 把具体视图逻辑与view拆分,适用性更强。
      • mvp
        • MVP设计模式的优点是:减低耦合,实现了Model与View 的真正分离,修改View而不影响Model。模块职责分明,层次分明,便于维护,多人开发首选。Presenter可复用,一个Presenter可以用于多个View,不用去改Presenter利于单元测试。模块分明,方便单元测试,而不用特意搭建平台,人工模擬用户操作等等耗时耗力的事情。
        • 缺点是:架构的引入在逻辑上清晰了,但代码量增加了很多,不利于小工程项目的开发和使用。
        • 由于Presenter层负责给View层提供数据,在View层需要数据较多的情况下,会导致Presenter层和View层之间的交互较为频繁,在一定程度上增加了他们的耦合度。
      • 编程中的六大设计原则?
        • 单一职责原则、开闭、接口隔离、依赖倒置、里氏替换、迪米特法则
  • 多线程、网络

    • 多线程的原理
      • 什么是多线程? 多线程就是指一个进程中可以开启多条线程,可以同时执行不同的任务。多线程可以提高程序的执行效率。多线程是一个进程中并发多个线程同时执行各自的任务。就是由单核CPU通过时间片不断的切换执行程序。
      • 分时操作系统会把CPU的时间划分为长短基本相同的时间区间(时间片),在一个时间片内,CPU只能处理一个线程中的一个任务,对于一个单核CPU来说,在不同的时间片来执行不同线程中的任务,就形成了多个任务在同时执行的“假象”。
    • 线程池:提供一组线程资源用来复用线程资源的一个池子
    • 多线程的死锁
      • 发生线程死锁的条件是,在队列里面的任务没有执行完毕的时候,在同一个队列里面添加了同步执行的任务.
    • 造成阻塞条件
      • 可能造成阻塞的条件: 锁(lock),循环引用,sleep()函数,循环执行
    • 多线程的优缺点
      • 1.优点
      • *减少应用程序的堵塞,增加程序的执行效率
      • *适当提高CPU和内存的利用率
      • *线程上的任务执行完成后,线程自动销毁(部分API可实现)
      • 3.缺点
      • *线程的开启需要占用一定的内存空间,默认是512KB/线程
      • *线程开启的越多内存占用越大,会降低程序的性能
      • *线程越多CPU在调用线程上的开销就越大
      • *程序设计更加复杂,需要考虑线程间通信,多线程的数据共享等问题
    • 多线程的并行和并发有什么区别
      • 并行是对于cpu多个核心来说的,在同一时刻有多个任务一起执行
      • 并发是对于cpu单个核心来说的。对每个线程分个不同片段来执行
    • GCD与NSOperation区别
      • 全称Grand Central Dispatch,由C语言实现,是苹果为多核的并行运算提出的解决方案,GCD会自动利用更多的CPU内核,自动管理线程的生命周期,程序员只需要告诉GCD需要执行的任务,无需编写任何管理线程的代码。GCD也是iOS使用频率最高的多线程技术。
      • NSOperation:基于GCD封装的面向对象的多线程类,相较于GCD提供了很多方便的API,使用频率较高。
        1. GCD 的核心是 C 语言写的系统服务,执行和操作简单高效,因此 NSOperation 底层也通过 GCD 实现,换个说法就是 NSOperation 是对 GCD 更高层次的抽象,这是他们之间最本质的区别。因此如果希望自定义任务,建议使用 NSOperation;
        1. 依赖关系,NSOperation 可以设置两个 NSOperation 之间的依赖,第二个任务依赖于第一个任务完成执行,GCD 无法设置依赖关系,不过可以通过dispatch_barrier_async来实现这种效果;
        1. KVO(键值对观察),NSOperation 和容易判断 Operation 当前的状态(是否执行,是否取消),对此 GCD 无法通过 KVO 进行判断;
        1. 优先级,NSOperation 可以设置自身的优先级,但是优先级高的不一定先执行,GCD 只能设置队列的优先级,无法在执行的 block 设置优先级;
        1. 继承,NSOperation 是一个抽象类,实际开发中常用的两个类是 NSInvocationOperation 和 NSBlockOperation ,同样我们可以自定义 NSOperation,GCD 执行任务可以自由组装,没有继承那么高的代码复用度;
        1. 效率,直接使用 GCD 效率确实会更高效,NSOperation 会多一点开销,但是通过 NSOperation 可以获得依赖,优先级,继承,键值对观察这些优势,相对于多的那么一点开销确实很划算,鱼和熊掌不可得兼,取舍在于开发者自己;
    • GCD执行原理
      • 串行与并行
        • Dispatch Queue。然而,存在于两种Dispatch Queue,一种是要等待上一个执行完,再执行下一个的Serial Dispatch Queue,这叫做串行队列;另一种,则是不需要上一个执行完,就能执行下一个的Concurrent Dispatch Queue,遵循FIFO(先进先出)。
      • 同步与异步
        • 串行与并行针对的是队列,而同步与异步,针对的则是线程。最大的区别在于,同步线程要阻塞当前线程,必须要等待同步线程中的任务执行完,返回以后,才能继续执行下一任务,整个过程是不会创建新线程的;而异步线程则是不用等待,会在新开启的线程中执行任务(执行主队列的任务除外,主队列的任务在主线程中执行)。
    • 锁相关原理
      • 1.自旋锁和互斥锁的特点
        • 自旋锁会忙等,所谓忙等,即在访问被锁资源时,调用者线程不会休眠,而是不停循环访问是否已经解锁,直到被锁资源释放锁。
        • 互斥锁会休眠,所谓休眠,即在访问被锁资源时,调用者线程会休眠,此时cpu可以调度其他线程工作,直到被锁资源释放锁。此时会唤醒休眠线程。
        • 自旋锁优缺点
        • 优点:因为自旋锁不会引起调用者睡眠,所以不会进行线程调度,CPU时间片轮转等耗时操作。所有如果能在很短的时间内获得锁,自旋锁的效率远高于互斥锁。
        • 缺点:自旋锁一直占用CPU,他在未获得锁的情况下,一直运行自旋,所以占用着CPU,如果不能在很短的时间内获得锁,这无疑会使CPU效率降低。自旋锁不能实现递归调用。
      • 2.原子属性和非原子属性
        • OC在定义属性时有nonatomic和atomic两种选择,默认为atomic属性
        • atomic:原子属性,为setter方法加自旋锁(即为单写多读)
        • nonatomic:非原子属性,不会为setter方法加锁
        • nonatomic和atomic的对比
        • atomic:线程安全,需要消耗大量的资源;
        • nonatomic:非线程安全,适合内存小的移动设备。
        • 注意:
        • 如非需抢占资源的属性(如购票,充值),所有属性都声明为nonatomic。
        • 尽量避免多线程抢夺同一块资源。
        • 尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力。
    • 进程和线程的区别
      • 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
      • 线程是进程的一个实体, 是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
      • 一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。
    • 网络设计
      • iOS应用架构 网络层设计方案
    • 网络的七层协议
      • 物理层、数据链路层、网络层、传输层、会话层、表示层和应用层
    • Http 和 Https 的区别?
      • 1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
      • 2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
      • 3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
      • 4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
    • TCP、UDP
      • TCP协议中包含了专门的传递保证机制,当数据接收方收到发送方传来的信息时,会自动向发送方发出确认消息;发送方只有在接收到该确认消息之后才继续传送其它信息,否则将一直等待直到收到确认信息为止。
      • UDP协议并不提供数据传送的保证机制。如果在从发送方到接收方的传递过程中出现数据包的丢失,协议本身并不能做出任何检测或提示。因此,通常人们把UDP协议称为不可靠的传输协议。
  • TCP 是面向连接的传输控制协议,而UDP 提供了无连接的数据报服务;

    • TCP 具有高可靠性,确保传输数据的正确性,不出现丢失或乱序;
    • UDP 在传输数据前不建立连接,不对数据报进行检查与修改,无须等待对方的应答,所以会出现分组丢失、重复、乱序,应用程序需要负责传输可靠性方面的所有工作;
    • UDP 具有较好的实时性,工作效率较 TCP 协议高;
    • UDP 段结构比 TCP 的段结构简单,因此网络开销也小;
    • TCP 协议可以保证接收端毫无差错地接收到发送端发出的字节流,为应用程序提供可靠的通信服务。对可靠性要求高的通信系统往往使用 TCP 传输数据。
  • Cookie和Session

  • 数据存储位置:cookie数据存放在客户的浏览器上,session数据放在服务器上。

  • 2、安全性:cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。

  • 3、服务器性能:session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。

  • 4、数据大小:单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

  • 5、信息重要程度:可以考虑将登陆信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中。

  • 数据结构算法

    • 排序
    • 数据结构设计
    • 复杂度讨论
    • 一些脑筋急转弯的算法题
  1. 链表和数组的区别是什么?插入和查询的时间复杂度分别是多少? 2. 哈希表是如何实现的?如何解决地址冲突? 3. 排序题:冒泡排序,选择排序,插入排序,快速排序(二路,三路)能写出哪些? 4. 链表题:如何检测链表中是否有环?如何删除链表中等于某个值的所有节点? 5. 数组题:如何在有序数组中找出和等于给定值的两个元素?如何合并两个有序的数组之后保持有序? 6. 二叉树题:如何反转二叉树?如何验证两个二叉树是完全相等的? 7. 数据结构的存储一般常用的有几种?各有什么特点?

https://github.com/LGBamboo/iOS-Advanced

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值