iOS面试问题第1部分:与众不同

iOS域非常庞大而深刻。 如果您正在寻找适合初学者或有经验的iOS开发面试问题,那么这里是正确的地方。 我已经准备了一些问题,并在各个部分进行了分叉,将一个故事组合在一起将无法证明该主题的合理性。

在这一部分中,我们将区分iOS中的许多已知术语。 我们遇到了许多看起来或听起来相似但略有不同或完全不同的术语。 这部分将主要关注iOS Core开发和Objective-C。 特定于Swift的术语将在单独的部分中进行讨论。 🙂

问:@合成VS @动态

@ synthesize将在编译时为您的属性生成getter和setter方法。

@dynamic只是告诉编译器,getter和setter方法不是由类本身实现的,而是由其他地方实现的(例如超类或将在运行时提供)。

@dynamic的用法例如与NSManagedObject (CoreData)的子类一起使用,或者当您要为由超类(未定义为插座)定义的属性创建插座时。

问:XIB VS NIB

XIB(XML Interface Builder)是Xcode中的可执行代码。 它的大小比笔尖大。 这些是平面文件和XML文件

NIB(Nxt Interface Builder)是不可编辑且不可操作的文件。 它们的尺寸较小。 这些是二进制或存档文件。 编译后,XIB转换为NIB。

问:NSInteger VS Int VS NSNumber

NSInteger是一种描述整数的类型定义,但它并不等效于64位平台上的int 。 在构建32位应用程序时将其定义为int ,对于64位应用程序则将其定义为int 。 大多数情况下,您可以使用NSInteger替换int,但这样做时需要考虑一些事项。

Int是原始数据类型。

NSNumber将数字类型存储为对象,并且可以转换为其他格式。 它还可以检索字符串表示形式。

问:任何VS任何对象

根据Apple的Swift文档:

  • Any 可以代表任何类型的实例, 包括函数类型和可选类型。
  • AnyObject 可以代表任何 类类型 的实例

查看更多详细信息。

问:类别VS协议

协议声明了一个类必须实现的一组方法。 方法可以通过@optional和@ required关键字标记为实现类的可选方法或必需方法。

类别将方法添加到现有类(例如NSObject),而无需修改类本身。

问:类别VS继承

类别允许扩展现有类的API,而无需更改其类型。 它用于添加新方法,而不是属性。

继承还扩展了API,但引入了新类型。 此外,通过子类化,您还可以添加状态和属性

注意:我们可以通过关联对象在类别中添加属性。 查看Matt Thompson的这篇文章。

问:类别VS扩展

注意:快速扩展名类似于Objective-C中的类别 。 与Objective-C类别不同,Swift扩展没有名称。

扩展(Swift)向现有的类,结构,枚举或协议类型添加新功能。 这包括扩展您无法访问原始源代码的类型的能力。

类别(仅Objc-C)允许您在主界面文件之外添加方法。 而Extensions(Objc-C)必须在主Interface文件中实现。 这意味着我们不能使用扩展来扩展内置类或您没有源代码的类,而应该使用类别。

问:正式VS非正式协议

非正式协议是NSObject上的一个类别,它隐式地使该协议的几乎所有对象适配器成为可能。 在非正式协议中实现这些方法是可选的 。 在调用方法之前,调用对象将检查目标对象是否实现了该方法。 在Objective-C 2.0中引入可选协议方法之前,非正式协议对于Foundation和AppKit类实现委派的方式至关重要。

正式协议声明了客户端类应实现的方法列表。 正式协议具有自己的声明,采用和类型检查语法。 您可以使用@required和@optional关键字来指定其实现是必需的还是可选的方法。 子类继承其祖先采用的正式协议。 正式协议也可以采用其他协议。

注意:Apple Docs

问:NSSet VS NSArray

NSSet主要通过比较访问项目。 它们是无序的,不允许重复。
NSArray按索引访问项。 他们允许重复的项目,并被订购。

问:NSDictionary VS NSMutableArray

NSDictionary是无序的,并且将对象存储为键值对。 通过使用任意字符串值寻址对象来访问对象。
NSMutableArray与NSArray相似,除了它的内容是动态的,即可以在创建对象后更改。

问:委派VS通知

代表们在两个类之间创建了一个has-a关系。 它支持双向通信,即我们可以返回该值,并且还可以修改或拒绝该操作。 它在编译时检查协议方法的实现。 只有一个指定的对象可以收听消息。 类似于电话交谈。
基于一对多通信的通知。 它无法接收反馈,并且对象之间没有链接来回通信。 没有方法执行的编译时检查。 任何数量的对象都可以接收该消息。

授权也避免了紧密耦合。 它无需子类对象即可修改行为和外观。

问:浅VS深复制

