在本文中,您将找到针对高级开发人员的iOS面试问题和解答。

当您准备进行技术性的iOS面试时,重要的是要了解您可能会被问到的话题以及经验丰富的iOS开发人员的期望。这些问题被许多公司用来衡量iOS候选人的经验水平。它们涵盖了iOS开发的各个方面,旨在接触对该平台的广泛了解。毕竟,高级开发人员有望能够从头到尾交付完整的iOS产品。但是,在拥有大型iOS开发团队(可容纳25人以上)的大型公司中,也会进行专业化并且专注于对特定问题(例如网络)的深入了解。这绝不是详尽的清单,但可以帮助您为即将进行的iOS技术面试做准备。

1. 个Swift的主要特征和优缺点是什么?

这听起来像是一个初学者的问题,但事实并非如此。有时可能会要求您评估您在使用其他语言方面的经验,以及对所使用语言为您提供的语言及其优点,缺点和局限性的更广泛理解。

预期答案:

TLDR:Swift的主要功能-静态类型,协议,引用类型,值类型,可选,泛型。

Swift是一种强类型语言,它可能同时是其最大的功能,优点和缺点。静态类型允许协议,泛型和可选项存在,并有助于您进行开发。静态类型为您提供了许多编译时警告和编译错误,但提供了更高的运行时安全性和确定性(可选,var / let,泛型或具体类型等)。这是该语言提供的最大优势之一。在以下情况下,具有严格的类型安全性是最有帮助的:

  • 在构建客户端应用程序时,您需要更严格的显式性,而不是动态性和灵活性
  • 当您要在一个环境中工作时,希望限制经验不足的开发人员(初学者和初级人员)不要拥有过多的能力并自行射击
  • 当您需要重构代码时,编译器将帮助您正确正确地编写代码

所有这些恰好是iOS开发人员构建的大多数面向客户的应用程序。

同时,当您构建需要更多灵活性的内容(如构建库或框架)时,静态类型可能会过于严格。在这方面,Objective-C可能是一个更好的选择,因为它比Swift具有更好的元编程功能。(尽管可以说,此时Objective-C已过时,并且Apple平台的所有开发都应在Swift中完成)

回答注意点:

只要您能阐明每个功能所提供的功能(即协议和泛型实际上允许您在代码中执行什么操作),就可以了?但是同样,与严格类型系统相比,那些语言可以说是次要的语言功能。

2. 什么是iOS应用程序,您的代码适合哪里?

这是一个大问题,以一种或另一种形式提出,以评估您对iOS应用程序的理解,以及您编写的代码在其中以及在iOS系统中的适用位置。

预期答案:

我们可能会认为我们构建的应用程序很特别,因为它们涵盖了独特的用例。但是您典型的iOS应用程序只是一个巨大的荣耀运行循环。它等待用户输入,并被外部信号打断,例如电话,推送通知,首页手势/按钮按下以及其他应用程序生命周期事件。唯一的区别在于,它不仅是每次用户点击您的应用程序图标时都会启动的简单主循环函数,它还具有开发人员可以使用的更高级别的抽象,UIApplicationAppDelegateSceneDelegate

您编写的用于实现应用程序业务逻辑的其余代码位于该主循环通过AppDelegate或委托给我们应用程序的“触发点”中SceneDelegate。在iOS 13 AppDelegate负责接收应用程序的所有外部事件并扩展UI之前,但从iOS 13开始,所有与UI相关的逻辑都移至SceneDelegate。

而已。简单。您为应用程序编写的代码可以像方法/函数调用一样简单,也可以像VIPER体系结构一样复杂。这是你的选择。

回答注意点:

通常,开发人员将iOS应用视为他们编写的MVC代码以及实现的复杂细节,这是事实。但是,如果退后一步,放眼大局,您可以看到真正的iOS应用程序-运行循环。

3. iOS中的内存管理如何处理?

内存管理在任何应用程序中都非常重要,尤其是在具有内存以及其他硬件和系统约束的iOS应用程序中。此问题涉及ARC,MRC,引用类型和值类型。

预期答案:

