在本文中,您将找到针对高级开发人员的iOS面试问题和解答。 当您准备进行技术性的iOS面试时,重要的是要了解您可能会被问到的话题以及经验丰富的iOS开发人员的期望。这些问题被许多公司用来衡量iOS候选人的经验水平。它们涵盖了iOS开发的各个方面,旨在接触对该平台的广泛了解。毕竟,高级开发人员有望能够从头到尾交付完整的iOS产品。但是,在拥有大型iOS开发团队(可容纳25人以上)的大型公司中,也会进行专业化并且专注于对特定问题(例如网络)的深入了解。这绝不是详尽的清单,但可以帮助您为即将进行的iOS技术面试做准备。 1. 个Swift的主要特征和优缺点是什么?这听起来像是一个初学者的问题,但事实并非如此。有时可能会要求您评估您在使用其他语言方面的经验,以及对所使用语言为您提供的语言及其优点,缺点和局限性的更广泛理解。 预期答案:
Swift是一种强类型语言,它可能同时是其最大的功能,优点和缺点。静态类型允许协议,泛型和可选项存在,并有助于您进行开发。静态类型为您提供了许多编译时警告和编译错误,但提供了更高的运行时安全性和确定性(可选,var / let,泛型或具体类型等)。这是该语言提供的最大优势之一。在以下情况下,具有严格的类型安全性是最有帮助的:
所有这些恰好是iOS开发人员构建的大多数面向客户的应用程序。 同时,当您构建需要更多灵活性的内容(如构建库或框架)时,静态类型可能会过于严格。在这方面,Objective-C可能是一个更好的选择,因为它比Swift具有更好的元编程功能。(尽管可以说,此时Objective-C已过时,并且Apple平台的所有开发都应在Swift中完成) 回答注意点: 只要您能阐明每个功能所提供的功能(即协议和泛型实际上允许您在代码中执行什么操作),就可以了?但是同样,与严格类型系统相比,那些语言可以说是次要的语言功能。 2. 什么是iOS应用程序,您的代码适合哪里?这是一个大问题,以一种或另一种形式提出,以评估您对iOS应用程序的理解,以及您编写的代码在其中以及在iOS系统中的适用位置。 预期答案:
您编写的用于实现应用程序业务逻辑的其余代码位于该主循环通过 而已。简单。您为应用程序编写的代码可以像方法/函数调用一样简单,也可以像VIPER体系结构一样复杂。这是你的选择。 回答注意点: 通常,开发人员将iOS应用视为他们编写的MVC代码以及实现的复杂细节,这是事实。但是,如果退后一步,放眼大局,您可以看到真正的iOS应用程序-运行循环。 3. iOS中的内存管理如何处理?内存管理在任何应用程序中都非常重要,尤其是在具有内存以及其他硬件和系统约束的iOS应用程序中。此问题涉及ARC,MRC,引用类型和值类型。 预期答案:
回答注意点: 这是每个iOS开发人员都必须知道的!由于iOS应用程序中的内存管理不善,内存泄漏和应用程序崩溃非常普遍。 4. 什么是MVC?哦,老MVC不错。这是Apple不断推向iOS开发人员的基本设计模式。无论您是申请高级职位还是初级职位,每位面试官都极有可能会问这个问题。不过,您作为大四学生的答案会有所不同。 预期答案:
iOS应用程序中每个Apple MVC层的典型表示为:
MVC是一种很棒的通用设计模式,但是作为高级开发人员,您应该知道它只是视图层的设计模式,单独使用它会限制您的体系结构,并经常导致臭名昭著的“大型视图控制器”问题。 Massive View Controller是代码库的状态,在该状态下,大量逻辑和职责被推到不属于该代码库的View Controller中。这种做法会使您的代码僵化、,肿且难以更改。还有其他设计模式可以帮助您解决这一问题,例如 MVVM, MVP和 Coordinator。还有一些架构,例如VIPER和 RIB是专门为扩展iOS代码和避免Massive View Controller问题而设计的。 即使Apple一直告诉我们MVC就是一切,但请多了解并坚持SOLID原则。 回答注意点: 您绝对必须知道MVC是什么,因为它是任何iOS开发的基础。但是,请探索替代产品和附加产品,例如MVVM,MVP,VIPER和RIB。 5. 您对单身人士了解多少?您将在哪里使用哪一个?Singleton是许多OOP语言中常用的设计模式,可可认为它是“可可核心能力”之一。面试中会出现这个问题,以评估您对单身人士的体验,或者了解您是否具有iOS以外的背景知识。 预期答案:
有时将单例视为反模式。使用单例有多个缺点。主要参数是全局状态,对象生命周期和依赖项注入。当您只有某个事物的一个实例时,很想直接在任何地方引用和使用它,而不是将其注入到对象中。这导致代码中具体实现的不必要耦合,而不是使用接口抽象。 “方便”单例的另一个恶意副作用是全局状态。通常,单例启用全局状态共享,并扮演每个对象用来存储状态的“公共包”的角色。当这种不受控制的状态被某人覆盖或删除时,这将导致不可预测的结果,错误或崩溃。 回答注意点: 即使在某些语言和平台中,单例被认为是不错的选择,但实际上它们是一种反模式,应不惜一切代价避免这种情况。 6. 代表和KVO有什么区别?有了这个问题,面试官正在评估您对iOS中使用的不同消息传递模式的了解。 预期答案:
回答注意点: 经验丰富的开发人员应该知道两者之间的差异,以及在哪里可以相互使用。 7. iOS应用程序通常使用哪些设计模式?除初级职位外,所有级别的面试中都会出现这个问题。使用iOS平台,开发人员应该熟悉iOS上常用的技术,体系结构和设计模式。 预期答案:
回答注意点: 当面试官(以一种或另一种形式)问这个问题时,他正在寻找MVC以外的东西。因为MVC是首选设计模式,所以期望每个iOS开发人员都知道这一点。但是,他们想从您那里得到的消息是我们通常开箱即用的其他信息。 8. 除了您知道的常见可可图案以外,还有哪些设计图案?这是一个高级问题,当您面试高级职位或建筑师职位时,面试官会提出这个问题。期望的是,您将了解iOS应用程序中使用的更实用的设计模式,而不仅仅是前面问题中涵盖的基本设计模式。准备召回一堆“ 四人帮”模式和其他类似模式。 设计模式本身就是一个巨大的话题(在我的书中有更好的介绍),因此在这里,我将仅总结我在iOS代码库中常见的模式。 预期答案:
Factory Method用于替换类构造函数,以抽象和隐藏对象的初始化,以便可以在运行时确定类型,并隐藏和包含 适配器是一种设计模式,顾名思义,它可以帮助您使一个对象的界面适应另一个对象的界面。当您尝试适应无法更改为代码的第三方代码时,或者当您需要使用不方便或不兼容的API时,通常会使用此模式。 装饰器是另一个类的包装,可以增强其功能。它包装了您要装饰的东西,实现了它的接口,并将发送给它的消息委托给基础对象,或者增强了它们或提供了自己的实现。 命令是一种设计模式,您将在其中实现一个对象,该对象表示您想要执行的操作。该操作可以具有其自己的状态和逻辑来执行它所执行的任务。这种设计模式的主要优点是,您可以向用户隐藏操作的内部实现,可以向其添加撤消/重做功能,并且可以在以后的某个时间点(或根本不执行)而不是执行操作。立即创建操作的位置。 模板是一种设计模式,其主要概念是拥有一个基类,该基类概述了需要完成的算法。基类有一些抽象方法,这些方法必须由其具体子类实现。这些方法称为挂钩方法。Template Method类的用户只能使用实现算法步骤的基类进行交互;这些步骤的具体实现由子类提供。 回答注意点: 当您刚从iOS平台开始时,仅坚持使用MVC,Singleton,Delegate和Observer模式是很好的,但是对于高级功能,您需要更深入地研究更抽象和更高级的内容,例如“四个OOP设计模式的帮派”。它们非常有用,可以使您的代码库更加灵活和可维护。 9. 解释并显示SOLID原理示例?SOLID原则相对较旧,但适用于任何语言的任何OOP代码库的概念都非常有用。观看Bob叔叔关于该主题的一些演讲,以充分理解其背后的历史。 在YouTube上:Bob Martin面向对象和敏捷设计的SOLID原理。 不幸的是,SOLID原则本身就是一个巨大的话题(在我的书中也有更好的介绍),因此在这里我仅对它们进行概述。 预期答案:
单一责任原则(SRP)是该小组最重要的原则。它指出,每个模块都应该只有一个责任和变更理由。SRP从小的具体情况开始,例如类和/或对象仅具有一个目的,并且仅用于一件事。 打开/关闭原则(OCP)指出,您的模块应打开以进行扩展,但应关闭以进行修改。这是听起来很容易的事情之一,但是当您开始思考它的含义时,很难把头缠起来。实际上,这意味着在编写代码时,您应该能够通过使用接口,抽象和依赖注入实现对象,从而通过继承,多态和组合来扩展对象的行为。 Liskov替换原理(LSP)指出,程序中的对象应该可以用其子类型的实例替换,而不会改变该程序的正确性。这意味着当您从类或抽象类继承或实现接口(协议)时,无论使用了您的子类接口或类,您的对象都应该是可替换和可注入的。这项原则通常被称为按合同设计,或者在Swift社区中最近被称为面向协议的编程。该原则的主要信息是,您不应违反从子类承诺继承的接口要履行的约定,并且通过子类化,这些子类可以在以前使用超类的任何地方使用。 接口隔离原理(ISP)表示,许多特定于客户端的接口比一种通用接口要好。它还指出,不应强迫任何客户端依赖和实现不使用的方法。这就是说,当您创建类要实现的接口(协议)时,您应该努力并依赖于抽象性而不是特异性,但是直到浪费掉您必须实现一堆新类的方法时,这种浪费才成为现实。甚至使用。 依赖倒置原则(DIP)指出:“依赖抽象,而不依赖具体。” 展示此原理的最佳示例是依赖注入(DI)技术。使用依赖注入技术,在创建对象时,您将在其初始化或配置时提供并注入其所有依赖关系,而不是让对象自行创建或获取/查找其依赖关系。 回答注意点: SOLID原则是良好的OOP设计的基础。应用这些原则将帮助您构建更好,更可维护的软件。如果您要申请iOS的高级职位,强烈建议您精通它们。 10. 您在iOS上实现存储和持久性有哪些选择?采访者会问这个问题,以了解您对可用于在iOS上存储和保存数据的工具和方式的理解。 预期答案:
内存中的数组,字典,集合和其他数据结构非常适合用于中间存储数据或无需持久存储数据。 NSUserDefaults / Keychain是简单的键值存储。一个是不安全的,另一个是安全的。 文件/磁盘存储是一种使用NSFileManager向磁盘写入数据或从磁盘写入数据的方法。 核心数据和领域是简化数据库工作的框架。 SQLite是一个关系数据库,当您需要实现复杂的查询机制而Core Data或Realm不会削减它时,它是一个很好的选择。 回答注意点: 您应该知道在iOS上存储数据的不同方式以及它们的优缺点。不要将自己仅限于您习惯的一种解决方案(例如,Core Data)。知道何时一个比另一个更可取。 11. iOS上的网络和HTTP有哪些可用选项?如今,每个应用程序都使用网络来从API和其他外部资源获取数据。如果未连接到互联网,许多应用程序将无用。每个iOS开发人员都应该知道他们可以使用什么来构建其应用程序的服务/网络层。 预期答案:
通常,如果您的团队很小,则可能需要依靠开源解决方案,例如Alamofire,它可以为您抽象出许多样板代码。但是如果您的团队很大,并且可以节省资源,那么您将希望更好地控制数据与服务器之间的传递以及使用NSURLSession自己实现数据的方式。 高级开发人员应记住,在iOS应用程序中构建网络层不仅意味着处理HTTP请求,而且意味着实现代码所涉及的整套任务:HTTP网络,数据序列化和数据映射。 回答注意点: 如今,NSURLSession和Codable是用于在iOS上联网的两种主要技术,但了解Alamofire之类的开源解决方案也是有益的。 12. 如何以及何时在iOS上序列化和映射数据?生成iOS应用程序时,数据序列化是一项常见任务。采访者会问这个问题,以了解您是否认识到合适的位置,并知道在处理数据时(无论是网络数据还是存储数据)所需的任务。 预期答案:
每次您从后端API收到JSON或XML或任何其他响应类型的响应时,您很可能会以JSON或二进制或其他“不便”格式获取它。要处理收到的数据,您需要做的第一件事就是将其序列化为您的应用可以理解的格式。最简单和最基本的级别是字典或包含该响应中其他字典,数组和基元的对象数组。NSJSONSerialization会解决这个问题。下一步是将数据映射到应用程序的域模型中。这些将是应用程序其余部分要使用的模型对象或结构。您可以手动执行此操作,也可以使用 同样,在存储层中,您将需要序列化数据并将其与自定义域模型对象之间的数据映射到存储所能理解的格式。用于读取数据的“映射”链: 回答注意点: 这里的主要危险信号是没有意识到与iOS应用程序的网络和存储层一起使用时,需要进行这些数据操作。事情不会“自动地”发生,并且与原始的NSDictionaries合作也不是适当和可维护的。 13. 在iOS上布置UI有哪些选项?当您需要解决iOS上不同的UI挑战时,了解在屏幕上布置内容的选项至关重要。该问题有助于评估您有关如何在屏幕上放置和对齐视图的知识。在回答这个问题时,您至少应提及CGRect,Fframes和AutoLayout和SwiftUI,但最好提及其他选项,例如Texture(ASDK),ComponentKit以及iOS上的其他Flexbox和React实现。 预期答案:
从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问题一起,访谈中的重要问题之一是滚动性能。 预期答案:
滚动性能问题的潜在解决方案可能是:
或者,您可以采用一种完全激进的方法,即使用诸如ASDK(纹理)之类的不同技术。ASDK(纹理)是专门为具有动态内容大小的列表视图制作的,并且经过优化以计算后台线程中的单元格高度,从而使其具有超强的性能。 15. 您将如何在iOS上执行异步任务?如今,多线程是任何客户端,面向用户应用程序的重要组成部分。该问题可以在网络环境中提出,也可以作为有关GCD或异步开发的独立问题提出。 预期答案:
使用第三方库的帮助还有其他处理异步工作的方法。最著名的是Promises(PromiseKit),RxSwift和ReactiveCocoa。RxSwift和ReactiveCocoa特别擅长建模时间和工作的异步特性,这些工作需要在后台完成并在线程之间进行协调。 回答注意点: 每个iOS开发人员应了解的有关异步工作的基础知识是GCD和NSOperations。RxSwift和Promises是高级概念,但是高级开发人员应该了解它们。 16. 您如何管理依赖关系?依赖管理是每个iOS项目中的重要任务。这个问题可以衡量您对问题及其解决方案的理解。 预期答案:
如今,我们还有其他依赖项管理器可供选择:CocoaPods,Carthage和Swift Package Manager。 到目前为止,最主要和最强大的功能是CocoaPods。我本着Ruby Bundler宝石的精神建造的,本身就是Ruby宝石。它的工作方式是安装gem, 使用Carthage,您可以创建一个名为的依赖项声明文件, Swift软件包管理器是任何Swift项目依赖管理的未来,但它仅支持库和框架,并且不能用于生成iOS目标,尽管iOS目标可以依赖于SPM构建的模块。 回答注意点: 每个iOS开发人员都应该理解,当多个库可能依赖于另一个库的两个不同版本时,将第三方库复制粘贴到您的代码库中会导致维护的噩梦,从而导致不匹配以及编译和运行时问题。 17. 您如何在iOS上调试和分析代码?没有人编写完美的代码,开发人员需要调试其代码和配置文件应用程序,以提高性能和内存泄漏。 预期答案:
您可以使用进行更高级的调试和分析 18. 您有TDD经验吗?您如何在iOS上进行单元和UI测试?尽管从历史上看,iOS社区在TDD上并不占优势,但由于工具的改进和来自其他社区(如Ruby)的影响(早在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功能还是更大的体系结构和概念性讨论问题,都可以期待这个问题。 预期答案:
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设计模式不能像大型应用程序架构那样很好。对于前辈,主管,建筑师等,这是一个非常高级的问题。 预期答案:
清洁体系结构是用于规模化的概念性应用程序体系结构,可以简单地描述为“洋葱分层体系结构”。主要思想是使依赖关系向内指向您的域逻辑和域模型,并使其他所有内容都是可插拔的和可选的(存储数据,呈现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开发人员应了解的广泛主题。这绝不是一个全面的清单。 推荐 |
|