浅拷贝也称为地址拷贝,类似于“按引用呼叫”。 它复制结构,而不是数据/元素。 对一个对象所做的更改也反映了另一个对象。 在Objective-C中,可以使用copy或mutable copy关键字实现它。

Deep Copy也类似于按值调用。 它复制实际数据,并且两个对象都有自己的副本,即它们指向不同的数组。 对一个对象所做的更改不会反映在另一个对象上。 在Objective-C中,可以使用NSKeyedArchiver / NSKeyedUnarchiver类的方法来实现。

请在Objective-C中检查这个很棒的实现。

问:原子VS非原子

原子是属性的默认行为。 它确保当前进程在另一个进程访问该变量之前由CPU完成,因此它是线程安全的。 这不是很快,因为它可以确保整个过程完成。

“非原子”不是默认行为。 它更快(对于合成代码,即使用@property和@synthesize创建的变量)。 它不是线程安全的,并且当两个不同的进程同时访问同一变量时,可能导致意外行为。

什么是线程安全?
如果一段代码即使在多线程环境中也能给出正确的结果,则它被称为线程安全的;即,如果它由多个线程同时执行,它将给出正确的结果。 线程安全性意味着代码可以处理多个线程。

问:弱vs强

STRONG引用表示您想使用属性或变量“拥有”所引用的对象。 编译器会注意您分配给该属性的任何对象都不会被破坏。 仅当将属性设置为nil时,该对象才会被销毁(除非一个或多个其他对象也对该对象具有强烈的引用)。

相反,使用WEAK引用表示您不希望控制对象的生存期。 您所弱引用的对象仅能生存,因为至少有另一个对象对此对象具有强引用。 一旦不再是这种情况,对象将被销毁,并且您的弱属性将自动设置为nil 。 iOS中弱引用的最常见用例是:

  1. 委派属性,这些属性通常被弱引用以避免保留周期,并且
  2. 视图控制器主视图的子视图/控件,因为这些视图已经由主视图牢牢占据。

问:分配VS弱

  • 如果只需要一个指向对象但不保留它的指针,请使用函数 -对避免保留循环(即委托)很有用-当释放对象时,它将自动使指针无效
  • 对原始函数使用assign —与弱函数完全一样,只是它在释放时不会清除对象,它可能留下悬空的指针,即。 将访问垃圾值。 Assign和unsafe_unretained的用法相同。

问:保留VS强(=)

  • strong与属性声明中的keep相同,因此对于ARC项目,请使用strong而不是keep
  • 保留与坚强相同。
  • 苹果说,如果您写保留,它将自动转换/仅像强一样工作。
  • 诸如“分配”之类的方法包括一个隐式的“保留”

问:保留VS复制

保留 :这在创建的对象上完成,并且只是将引用计数增加了一个。

copy :复制对象,并以保留计数1返回它。如果复制对象,则您拥有该副本。 这适用于任何包含单词copy的方法,其中“ copy”是指要返回的对象。

问:绑定VS帧

视图对象使用其框架,边界和中心属性跟踪其大小和位置:

frame属性包含框架矩形,该矩形指定视图在其超级视图的坐标系中的大小和位置

bounds属性包含bounds矩形,该矩形指定视图自身的本地坐标系中视图的大小(及其内容原点)。

center属性包含超级视图坐标系中视图的已知中心点。

问:零VS零VS NSNull

Matt Thompson撰写的详细博客。

问:NSNotificationCenter VS本地通知VS推送通知

UILocalNotificationUILocalNotification的实例表示应用程序可以安排在特定日期和时间向其用户呈现的通知。 操作系统负责在适当的时间传递通知。 它不会通知您的自定义类对象。 如果应用程序在后台,它将显示为警报。 仅在应用未运行时才自动显示UILocalNotifications。 如果应用程序正在运行并且触发了本地通知,则将调用UIApplicationDelegate的didReceiveLocalNotification方法,并且系统不会显示任何内容/不会播放声音。 如果要显示通知,请在委托方法中自己创建一个UIAlertView。

NSNotificationCenter :它在正在运行的应用程序内部,不需要服务器或任何特殊设置。 无需在Apple开发人员中心获取证书,标识符和配置文件。 它用于通知自定义类对象。 NSNotification是在应用程序中的对象之间内部发送的消息。

推送通知:我们需要在Apple开发人员中心获取证书,标识符和配置文件。 确实,这需要服务器和供应配置文件或Info.plist中的特殊设置。 该消息是从服务器发送的,应用程序会显示该消息。

问:关键值观察VS NSNotificationCenter

键值观察 添加关键路径的观察者,并用来观察对象属性的变化

NSNotificationCenter添加了用于通知的观察者,并在要通知多个对象时使用

问:isKindOfClass VS isMemberOfClass VS isSubclassOfClass