Swift使用自动引用计数(ARC)。从概念上讲,这在Swift中与在Objective-C中是相同的。ARC会跟踪对类实例的强引用,并在您将类实例(引用类型)的实例分配或取消分配给常量,属性和变量时相应地增加或减少其引用计数。它释放由引用计数降至零的对象使用的内存。ARC不会增加或减少值类型的引用计数,因为在分配值时,它们会被复制。默认情况下,如果没有另外指定,则所有引用都是强引用。

回答注意点:

这是每个iOS开发人员都必须知道的!由于iOS应用程序中的内存管理不善,内存泄漏和应用程序崩溃非常普遍。

4. 什么是MVC?

哦,老MVC不错。这是Apple不断推向iOS开发人员的基本设计模式。无论您是申请高级职位还是初级职位,每位面试官都极有可能会问这个问题。不过,您作为大四学生的答案会有所不同。

预期答案:

MVC代表模型视图控制器。这是Apple选择作为iOS应用程序开发的主要方法的软件设计模式。模型代表应用程序数据;视图在屏幕上绘制事物;控制器管理模型和视图之间的数据流。模型和视图从不直接相互通信,而依赖于控制器来协调通信。苹果公司从最初的SmallTalk实现中将这种设计模式转变为其他形式 。

iOS应用程序中每个Apple MVC层的典型表示为:

MVC是一种很棒的通用设计模式,但是作为高级开发人员,您应该知道它只是视图层的设计模式,单独使用它会限制您的体系结构,并经常导致臭名昭著的“大型视图控制器”问题。

Massive View Controller是代码库的状态,在该状态下,大量逻辑和职责被推到不属于该代码库的View Controller中。这种做***使您的代码僵化、,肿且难以更改。还有其他设计模式可以帮助您解决这一问题,例如 MVVMMVPCoordinator。还有一些架构,例如VIPERRIB是专门为扩展iOS代码和避免Massive View Controller问题而设计的。

即使Apple一直告诉我们MVC就是一切,但请多了解并坚持SOLID原则。

回答注意点:

您绝对必须知道MVC是什么,因为它是任何iOS开发的基础。但是,请探索替代产品和附加产品,例如MVVM,MVP,VIPER和RIB。

5. 您对单身人士了解多少?您将在哪里使用哪一个?

Singleton是许多OOP语言中常用的设计模式,可可认为它是“可可核心能力”之一。面试中会出现这个问题,以评估您对单身人士的体验,或者了解您是否具有iOS以外的背景知识。

预期答案:

Singleton是一个类,无论您请求多少次,它都只返回一个实例。

有时将单例视为反模式。使用单例有多个缺点。主要参数是全局状态,对象生命周期和依赖项注入。当您只有某个事物的一个实例时,很想直接在任何地方引用和使用它,而不是将其注入到对象中。这导致代码中具体实现的不必要耦合,而不是使用接口抽象。

“方便”单例的另一个恶意副作用是全局状态。通常,单例启用全局状态共享,并扮演每个对象用来存储状态的“公共包”的角色。当这种不受控制的状态被某人覆盖或删除时,这将导致不可预测的结果,错误或崩溃。

回答注意点:

即使在某些语言和平台中,单例被认为是不错的选择,但实际上它们是一种反模式,应不惜一切代价避免这种情况。

6. 代表和KVO有什么区别?

有了这个问题,面试官正在评估您对iOS中使用的不同消息传递模式的了解。

预期答案:

两者都是在对象之间建立关系的方式。委托是一对一关系,其中一个对象实现委托协议。另一个使用协议定义的方法向其发送消息。KVO是一种多对多关系,其中一个对象广播一条消息,而一个或多个其他对象侦听该消息并做出反应。KVO不依赖协议。KVO是反应式编程(RxSwiftReactiveCocoa等)的 第一步和基本步骤

回答注意点:

经验丰富的开发人员应该知道两者之间的差异,以及在哪里可以相互使用。

7. iOS应用程序通常使用哪些设计模式?

除初级职位外,所有级别的面试中都会出现这个问题。使用iOS平台,开发人员应该熟悉iOS上常用的技术,体系结构和设计模式。

预期答案:

构建iOS应用程序时,通常使用的典型模式是Apple在其Cocoa,Cocoa Touch,Objective-C和Swift文档中所倡导的模式。这些是每个iOS开发人员都可以学习的模式。苹果将​​它们称为“核心竞争力”设计模式。它们包括MVCSingletonDelegateObserver

