2019 - iOS最新最全面试题梳理(内含框架和算法题)

本文详细梳理了iOS开发中的面试知识点,涵盖了内存管理、远程推送、Block使用、多线程、数据持久化、设计模式、网络请求安全等多个方面。内容包括Block的内存管理、iOS远程推送的工作流程、Block与函数的关系、多线程的优缺点及其管理方式(如NSThread、GCD、NSOperation)、HTTP状态码、数据持久化手段、设计模式的应用、Objective-C中的内存管理关键字如readwrite、readonly、assign、retain、copy、nonatomic的使用场景,以及Notification、KVO、Delegate与Block的区别。此外,还讨论了iOS中防止循环引用的策略、面试中常见的iOS题目和解决方案,以及如何处理过于庞大的UIViewController。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内存中的区域划分

栈区(stack):由系统自动分配和释放,存放局部变量的值,容量小速度快,有序
堆:一般由程序员分配和释放,如果不释放,则出现内存泄露。程序会回收您的内存,特点:容量大,速度慢,无序
静态存储区:全局变量(外部变量)和静态变量都存放在静态区域。当程序结束使,系统回收
常量区:存放常量的内存区域,程序结束时,系统回收
代码区:存放二进制代码的区域

iOS的远程推送

  1. 应用程序安装后提示用户是否需要接收推送,用户确认后注册消息推送。
  2. App接收到从APNS Server获取的令牌信息;
  3. APP将令牌信息发送到自己的服务器端;
  4. 当需要向用户推送消息时,自己的服务器将向苹果的推送通知服务器(Apple Push Notification Service,以下简称 APNS)发送通知;
  5. APNS 会向装有此APP的iPhone设备发送消息

理解Block的使用

Block为什么要用copy
a、block在创建的时候默认分配的内存是在栈上,而不是在堆上。这样的话其本身的作用域是属于创建时候的作用域,一旦在创建的作用域之外调用就会导致程序的崩溃。所以使用了copy将其拷贝到堆内存上。
b、block创建在栈上,而block的代码中可能会用到本地的一些变量,只有将其拷贝到堆上,才能用这些变量

Block为什么不用retain

retain这是增加了一次计数,block的内存还是在栈上,并没有存在堆上,存在栈上的block可能随时被系统回收。

为什么进入block中的对象引用计数需要自动加1

Block执行的是回调,因此block并不知道其中的对象obj创建后会在什么时候被释放,为了不在block使用obj之前,对象已经被释放,block就retain了obj一次

block和函数的关系

Block的使用很像函数指针,不过与函数最大的不同是Block可以访问函数以外、词法作用域以内的外部变量的值。
换句话说,Block不仅 实现函数的功能,还能携带函数的执行环境。

对于block的理解

block实际上是: 指向结构体的指针
编译器会将block的内部代码生成对应的函数

Block中self的循环引用

block默认创建在栈上,所以对要对其进行执行copy操作,将其拷贝到堆区,便于更好的操作对象。但是执行了copy操作之后,block中使用self,此对象会被retain一次(注意:block在堆区上时才会起到retain作用),会造成循环引用。
解决方法:
在MRC下,使用__block修饰
在ARC下,使用__unsafe_unretained\weak修饰

总结:block可以理解为指向结构体的指针,编译器会把block的代码默认生成其对应的函数。因为block创建时是在栈上,因此需要使用copy进行修饰,使其copy到堆上,方便操作其对象。因为block是回调,我们不知道其对象将会在什么时候被释放掉,所以block会自动将其对象reatin一次,使其引用计数加1,避免在使用其对象前,就被释放掉的尴尬场景。需要注意的是,在block内部使用self修饰对象,会使其reatin一次,造成循环引用,解决方案是MRC下使用__block进行修饰 ARC下使用__unsafe_unretained或者__weak修饰。