isKindOfClass: 对象是类的实例还是子类的实例。
isMemberOfClass对象是类的实例吗? (不包括子类)。
isSubclassOfClass一个类是否等于另一个类或该类的子类? 这是一个类方法。

以上所有返回布尔值。

  [[NSMutableData数据] isKindOfClass:[NSData类]];  //是 
[[NSMutableData数据] isMemberOfClass:[NSData类]]; //否
[NSString isSubclassOfClass:[NSObject类]]

问:委托与目标/行动

委托通常使用协议而不是选择器来实现。 这是跨类进行通信的一种更正式的方式,并且在可能需要多个方法时最有用。 它用于在2个对象之间发送和接收数据。 通过具有返回值的方法,它用于双向通讯。

目标/动作通常用于对应于“类似事件”的情况,例如单击,计时器触发等,并且在通信仅限于控制(事件,状态等)时更适用。 主要表现为一维沟通

问:内容拥抱与 压缩性

内在内容大小 -相当不言自明,但是内容可变的视图会知道其内容的大小,并通过此属性描述其内容的大小。 具有内在内容大小的视图的一些明显示例是UIImageViews,UILabels,UIButtons。

内容拥抱(内容不希望增长):优先级越高, 视图抵抗增长的能力越大 ,其内部内容大小也多。

抗压缩性(内容不希望收缩):此优先级越高, 视图抵抗收缩的能力就比其固有内容大小小得多

问:GCD VS NSOperation

GCD是基于C的底层API。
NSOperationNSOperationQueue是Objective-C类。
NSOperationQueueGCD目标C包装器。 如果您使用的是NSOperation,那么您将隐式使用Grand Central Dispatch。

GCD优于NSOperation:
一世。 实作
对于GCD实现非常简单,轻巧并且具有无锁算法。
NSOperationQueue非常复杂,笨重并且涉及很多锁定

NSOperation相对于GCD的优势:

一世。 操作控制
您可以暂停,取消,恢复NSOperation

ii。 依存关系
您可以在两个NSOperations之间建立依赖关系
直到所有依赖项都为完成返回true时,操作才会开始。

iii。 运行状态
可以监视操作或操作队列的状态。 准备,执行或完成。 也可以计算待处理的操作。

iv。 最大操作数
您可以指定可以同时运行的最大排队操作数

v。可观察
NSOperation和NSOperationQueue类具有许多可以使用KVO(键值观察)观察到的属性。 如果要监视操作或操作队列的状态,这是另一个重要的好处。

何时参加 GCD NSOperation
当您想对队列进行更多控制时(以上都提到了),请使用NSOperation ;对于一些简单的情况,您需要较少的开销(您只想在后台完成一些工作,而几乎没有额外的工作),请使用GCD

问:静态与动态输入

静态类型是在编译时进行类型检查的时间。 您必须在代码中为变量定义类型,并且对数据执行的所有操作都将由编译器检查。

动态类型是在运行时进行类型检查的时候 。 如果您尝试对不兼容的类型执行操作,则会得到运行时错误,而不是在编译代码时出现错误。 但是,您将获得具有更多用途的功能的好处,因为它们可以针对多种数据类型编写一次。

问:什么是“应用程序ID”和“捆绑包ID”?

捆绑软件ID可以准确地标识一个应用。 当开发应用程序分发给客户时,它在开发过程中用于供应设备和由操作系统使用。

在开发过程中,您可以在许多不同的地方使用应用程序的捆绑软件ID来标识该应用程序。

而App ID是一个由两部分组成的字符串,用于标识单个开发团队中的一个或多个应用程序。

团队ID由Apple提供,对于特定的开发团队而言是唯一的,而捆绑包ID搜索字符串由您提供,以匹配单个应用程序的捆绑包ID或一组应用程序的捆绑包ID。

应用程序ID有两种类型:显式应用程序ID(用于单个应用程序)和通配符应用程序ID(用于一组应用程序)。

来源:捆绑包ID,APP ID

问:KVC VS KVO?

KVC(键值编码) –这是一种机制,通过它可以在运行时使用字符串访问对象的属性,而不必在开发时静态地知道属性名称。

KVO(键值观察)-它允许控制器或类观察对属性值的更改。 在KVO中,对象可以要求将特定属性的任何更改通知给对象,只要该属性更改值,就会自动通知观察者。

问:BDD VS TDD

BDD和TDD之间的主要区别是非工程师可以读取BDD测试用例,这在团队中非常有用。

测试驱动开发是一种测试优先的软件开发方法,这意味着它需要先编写测试代码,然后再编写将要测试的实际代码

行为驱动开发是一种基于TDD创建的方法,但后来演变为一个过程,该过程不仅涉及程序员和测试人员,而且涉及整个团队以及所有重要的技术和非技术利益相关者。 BDD从TDD不能很好回答的几个简单问题开始:我应该编写多少测试? 我应该实际测试什么,我不应该测试什么? 实际上,我编写的哪些测试对业务或产品的整体质量很重要,而哪些只是我的过度设计?