回答注意点:

当面试官(以一种或另一种形式)问这个问题时,他正在寻找MVC以外的东西。因为MVC是首选设计模式,所以期望每个iOS开发人员都知道这一点。但是,他们想从您那里得到的消息是我们通常开箱即用的其他信息。

8. 除了您知道的常见可可图案以外,还有哪些设计图案?

这是一个高级问题,当您面试高级职位或建筑师职位时,面试官会提出这个问题。期望的是,您将了解iOS应用程序中使用的更实用的设计模式,而不仅仅是前面问题中涵盖的基本设计模式。准备召回一堆“ 四人帮”模式和其他类似模式。

设计模式本身就是一个巨大的话题(在我的书中有更好的介绍),因此在这里,我将仅总结我在iOS代码库中常见的模式。

预期答案:

除了常用的MVC,Singleton,Delegate和Observer模式外,还有许多其他完全适用于iOS应用程序的模式:Factory MethodAdapterDecoratorCommandTemplate

Factory Method用于替换类构造函数,以抽象和隐藏对象的初始化,以便可以在运行时确定类型,并隐藏和包含switch/if确定要实例化的对象类型的语句。

适配器是一种设计模式,顾名思义,它可以帮助您使一个对象的界面适应另一个对象的界面。当您尝试适应无法更改为代码的第三方代码时,或者当您需要使用不方便或不兼容的API时,通常会使用此模式。

装饰器是另一个类的包装,可以增强其功能。它包装了您要装饰的东西,实现了它的接口,并将发送给它的消息委托给基础对象,或者增强了它们或提供了自己的实现。

命令是一种设计模式,您将在其中实现一个对象,该对象表示您想要执行的操作。该操作可以具有其自己的状态和逻辑来执行它所执行的任务。这种设计模式的主要优点是,您可以向用户隐藏操作的内部实现,可以向其添加撤消/重做功能,并且可以在以后的某个时间点(或根本不执行)而不是执行操作。立即创建操作的位置。

模板是一种设计模式,其主要概念是拥有一个基类,该基类概述了需要完成的算法。基类有一些抽象方法,这些方法必须由其具体子类实现。这些方法称为挂钩方法。Template Method类的用户只能使用实现算法步骤的基类进行交互;这些步骤的具体实现由子类提供。

回答注意点:

当您刚从iOS平台开始时,仅坚持使用MVC,Singleton,Delegate和Observer模式是很好的,但是对于高级功能,您需要更深入地研究更抽象和更高级的内容,例如“四个OOP设计模式的帮派”。它们非常有用,可以使您的代码库更加灵活和可维护。

9. 解释并显示SOLID原理示例?

SOLID原则相对较旧,但适用于任何语言的任何OOP代码库的概念都非常有用。观看Bob叔叔关于该主题的一些演讲,以充分理解其背后的历史。

在YouTube上:Bob Martin面向对象和敏捷设计的SOLID原理

不幸的是,SOLID原则本身就是一个巨大的话题(在我的书中也有更好的介绍),因此在这里我仅对它们进行概述。

预期答案:

SOLID代表单一责任原则开放/封闭原则Liskov替代原则接口隔离原则依赖倒置原则。这些原则相互融合并相互支持,是您可以为代码采用的最佳常规设计方法之一。让我们逐一介绍一下。

单一责任原则(SRP)是该小组最重要的原则。它指出,每个模块都应该只有一个责任和变更理由。SRP从小的具体情况开始,例如类和/或对象仅具有一个目的,并且仅用于一件事。

打开/关闭原则(OCP)指出,您的模块应打开以进行扩展,但应关闭以进行修改。这是听起来很容易的事情之一,但是当您开始思考它的含义时,很难把头缠起来。实际上,这意味着在编写代码时,您应该能够通过使用接口,抽象和依赖注入实现对象,从而通过继承,多态和组合来扩展对象的行为。

Liskov替换原理(LSP)指出,程序中的对象应该可以用其子类型的实例替换,而不会改变该程序的正确性。这意味着当您从类或抽象类继承或实现接口(协议)时,无论使用了您的子类接口或类,您的对象都应该是可替换和可注入的。这项原则通常被称为按合同设计,或者在Swift社区中最近被称为面向协议的编程。该原则的主要信息是,您不应违反从子类承诺继承的接口要履行的约定,并且通过子类化,这些子类可以在以前使用超类的任何地方使用。