同时小编在这里提供了一些书籍和面试资料哦(点击下载

循环引用出现的三种情况

NSTimer
NSTimer对象timer作为一个对象A的属性,本意在A的dealloc中释放timer,但是timer没有停止就不会触发dealloc,然后就互相等待,造成循环引用。解决方法是显式的调用timer的关闭方法[timer invaluate],再释放A对象

Block

block代码块没有配合weak使用

Delegate

声明delegate时请用assign(MRC)或者weak(ARC)。

理解iOS中的多线程

多线程是针对于单核的CPU来设计的,目的是为了让CPU快速在多个线程之间进行调度。

多线程的优缺点
优点:提高程序的执行效率
缺点:开启线程需要一定的内存空间

同步和异步:决定了可不可以开启新的线程
同步:在当前线程中执行任务,不具备开启新线程的能力
异步:在新的线程中执行任务,具备开启新线程的能力

并行与串行:决定了任务的执行方式
并行:多个任务并发(同时)执行。类型迅雷,多个任务同时开启下载
串行:一个任务执行完毕后,再执行下一个任务。类似浏览器的一个接一个下载

iOS应用程序中都是一个主线程,也成为UI线程
那么主线程的作用就是用来更新UI,显示或者刷新界面
注意:不能将耗时的任务放在主线程上,否则会出现卡顿的现象。

NSThread

直接操作线程对象,但需要手动管理生命周期,而且经常使用这种方式来查看当前线程

GCD(Grand Central Dispatch)

底层使用的是C语言,灵活方便,可以根据系统负荷来增减线程,性能效率更好

Cocoa NSOperation

NSOperation对GCD的封装,使用起来更好理解,将任务封装为NSOpertaion,添加到NSOPerationQueue对象中。子类化NSOpertaion的设计,更具有面向对象(封装,复用)的特性。更加适合在复杂项目中使用

进程与线程

Progress和Thread,进程和线程是操作系统里的基本概念
线程与进程的区别:
线程是资源分配的最小单位,也是处理器调度的基本单位,但是进程不是
进程是资源拥有的单位,同一个进程内的线程共享进程里的资源
多进程,允许多个任务同时运行
多线程,允许单个任务分为不同的部分运行

一个对象被创建需要的三个步骤
开辟内存空间
初始化参数
返回内存地址值

常见的Http状态码有哪些?

  • 302是请求重定向。
  • 500及以上是服务器错误,如503表示服务器找不到、3840表示服务器返回无效JSON。
  • 400及以上是请求链接错误或者找不到服务器,如常见的404。
  • 200及以上是正确,如常见的是200表示请求正常。

iOS数据持久化方式

  • plist文件
  • NSKeyedArchiver归档
  • preference(偏好设置)
  • SQLite 3(第三方FMDB对其封装)
  • CoreData

一.设计模式是什么? 你知道哪些设计模式,并简要叙述?

  • 设计模式是一种编码经验,就是用比较成熟的逻辑去处理某一种类型的事情。
    1). MVC模式:Model View Control,把模型 视图 控制器 层进行解耦合编写。
    2). MVVM模式:Model View ViewModel 把模型 视图 业务逻辑 层进行解耦和编写。
    3). 单例模式:通过static关键词,声明全局变量。在整个进程运行期间只会被赋值一次。
    4). 观察者模式:KVO是典型的通知模式,观察某个属性的状态,状态发生变化时通知观察者。
    5). 委托模式:代理+协议的组合。实现1对1的反向传值操作。
    6). 工厂模式:通过一个类方法,批量的根据已有模板生产对象。

  • MVC 和 MVVM 的区别
    在MVC下,Controller基本是无法测试的,里面混杂了个各种逻辑,而且分散在不同的地方。有了MVVM我们就可以测试里面的viewModel,来验证我们的处理结果对不对(Xcode7的测试已经越来越完善了)。
    比如iOS里面有iPhone版本和iPad版本,除了交互展示不一样外,业务逻辑的model是一致的。这样,我们就可以以很小的代价去开发另一个app。
    MVVM是MVC的一个升级版,目前的MVC也可以很快的转换到MVVM这个模式。VC可以省去一大部分展示逻辑。

  • 缺点:

    • 每个VC都附带一个viewModel,类的数量*2
    • 我们把逻辑给了viewModel,那势必Model也会变得很复杂,里面的属性和方法越来越多。可能重写的方法比较多,因为涉及到一些数据的转换以及和controller之间的通信。
    • 由于数据都是从viewModel来,想想突然来了一个新人,一看代码,不知道真实的模型是谁。比如常用tableview的数据源,一般都是一个数组,如果不断的通过viewModel去取,沟通上没有那么直接。况且每封一层,意味着要写很多代码去融合他们的转换。
    • Model负责存储、定义、操作数据;
    • View用来展示给用户,并且和用户进行交互;

