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对象)。

指针与内存的一些相关面试

深拷贝与浅拷贝

浅拷贝就是拷贝后,并没有进行真正的复制,而是复制的对象和原对象都指向同一个地址

深拷贝是真正的复制了一份,复制的对象指向了新的地址

copy: 对于可变对象为深拷贝,对于不可变对象为浅拷贝

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,决定是否结束循环,继续执行循环外的代码。  处理事件:点击、定时器 ,mach_msg()线程休眠:内核操作

Runloop 应用,定时器不受滑动事件影响,添加至runloop的comomodel中, tracking,2种模式,

Runloop 和线程的关系:Runloop和线程是一一对应保存在全局的字典里面。线程(非主线程)刚创建时并没有Runloop,当你需要时创建,线程结束时Runloop销毁。

苹果不允许直接创建 RunLoop,你只能在线程内部获取,它提供了两个自动获取的函数:CFRunLoopGetMain() 和 CFRunLoopGetCurrent()。

Runtime原理

消息转发原理

一个用C、汇编写的运行时系统来动态得创建类和对象、进行消息传递和转发。

动态方法解析 resolveInstanceMethod  返回实现新方法

备用接收者  forwardingTargetForSelector  指定某个类接收

完整消息转发  methodSignatureForSelector 

runtime应用场景

关联对象(Objective-C Associated Objects)给分类增加属性

(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方法可能会调用多次)

性能优化以及架构

①性能优化方面:

tableView的优化->

runloop如何优化tableView

cell重用

提前计算高度

界面卡顿原理 ->

因为苹果使用双缓冲区,根据上图,当垂直信号过来之后,但是GPU还没有渲染完成,就会出现掉帧(卡顿)显现

预排版  缓存tableView cell 的高度

预解码 & 预渲染  预解码 SDWebImage 或YYImage 中有是先用

异步渲染 使用core Graphic合成位图

app 性能分析->

线程使用、 I/O操作  、 CPU使用分析、

内存

日常如何检查内存泄露

启动

SDK注册较为耗时的可以使用异步并发加载,部分二级页才用到的SDK可以采用懒加载的形式。

防止启动时有过多的串行接口操作,尽量精简。

避免启动后出现过多的耗性能操作,例如频繁读写IO,数据解码等耗时方法的调用。

3. APP启动时间应从哪些方面优化?

原生页面

编译打包

4. 如何降低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

全称Grand Central Dispatch,由C语言实现,是苹果为多核的并行运算提出的解决方案,GCD会自动利用更多的CPU内核,自动管理线程的生命周期,程序员只需要告诉GCD需要执行的任务,无需编写任何管理线程的代码。GCD也是iOS使用频率最高的多线程技术。

  NSOperation:基于GCD封装的面向对象的多线程类,相较于GCD提供了很多方便的API,使用频率较高。

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调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。

开发过程中一些需求结合多线程或者网络设计!

7. 网络的七层协议? 8. Http 和 Https 的区别?Https为什么更加安全? 9. 解释一下 三次握手 和 四次挥手? 10. Cookie和Session

数据结构算法

排序

数据结构设计

复杂度讨论

一些脑筋急转弯的算法题

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容