接口隔离原理(ISP)表示,许多特定于客户端的接口比一种通用接口要好。它还指出,不应强迫任何客户端依赖和实现不使用的方法。这就是说,当您创建类要实现的接口(协议)时,您应该努力并依赖于抽象性而不是特异性,但是直到浪费掉您必须实现一堆新类的方法时,这种浪费才成为现实。甚至使用。

依赖倒置原则(DIP)指出:“依赖抽象,而不依赖具体。” 展示此原理的最佳示例是依赖注入(DI)技术。使用依赖注入技术,在创建对象时,您将在其初始化或配置时提供并注入其所有依赖关系,而不是让对象自行创建或获取/查找其依赖关系。

回答注意点:

SOLID原则是良好的OOP设计的基础。应用这些原则将帮助您构建更好,更可维护的软件。如果您要申请iOS的高级职位,强烈建议您精通它们。

10. 您在iOS上实现存储和持久性有哪些选择?

采访者会问这个问题,以了解您对可用于在iOS上存储和保存数据的工具和方式的理解。

预期答案:

通常,有以下几种按简单到复杂的顺序存储数据的方式:

  • 内存中的数组,字典,集合和其他数据结构
  • NSUserDefaults /钥匙串
  • 文件/磁盘存储
  • 核心数据,领域
  • SQLite的

内存中的数组,字典,集合和其他数据结构非常适合用于中间存储数据或无需持久存储数据。

NSUserDefaults / Keychain是简单的键值存储。一个是不安全的,另一个是安全的。

文件/磁盘存储是一种使用NSFileManager向磁盘写入数据或从磁盘写入数据的方法。

核心数据领域是简化数据库工作的框架。

SQLite是一个关系数据库,当您需要实现复杂的查询机制而Core Data或Realm不会削减它时,它是一个很好的选择。

回答注意点:

您应该知道在iOS上存储数据的不同方式以及它们的优缺点。不要将自己仅限于您习惯的一种解决方案(例如,Core Data)。知道何时一个比另一个更可取。

11. iOS上的网络和HTTP有哪些可用选项?

如今,每个应用程序都使用网络来从API和其他外部资源获取数据。如果未连接到互联网,许多应用程序将无用。每个iOS开发人员都应该知道他们可以使用什么来构建其应用程序的服务/网络层。

预期答案:

在iOS中,有几种实现HTTP网络的选项。您可以使用旧的NSURLSession,但是除非您对其进行足够好的抽象,否则使用它可能会令人生畏。另一种选择是在其周围使用包装器库。iOS上最受欢迎的解决方案是Alamofire

通常,如果您的团队很小,则可能需要依靠开源解决方案,例如Alamofire,它可以为您抽象出许多样板代码。但是如果您的团队很大,并且可以节省资源,那么您将希望更好地控制数据与服务器之间的传递以及使用NSURLSession自己实现数据的方式。

高级开发人员应记住,在iOS应用程序中构建网络层不仅意味着处理HTTP请求,而且意味着实现代码所涉及的整套任务:HTTP网络,数据序列化和数据映射。

回答注意点:

如今,NSURLSession和Codable是用于在iOS上联网的两种主要技术,但了解Alamofire之类的开源解决方案也是有益的。

12. 如何以及何时在iOS上序列化和映射数据?

生成iOS应用程序时,数据序列化是一项常见任务。采访者会问这个问题,以了解您是否认识到合适的位置,并知道在处理数据时(无论是网络数据还是存储数据)所需的任务。

预期答案:

有两种最常见的情况,您需要在iOS应用程序中序列化和映射数据:在网络层中接收或发送数据(例如JSON或XML或其他东西),以及在存储层中持久化或检索模型(NSData) ,NSManagedObject)。

每次您从后端API收到JSON或XML或任何其他响应类型的响应时,您很可能会以JSON或二进制或其他“不便”格式获取它。要处理收到的数据,您需要做的第一件事就是将其序列化为您的应用可以理解的格式。最简单和最基本的级别是字典或包含该响应中其他字典,数组和基元的对象数组。NSJSONSerialization会解决这个问题。下一步是将数据映射到应用程序的域模型中。这些将是应用程序其余部分要使用的模型对象或结构。您可以手动执行此操作,也可以使用CodableApple提供的协议,也可以使用Mantle或SwiftyJSON之类的库。数据流和序列化/映射为:binary data->json- > NSDictionary/NSArray- > your domain model objects