Controller是Model和View的协调者,Controller把Model中的数据拿过来给View使用。Controller可以直接与Model和View进行通信,而View不能与Controller直接通信。,当有数据更新时,Model也要与Controller进行通信,这个时候就要用Notification和KVO,这个方式就像发广播一样,Model发信号,Controller设置接收监听信号,当有数据更新是就发信号给Controller,Model和View不能直接通信,这样违背MVC设计原则。View与Controller通信需要利用代理协议的方式,Controller可以直接根据Model决定View的展示。View如果接受响应事件则通过delegate,target-action,block等方式告诉Controller的状态变化。Controller进行业务的处理,然后再控制View的展示。

  • 关于MVVM的优点:
  1. 方便测试
  2. 便于代码的移植
  3. 兼容MVC
  4. 类会增多
  5. viewModel会越来越庞大
  6. 调用复杂度增加

二.#import跟 #include 有什么区别,@class呢,#import<> 跟 #import””有什么区别?

  1. .#import指令是Object-C针对@include的改进版本,能确保引用的文件只会被引用一次,不会陷入递归包含的问题中;

  2. @import与@class的区别:
    .#import会链入该头文件的全部信息,包括实体变量和方法等;二@class只是告诉编译器,其后面声明的名称是类的名称,至于这些类如何定义的,暂时不用考虑。在头文件中,一般只需要知道被引用的类的名称就可以了,不需要知道其内部的实体变量和方法,所以在头文件中一般使用@class来声明这个名称是类的名称;而在实现类里面,因为会用到这个引用类的内部的实体变量和方法,所以需要使用#import类包含这个被引用类的头文件。

@class还可以解决循环包含的问题

  1. .#import<>跟#import"“的区别:
    .#import<>用来包含系统自带的文件,#import”"用来包含自定义的文件

  2. 属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?
    • readwrite:是可读可写特性,同时生成get方法和set方法的声明和实现(补充:默认属性,将生成不带额外参数的getter和setter方法(setterff只有一个参数))
    • readonly:只读特性,只会生成get方法的声明和实现;不希望属性在类外改变
    • assign:是赋值特性,set方法的实现是直接赋值,用于基本数据类型;仅设置变量时
    • retain:表示持有特性,set方法将传入参数先保留,再赋值,传入参数的retaincount会+1;
    • copy:表示拷贝特性,set方法的实现是release旧值,copy新值,用于NSString、block等类型(set方法将传入的对象复制一份;需要完全一份新的变量时使用);

• nonatomic:非原子操作,决定编译器生成的setter getter是否是原子操作,atomic表示多线程安全,一般使用nonatomic

三.frame 和 bounds 有什么不同?

  • frame指的是:该view在父view坐标系统中的位置和大小。(参照点是父view的坐标系统)
  • bounds指的是:该view在本身坐标系统中的位置和大小。(参照点是本身坐标系统)

四.Objective-C的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么?

答:Objective-C的类不可以多重继承;可以实现多个接口(协议);Category是类别;一般情况用分类好,用Category去重写类的方法,仅对本Category有效,不会影响到其他类与原有类的关系。