有人认为BDD总是比TDD更好,因为它无法消除使用TDD时可能出现的问题。 诸如不良的代码组织,不良的设计实践等问题仍将继续存在。 您编写不良测试的可能性更低,因此具有更强大的功能。

iOS BDD Framework:快速灵活。

问:SVN VS Git

SVN依靠集中式系统进行版本管理。 它是一个中央存储库,在其中生成工作副本,并且需要网络连接才能访问。

Git依靠分布式系统来进行版本管理。 您将拥有一个可以在其上工作的本地存储库,并且只有同步才需要网络连接。

问:JSON VS XML

问:休息VS肥皂

检查此细节比较。

问:堆栈VS堆

堆栈可以快速访问,而不必显式地取消分配变量。 CPU可以有效地管理空间,并且内存不会碎片化。 堆栈大小有限制(取决于OS)。 通常,变量是存储的,无法调整大小。

使用堆,可以全局访问变量,但访问速度较慢。 没有内存限制。 无法保证有效利用空间,随着时间的推移,内存块可能会随着内存块的分配而碎片化,然后释放。 我们需要管理内存。

更多信息。

问:静态VS动态库

静态库(.a)

静态库允许应用程序在编译时将代码加载到其地址空间中,这会导致磁盘更大且启动时间更慢。 因为库的代码直接添加到链接目标的二进制文件中,所以这意味着要更新库中的任何代码,也必须重建链接目标。

动态库(.dylib)

动态库允许应用程序在运行时实际需要时将代码加载到其地址空间中。 由于代码不是静态链接到可执行二进制文件中,因此在运行时加载有一些好处。 通常,可以使用新功能或错误修复程序来更新库,而无需重新编译和重新链接可执行文件。 此外,在运行时加载意味着各个代码库可以拥有自己的初始化程序,并在完成自己的任务后进行清理,然后再从内存中卸载

问:SQLite与核心数据

SQLite:主要功能是存储和获取数据。 它对存储在磁盘上的数据进行操作。 它可以存储“哑”数据,并且可以是事务性的,线程安全的和多用途的。 永久保存到磁盘(并且通常具有崩溃恢复能力),并且创建数百万个新行的速度可能很慢。 它提供了诸如“唯一”键之类的数据约束。

核心数据:主要功能是图形管理(尽管对磁盘的读写是重要的支持功能)。 它对存储在内存中的对象进行操作。 它与成熟的对象一起使用,这些对象可以自我管理很多行为,并且可以为进一步的行为进行子类化和自定义。 它也是非事务性,单线程,单用户。 它需要一个保存过程,并将数据约束留给程序的业务逻辑端

问:CollectionViews与TableViews

TableViews在垂直方向上以单列显示项目列表,并且仅限于垂直滚动。

CollectionViews还显示项目列表,但是它们可以具有多个列和行。

问:LLVM VS C

Clang是LLVM工具链的前端(“ clang”是LLVM的C语言家族前端)。 每个编译器都有三个部分。
1.前端(词法分析,解析)
2.优化器(优化抽象语法树)
3.后端(机器代码生成)

前端(Clang)获取源代码并生成抽象语法树(LLVM IR)。

问:属性VS实例变量

对于私有/受保护的变量,请使用iVar对于公共变量,请使用property 。 如果要对私有变量使用属性属性的好处,例如保留,非原子等,请在实现文件中将该属性声明为私有属性。

对于iVar,可以使用@protected @public@protected@public 。 但是这些属性仅影响子类的访问,与实例的访问能力无关。

iVar比属性快,因为属性将调用gettersetter函数。 声明属性时,编译器将为该属性添加gettersetter函数。

iVar是一个实例变量。 除非我们创建由@property生成的访问器,否则无法访问它。 iVar及其对应的@property可以使用不同的名称。 始终可以使用KVC访问iVar。

有关属性继承的说明: 如果超类具有声明为public的属性,则子类可以继承该属性。 但是自动合成机制不会自动合成属性,并且只能通过点操作使用超类的getter和setter访问器。 如果要手动合成, 请小心! 您应该避免在超类中使用与它们相同的iVar。 这将导致错误消息“试图使用父类“ SuperClassName”中声明的实例变量“ InstanceVariableName”的属性“ propertyName””。

问:SDK VS框架

SDK是一组软件开发工具。 该集合用于创建应用程序。 框架基本上是用于开发软件应用程序的平台。 它提供了必要的基础,可以为特定平台开发程序。 SDK和Framework相互补充,并且SDK可用于框架。

问:ARC VS自动发布

自动释放仍在使用ARC。 范围内使用ARC,而功能范围外使用自动释放。