同样,在存储层中,您将需要序列化数据并将其与自定义域模型对象之间的数据映射到存储所能理解的格式。用于读取数据的“映射”链:db-> raw data format-> custom domain models; 编写:custom domain models-> raw data format-> db。您可以在此处使用NSManagedObject或NSCoding或Codable协议来实现。

回答注意点:

这里的主要危险信号是没有意识到与iOS应用程序的网络和存储层一起使用时,需要进行这些数据操作。事情不会“自动地”发生,并且与原始的NSDictionaries合作也不是适当和可维护的。

13. 在iOS上布置UI有哪些选项?

当您需要解决iOS上不同的UI挑战时,了解在屏幕上布置内容的选项至关重要。该问题有助于评估您有关如何在屏幕上放置和对齐视图的知识。在回答这个问题时,您至少应提及CGRect,Fframes和AutoLayout和SwiftUI,但最好提及其他选项,例如Texture(ASDK),ComponentKit以及iOS上的其他Flexbox和React实现。

预期答案:

旧的CGRect框架和自动版式是在屏幕上显示视图的理想选择。框架以及自动调整大小的蒙版在iOS 6之前就已使用过,如今已不再是首选。框架太容易出错并且难以使用,因为很难为各种设备计算精确的坐标和视图大小。

从iOS 6开始,我们有了AutoLayout,这是当今流行的解决方案,也是Apple首选的解决方案。AutoLayout是一项技术,可帮助您以声明性的方式定义视图之间的关系(称为约束),使框架可以计算出精确的框架和UI元素的位置。

在iOS 13中,Apple引入了一种新的视图布局方法-SwiftUI,这是一种声明性方法,它支持通过Combine进行FRP(函数式反应性编程)数据绑定。FRP和声明性UI并不是新概念,但是SwiftUI和Combine是Apple支持的新框架。SwiftUI的声明性质使您可以非常简洁地声明UI元素,然后通过数据绑定声明UI的哪些部分(例如文本标签)来更新什么数据模型发生了变化。实际上,它允许您使用RxSwift进行以前但现在可以使用Apple框架进行的操作。

还有其他布局视图的选项,例如ASDK(纹理),ComponentKit和LayoutKit,其中一些或多或少受React启发,而其他解决方案则不同。在某些情况下,例如,当您需要构建高度动态和快速的表视图和集合视图时,这些替代方法非常有用。AutoLayout并非总是那么完美,知道其他选项总是一件好事。

注意:我们将看到SwiftUI将来如何证明自己能够解决复杂的UI问题和复杂的异步UI布局问题,在撰写本文时,这是一项非常新的技术。

回答注意点:

至少没有提到自动版式以及框架很难正确放置的事实对于您的面试官来说是一个危险信号。如今,除非有必要,否则没有理智的人会进行CGRect框架计算(例如,当您进行疯狂的绘制时)。

它不会是一个危险信号,但是要提到SwiftUI,这很可能将成为苹果在未来几年内对我们的推动。

14. 如何优化动态大小的表或集合视图的滚动性能?

与UITableView问题一起,访谈中的重要问题之一是滚动性能。

预期答案:

滚动性能是UITableViews的一个大问题,而且通常很难正确实现。主要困难是像元高度的计算。当用户滚动时,每个下一个单元格需要先计算其内容,然后计算高度,然后才能显示它。如果您手动进行“框架”视图布局,则性能会更高,但面临的挑战是正确计算高度和尺寸。如果使用自动版式,那么面临的挑战就是正确设置所有约束。但是,即使AutoLayout本身也可能需要一些时间来计算单元格高度,并且滚动性能会受到影响。

滚动性能问题的潜在解决方案可能是:

  • 自己计算像元高度
  • 保留一个您填充了内容的原型单元,并使用它来计算单元的高度

或者,您可以采用一种完全激进的方法,即使用诸如ASDK(纹理)之类的不同技术。ASDK(纹理)是专门为具有动态内容大小的列表视图制作的,并且经过优化以计算后台线程中的单元格高度,从而使其具有超强的性能。