五.@property 的本质是什么?ivar、getter、setter 是如何生成并添加到这个类中的

@property 的本质是什么?
@property = ivar + getter + setter;
“属性” (property)有两大概念:ivar(实例变量)、getter+setter(存取方法)

“属性” (property)作为 Objective-C 的一项特性,主要的作用就在于封装对象中的数据。 Objective-C 对象通常会把其所需要的数据保存为各种实例变量。实例变量一般通过“存取方法”(access method)来访问。其中,“获取方法” (getter)用于读取变量值,而“设置方法” (setter)用于写入变量值。

六.@property中有哪些属性关键字?/ @property 后面可以有哪些修饰符?

属性可以拥有的特质分为四类:

  1. 原子性— nonatomic 特质
  2. 读/写权限—readwrite(读写)、readonly (只读)
  3. 内存管理语义—assign、strong、 weak、unsafe_unretained、copy
  4. 方法名—getter= 、setter=
  5. 不常用的:nonnull,null_resettable,nullable

七.属性关键字 readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?

答:

  1. readwrite 是可读可写特性。需要生成getter方法和setter方法。
  2. readonly 是只读特性。只会生成getter方法,不会生成setter方法,不希望属性在类外改变。
  3. assign 是赋值特性。setter方法将传入参数赋值给实例变量;仅设置变量时,assign用于基本数据类型。
  4. retain(MRC)/strong(ARC) 表示持有特性。setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1。
  5. copy 表示拷贝特性。setter方法将传入对象复制一份,需要完全一份新的变量时。
  6. nonatomic 非原子操作。决定编译器生成的setter和getter方法是否是原子操作,atomic表示多线程安全,一般使用nonatomic,效率高。

八.什么情况使用 weak 关键字,相比 assign 有什么不同?

  1. 在 ARC 中,在有可能出现循环引用的时候,往往要通过让其中一端使用 weak 来解决,比如: delegate 代理属性。
  2. 自身已经对它进行一次强引用,没有必要再强引用一次,此时也会使用 weak,自定义 IBOutlet 控件属性一般也使用 weak;当然,也可以使用strong。

IBOutlet连出来的视图属性为什么可以被设置成weak?
因为父控件的subViews数组已经对它有一个强引用。

  • 不同点:
    assign 可以用非 OC 对象,而 weak 必须用于 OC 对象。
    weak 表明该属性定义了一种“非拥有关系”。在属性所指的对象销毁时,属性值会自动清空(nil)。

九.怎么用 copy 关键字?

  • 用途:
  1. NSString、NSArray、NSDictionary 等等经常使用copy关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary;
  2. block 也经常使用 copy 关键字。
  • 说明:
    block 使用 copy 是从 MRC 遗留下来的“传统”,在 MRC 中,方法内部的 block 是在栈区的,使用 copy 可以把它放到堆区.在 ARC 中写不写都行:对于 block 使用 copy 还是 strong 效果是一样的,但写上 copy 也无伤大雅,还能时刻提醒我们:编译器自动对 block 进行了 copy 操作。如果不写 copy ,该类的调用者有可能会忘记或者根本不知道“编译器会自动对 block 进行了 copy 操作”,他们有可能会在调用之前自行拷贝属性值。这种操作多余而低效。

十.用@property声明的 NSString / NSArray / NSDictionary 经常使用 copy 关键字,为什么?如果改用strong关键字,可能造成什么问题?

答:用 @property 声明 NSString、NSArray、NSDictionary 经常使用 copy 关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,他们之间可能进行赋值操作(就是把可变的赋值给不可变的),为确保对象中的字符串值不会无意间变动,应该在设置新属性值时拷贝一份。

  1. 因为父类指针可以指向子类对象,使用 copy 的目的是为了让本对象的属性不受外界影响,使用 copy 无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本。
  2. 如果我们使用是 strong ,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值