15. 您将如何在iOS上执行异步任务?

如今,多线程是任何客户端,面向用户应用程序的重要组成部分。该问题可以在网络环境中提出,也可以作为有关GCD或异步开发的独立问题提出。

预期答案:

在iOS上,如今,异步任务的首选解决方案是NSOperations和GCD块。Grand Central Dispatch是一项可以与多个后台队列一起使用的技术,该后台队列又可以找出哪个后台线程来处理工作。最主要的是,它是从您那里抽象出来的,因此您不必担心它。NSOperation是GCD之上的OOP抽象,它允许您执行更复杂的异步操作,但是使用NSOperation可以实现的一切都可以与GCD一起实现。许多可可框架在后台使用GCD和/或NSOperation(例如,NSURLSession)。

使用第三方库的帮助还有其他处理异步工作的方法。最著名的是Promises(PromiseKit),RxSwift和ReactiveCocoa。RxSwift和ReactiveCocoa特别擅长建模时间和工作的异步特性,这些工作需要在后台完成并在线程之间进行协调。

回答注意点:

每个iOS开发人员应了解的有关异步工作的基础知识是GCD和NSOperations。RxSwift和Promises是高级概念,但是高级开发人员应该了解它们。

16. 您如何管理依赖关系?

依赖管理是每个iOS项目中的重要任务。这个问题可以衡量您对问题及其解决方案的理解。

预期答案:

几年前,我们在iOS上还没有任何依赖项管理器,因此不得不将第三方代码复制粘贴和拖放到我们的项目中或使用Git子模块。随着我们的代码库和依赖关系的增长,这些方法变得难以管理。

如今,我们还有其他依赖项管理器可供选择:CocoaPods,Carthage和Swift Package Manager。

到目前为止,最主要和最强大的功能是CocoaPods。我本着Ruby Bundler宝石的精神建造的,本身就是Ruby宝石。它的工作方式是安装gem,Podfile在项目的根目录中创建,声明要使用的pod(库)并运行pod install。而已。

使用Carthage,您可以创建一个名为的依赖项声明文件,Cartfile但与Cocoapods不同,您需要进行Xcode项目设置才能使其工作。

Swift软件包管理器是任何Swift项目依赖管理的未来,但它仅支持库和框架,并且不能用于生成iOS目标,尽管iOS目标可以依赖于SPM构建的模块。

回答注意点:

每个iOS开发人员都应该理解,当多个库可能依赖于另一个库的两个不同版本时,将第三方库复制粘贴到您的代码库中会导致维护的噩梦,从而导致不匹配以及编译和运行时问题。

17. 您如何在iOS上调试和分析代码?

没有人编写完美的代码,开发人员需要调试其代码和配置文件应用程序,以提高性能和内存泄漏。

预期答案:

iOS应用程序中 总是存在NSLogging和printing。您可以使用Xcode设置断点。为了实现单个代码段的性能,可以使用XCTest的measureBlock。

您可以使用进行更高级的调试和分析Instruments。Instruments是一种性能分析工具,可帮助您分析应用程序并在运行时查找内存泄漏和性能问题。

18. 您有TDD经验吗?您如何在iOS上进行单元和UI测试?

尽管从历史上看,iOS社区在TDD上并不占优势,但由于工具的改进和来自其他社区(如Ruby)的影响(早在TDD之前就加入了TDD),它现在变得越来越流行。

预期答案:

TDD是一种技术和学科,在编写使测试通过的生产代码之前,您首先要编写失败的测试。测试推动了生产代码的实现和设计,从而帮助您仅编写通过测试实现所必需的代码,没有更多,更少。一开始的纪律可能令人望而生畏,您不会立即看到这种方法的收益,但是如果坚持下去,从长远来看,它可以帮助您更快地采取行动。它在帮助您进行重构和代码更改方面特别有效,因为在任何给定的时间,您都可以通过测试的安全网来告诉您是否发生了故障,或者在进行更改时一切仍然正常。

最近,Apple对XCTest框架进行了改进,使我们的测试变得更加容易。他们还通过Xcode(XCUITest)中的UI测试进行了很多改进,因此现在我们有了一个不错的程序化界面来与我们的应用程序交互并查询我们在屏幕上看到的内容。或者,您可以使用KIF,iOSSnapshotTestCase,EarlGrey等框架。

关于单元测试,也有几种选择,但是两个最受欢迎的选择是XCTest和Quick and Nimble。

XCTest是Apple构建的类似于xUnit的测试框架。这是他们建议使用的方法,它与Xcode的集成最佳。

Quick是一种类似于RSpec的BDD框架,可帮助您用行为而不是“测试”来描述规格/测试。RSpec的粉丝非常喜欢。

Nimble是一个匹配程序库,可以与XCTest或Quick一起使用,以断言测试/规范中的期望。

回答注意点:

越来越多的团队和公司采用TDD,它已成为iOS开发过程中至关重要的一部分。如果您不想被抛在后面,请继续学习并学习如何测试驱动您的代码。

19. 模拟,存根和假货之间有何不同?

随着测试成为iOS世界中越来越重要的实践,重要的是要在编写测试时知道自己在做什么。测试代码与应用程序代码一样重要。这个问题可以帮助您了解对用于单元测试的对象的测试术语的理解。

预期答案:

不同的人可以通过多种方式对测试对象进行调用和分类,但是最常见的测试对象可以通过以下方式进行分类:伪造,存根和模拟。

伪造品是任何种类的模拟,伪造,存根,双精度等的通用总称。它们自己通常没有实现,仅满足它们所替代类型的接口API要求。

存根是伪造品,它们执行一些有意义的工作,这些工作对于测试所涉及的对象进行操作是必需的,但仅用于其他用途。它们不能代替实际的生产对象,但可以返回存根值。无法断言它们。

cks是可以断言的假货。伪造用来代替伪造的其他对象,但是它们本身会记录一些数据,例如方法调用的数量或传递给您的测试以供以后声明的变量。

回答注意点:

许多开发人员将任何测试对象称为模拟都是错误的,但是测试对象有一个特定的独特命名法,用于指示每个对象的用途。作为高级开发人员,您不仅要编写测试,还应该知道如何维护测试以及应用程序代码库。

20. 您是否编写评论和/或配对程序的代码?

即使那里有许多由独立开发人员构建的应用程序,但应用程序执行的复杂性仍在不断增加,要求由一组开发人员来进行处理。团队合作在代码维护,协作和知识共享方面提出了不同的挑战。

预期答案:

结对编程是一种实践,其中两个开发人员在同一台计算机上共同完成同一任务(希望不会共享相同的屏幕和键盘,而是拥有两组自己的屏幕和键盘)。目的是在代码产生的地方促进协作,讨论,代码审阅和质量检查。这个过程使知识转移和架构讨论成为日常的日常事务,从而防止人们在代码的某些部分孤立或成为“专家”(当这个人离开或生病时会发生什么?)。这也提高了代码质量,因为两组眼睛在编写代码时都在看代码。这个过程同时发生在两个开发人员之间,有时也称为同步。

结对编程并不适合每个人,如果人们的个性不匹配,结对编程可能会很累人。但是,它仍然是软件开发中最有效的协作技术之一。

代码审查是协作和知识转移的类似过程,但是与结对编程不同,它不会同时发生,因此是异步的。通过代码审查,在开发人员编写了一段代码或功能之后,团队中的其他人就会对其进行查看。审阅者检查代码是否有意义,并建议进行更改和重构以进行改进。这就打开了有关该代码的在线或离线讨论,这很棒。这样可以将有关该代码段的知识转移给其他队友,并帮助及早发现错误和设计异味。

代码审查是一种较少参与的协作类型,可以实现与结对编程相同的结果。这也是一种换位思考的练习,您可以在此向他人提供有关他们工作的反馈。

21. 什么是FRP(功能性反应式编程)及其在iOS平台中的位置?

函数式反应式编程(FRP)是iOS / Swift,JavaScript和其他开发者社区中的新热点。除了它实际上不是那么新。无论是Swift功能还是更大的体系结构和概念性讨论问题,都可以期待这个问题。

预期答案:

功能响应式编程(FRP)是一种声明式编程范例,它结合了功能编程和响应式(异步数据流编程)范例。这是一种声明式的编程风格,您可以声明代码的工作方式,而不是声明代码的工作方式。FRP的反应性组件使我们能够引入和描述时间的概念,这在纯函数式编程中很难使用。FRP通常可以帮助我们处理用户输入和iOS应用程序的异步特性;用户输入发生在某个时间点,联网将在将来的某个时间结束,等等。

FP和FRP依赖于将函数作为参数并返回其他函数的高阶函数(例如map,reduce和filter),这使它们具有很高的可组合性。

Swift没有对FRP的本机支持,但是有两个出色的库实现了功能性反应式编程概念并使它们易于我们使用:ReactiveCocoa和RxSwift。

在iOS 13中,苹果公司还宣布了iOS内置的名为F合并的新FRP框架。组合实际上是类似于RxSwift的FRP框架实现。它具有两个优点:它与SwiftUI集成在一起,从而可以将UI元素绑定到数据更改,并且它是Apple内置和支持的。缺点是:它不如RxSwift成熟,Apple对其进行更改和添加将很慢。

回答注意点:

FRP在iOS应用程序中正变得越来越普遍,并且将在Apple官方对Combine编程范例的官方支持下使用更多FRP。iOS开发人员应该开始拥抱它。

22. 您知道哪种iOS架构可扩展吗?

可能会问这个问题,采访一家拥有大型iOS开发团队的大公司。iOS应用程序变得越来越复杂,MVC设计模式不能像大型应用程序架构那样很好。对于前辈,主管,建筑师等,这是一个非常高级的问题。

预期答案:

MVC,MVVM,MVP和类似的设计模式很棒,并且在彼此上都是一个改进,但是对于10人或20人以上的团队,它们仍然无法很好地扩展。如果您超出了团队规模,则需要使用更通用且可扩展的体系结构方法。有一种概念性方法,称为“干净架构”。

清洁体系结构是用于规模化的概念性应用程序体系结构,可以简单地描述为“洋葱分层体系结构”。主要思想是使依赖关系向内指向您的域逻辑和域模型,并使其他所有内容都是可插拔的和可选的(存储数据,呈现ui,接收或发送网络请求的方式等)。对于拥有100多个开发人员的大型团队而言,此架构的扩展性特别好。

iOS上有两种“清洁体系结构”的具体实现:VIPER和RIB。

毒蛇代表View,Interactor,Presenter,Entity和Router。这些是该体系结构的基石。在这种架构中,一切都始于路由器,并以视图结束。每个VIPER堆栈(意味着一组View,Interactor,Presenter,Entity和Router)都是应用程序的一个屏幕或一个逻辑UI部分。要导航和使用VIPER堆栈,请实例化其路由器,然后要求其创建其视图控制器。路由器创建视图控制器,格式化视图数据并接收视图用户输入的相应演示者,保存业务逻辑并与演示者进行通信的交互器,以及使交互器工作所需的实体。然后,VC拥有演示者,演示者拥有交互者,而交互者拥有实体和路由器。结果视图控制器将在视图层次结构中使用,并根据需要插入,推送或显示。由于您的应用程序的每个部分现在都是VIPER堆栈,因此该体系结构可以为团队规模提供强大的逻辑封装和可伸缩性。

RIB代表路由器,交互器,构建器。RIB是Clean Architecture的另一种实现,它是VIPER的改进。在RIBs体系结构中,主要构建块是RIB,一组一个路由器,一个交互器和一个带有可选视图和演示者的构建器。没有视图的RIB称为无头RIB。就像在VIPER架构中一样,您使用路由器从一个RIB路由到另一个RIB,这将应用程序的整个运行时结构化为带有父RIB和子RIB的树形结构。由于视图是可选的,因此与VIPER不同,您的应用程序树结构可能会或可能不会模仿您的视图层次结构。

Builder负责为交互器,路由器以及视图和演示者组装或初始化它们而获取或创建依赖关系。

路由器负责导航到特定的子RIB。

Interactor负责所有业务逻辑并使用路由器启动路由。

演示者和视图通常组合在视图控制器中,其中演示者负责***和格式化要在视图中显示的数据。

View负责在屏幕上显示数据并收集用户输入。

结论

本文中涉及的问题涉及iOS开发人员应了解的广泛主题。这绝不是一个全面的清单。

推荐👇:

面试题持续整理更新中,如果你想一起进阶,不妨添加一下交流群1012951431

面试题资料或者相关学习资料都在群文件中 进群即可下载!