IOS面试问答(2019年1月)第3部分

iOS面试题2019

本文包括来自VMware的有关IOS职位的更多问题。 希望对您有帮助。

下一篇: IOS面试常见问题解答(2019年1月)第4部分

如有其他疑问,请查看以前的文章-2018/2019年度IOS面试常见问题解答

Q1。 您使用了哪个应用程序,为什么使用了MVVM,MVC?

回答MVVM

首先,关键优势在于实现viewmodel之间的真正分离。 实际上,这意味着如果/当您的模型需要更改时,它可以不需要视图,反之亦然。

其次,虽然model可能包含view可能需要的所有数据,但您可能希望以model不支持的方式抽象该数据。 例如,假设您的模型包含date属性。 在模型中,它可以单独作为DateTime对象存在,但是您的视图可能希望以完全不同的方式呈现它。 如果没有viewmodel您将不得不复制model的属性以支持视图,或者修改可能严重混淆“模型”的属性。

您还可以使用viewmodel模型来聚合模型中存在于单独的类/库中的部分,以简化view的处理流程。 您不太可能希望以用户希望或希望将数据呈现给他们的相同方式来处理代码中的数据。

最重要的是,您还支持viewviewmodel之间的自动双向数据绑定。

是什么激发了MVC

MVC的核心是我所说的“独立演示”。 分离演示的背后思想是在建模我们对现实世界的感知的领域对象和作为屏幕上看到的GUI元素的演示对象之间进行清晰的划分。 域对象应该完全独立并且可以在不引用演示文稿的情况下工作,它们还应该能够支持多个演示文稿,并且可能同时支持。

Q2。 为什么我们要在主线程上执行UI操作?

回答 :由于某些原因,您必须在主线程上更新UI。

第一个是在Cocoa Touch中,在主线程上设置了UIApplication。 这是启动应用程序时实例化的应用程序的第一部分。

屏幕上的所有视图(例如您正在使用的标签)都是该UIApplication实例的后代。 因此,当您点击按钮或使用按钮时,这些必须在主线程上进行更新,因为它们是主线程的一部分。 同样,任何来自按钮或标签的事件(例如敲击或捏)都将是主线程的一部分,应在此进行处理。

另一个原因是图形渲染:iPhone的图形管道最终是同步的。

假设您正在使用UILabel,即屏幕上的一些文本。 您等待异步请求返回,也许是包含iPhone用户名的用户数据。 数据输入后,您将使用用户名更新标签。

UIKit是UILabel所属的框架,然后在屏幕上呈现文本。 它将光栅化字体(因为字体是矢量),然后将文本转换为像素。 当该文本是混合层的一部分时,例如在剪切或应用透明度时,图形渲染器将计算应显示标签的哪个像素。 然后将这些像素与屏幕的其余部分放在一起,每秒最多60次。

绘制到iPhone屏幕上(点亮LED显示屏上的像素)是需要立即进行的过程,屏幕上的所有像素都必须同时出现。 从定义上讲,异步编程不是同步的,而是并行的,您不确定异步操作何时完成。

如果允许异步绘制到iPhone显示屏,则可能会出现大量的闪烁和丢失的零件,因为在渲染整个屏幕时尚未准备好对该零件的处理。

最终,在主线程上更新UI更加简单。 它可以为您节省大量决策,需要解决的问题和错误。 当然,只要UI的更新是同步的,就可以在异步线程上创建UI的一部分。

一些例子:

  • 将滤镜或图形效果应用于视图,例如圆角或使用CIFilter。 这些过程非常密集,您需要对其进行缓存,并在将它们绘制到屏幕之前在异步线程上分派它们。
  • 创建动态图形,例如动画。 您首先要处理它们,然后播放处理后的动画。 绘制图形和生成的图像也是如此。
  • 下载网络资源(如用户数据),然后同步更新UI。

当然也有例外,最著名的是Facebook的iOS版AsyncDisplayKit。 作为框架不可分割的一部分,视图是异步呈现的,尽管这并不意味着iPhone的显示是异步更新的。 在任何情况下,该框架都可以实现流畅的UI!

这是WWDC的很酷的视频,向您展示了如何同时渲染UI:在iOS上构建并发用户界面

Q3。 iOS 12和APNS有哪些新功能?

:请查看本文以了解详细信息-iOS 12中针对开发人员的新增功能

Q4。 何时使用NSObject的Initialize vs Load API?

load() :每当将类或类别添加到Objective-C运行时时调用; 实现此方法以在加载时执行特定于类的行为。

  1. 每当将类或类别添加到Objective-C运行时时调用。 应用启动时
  2. 即使不调用类的任何方法也被调用。
  3. 如果在类别中实现+ load,则每个类别调用一次,每个类别类别调用一次
  4. 框架类此时被加载
  5. 未加载C ++静态初始化程序
  6. 在主要方法之前调用。
  7. 在这里使用自动释放对象是安全的,因为ARC会自动创建自动释放池。

initialize():在类收到其第一条消息之前对其进行初始化。

  1. 每堂课一次
  2. 如果您不调用类,则不会被调用。
  3. + initialize方法可以多次调用。
    例如,如果子类未实现初始化,它将被调用两次
  4. 初次上课时被呼叫
  5. 以线程安全的方式调用
  6. 超类在其子类之前收到初始化消息

Q5。 在您的应用程序中添加哪些APNS步骤?

回答 :设置用于推送通知的APNS

步骤 1:建立应用程式编号。

步骤 2:创建APNs SSL证书。

步骤 3:注册测试设备。

步骤 4:创建iOS发行证书。

步骤 5:创建配置文件。

步骤 6:项目设置, 启用APN,在Xcode中,转到“ 目标” ,在应用名称下,选择“ 功能”,然后在列表中找到“ 推送通知,然后切换

7 :在AppDelegate中添加UserNotifications框架,启动requestAuthorization ,然后注册registerForRemoteNotifications

步骤 8:由App委托提供两个api, 一个获取我们设备令牌,另一个则检查是否存在错误

didRegisterForRemoteNotificationsWithDeviceToken和didFailToRegisterForRemoteNotificationsWithError

9 :使用rest api与您的服务器共享令牌,并开始接收推送通知。

Q6。 迭代与递归方法—哪个更快,为什么?

回答:从技术上讲, 迭代循环在硬件级别上更适合典型的计算机系统:在机器代码级别,循环只是测试和有条件的跳转,而递归(天真的实现)涉及推入堆栈帧,跳转,返回和从堆栈弹出。

  1. 递归始终应用于方法,而迭代则应用于指令集。
  2. 递归可以比迭代更快 。 现在多核芯片已成为常态,可以通过在内核之间分配负载来提高性能。 但是,这在迭代解决方案中并未完成,因为它很难执行,有时甚至无法执行。 但是依赖无状态幂等方法的语言无法执行迭代,因此程序员必须使用递归。 这些方法是无状态且幂等的,这意味着优化器可以始终在多个内核之间分配负载,从而提高性能。

Q7。 我们应使用≥vs <运算符中的哪一个?

回答 :≥需要检查条件(c1和c2),而在<情况下,仅需要检查一个条件。

Q8。 KVC与KVO?

回答键值编码(KVC)表示使用字符串访问属性或值。

 id someValue = [myObject valueForKeyPath:@"foo.bar.baz"]; 

可能与以下内容相同:

 id someValue = [[[myObject foo] bar] baz]; 

键值观察(KVO)允许您观察对属性或值的更改。

要使用KVO观察属性,您将使用字符串将属性标识为; 即使用KVC。 因此,可观察对象必须符合KVC。

 [myObject addObserver:self forKeyPath:@"foo.bar.baz" options:0 context:NULL]; 

Q9。 什么是自动释放池,自动释放池,有多少个自动释放池?

回答 :在一个引用计数的环境(与使用垃圾回收的环境相对)中, NSAutoreleasePool对象包含已接收到autorelease消息的对象,并且在耗尽后将向每个这些对象发送release消息。 因此,向对象发送autorelease而不是release ,至少可以延长该对象的寿命,直到耗尽池本身为止(如果随后保留该对象,则可能会更长)。 一个对象可以多次放入同一个池中,在这种情况下,每次将对象放入池中时都会收到release消息。

Application Kit在事件循环的每个循环的开始在主线程上创建一个自动释放池,并在结束时将其耗尽,从而释放在处理事件时生成的任何自动释放对象。 因此,如果使用应用程序套件,则通常不必创建自己的池。 但是,如果您的应用程序在事件循环中创建了许多临时的自动释放对象,则创建“本地”自动释放池以帮助最大程度地减少峰值内存占用可能是有益的。

Q10。 ARC如何工作?

回答 :每次创建类的新实例时,ARC都会分配一块内存来存储有关该实例的信息。 该内存保存有关实例类型的信息,以及与该实例关联的任何存储属性的值。

此外,当不再需要某个实例时,ARC会释放该实例使用的内存,以便该内存可用于其他目的。 这样可以确保不再需要类实例时,它们不会占用内存空间。

但是,如果ARC要取消分配仍在使用的实例,则将无法再访问该实例的属性或调用该实例的方法。 实际上,如果您尝试访问该实例,则您的应用很可能会崩溃。

为了确保实例在仍然需要时不会消失,ARC跟踪当前引用每个类实例的属性,常量和变量的数量。 只要仍存在至少一个对该实例的活动引用,ARC便不会取消分配该实例。

为此,无论何时将类实例分配给属性,常数或变量,该属性,常数或变量都会对实例进行强引用 。 引用被称为“强引用”,因为它在该实例上保持坚挺,并且只要该强引用仍然存在,就不允许对其进行重新分配。

Q11。 您是否使用过Operation和OperationQueue? 哪里? 什么是操作类的被覆盖的api?

回答 :因为Operation类是一个抽象类,所以您不直接使用它而是使用子类或使用系统定义的子类之一( NSInvocationOperationBlockOperation )执行实际任务。

替代方法

对于非并行操作,通常只覆盖一种方法:

  • main()

如果要创建并发操作,则至少需要重写以下方法和属性:

  • start()
  • isAsynchronous
  • isExecuting
  • isFinished

在并发操作中,您的start()方法负责以异步方式启动操作。 start()操作后,您的start()方法还应更新isExecuting属性报告的操作的执行状态。 您可以通过为isExecuting密钥路径发送KVO通知来执行此操作,该通知使感兴趣的客户端知道该操作正在运行。 您的isExecuting属性还必须以线程安全的方式提供状态。

完成或取消其任务后,并发操作对象必须为isExecutingisFinished键路径生成KVO通知,以标记操作状态的最终改变。

资料来源:https://developer.apple.com/documentation/foundation/operation

Q12。 为什么我们使用ManageObjectContext,目的是什么?

回答NSManagedObjectContext :一个对象,代表单个对象空间或便签本,可用于获取,创建和保存托管对象。

  • 上下文是一个强大的对象,在被管理对象的生命周期中扮演着中心角色,负责从生命周期管理(包括故障)到验证,逆向关系处理以及撤消/重做的职责。
  • 受管对象上下文有一个父存储,它们从中检索代表受管对象的数据,并通过它们将更改提交给受管对象。
    在OS X v10.7和iOS v5.0之前,父存储始终是持久性存储协调器。 在macOS 10.7和更高版本以及iOS v5.0和更高版本中,父存储可能是另一个托管对象上下文。
  • 上下文在各个点发布通知,请参阅NSManagedObjectContextObjectsDidChange
  • 并发性:使用init(concurrencyType:)创建托管对象上下文时,其线程(队列)关联有两个选择
    1.专用队列( NSManagedObjectContextConcurrencyType.privateQueueConcurrencyType ):上下文创建和管理专用队列。
    2.主队列( NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType ):上下文与主队列相关联,并因此绑定到应用程序的事件循环中,但是在其他方面类似于基于私有队列的上下文。 您将此队列类型用于链接到仅在主线程上使用的控制器和UI对象的上下文。

资料来源:https://developer.apple.com/documentation/coredata/nsmanagedobjectcontext

奖励时间:DS问题

  1. 对每个数字求和,直到转换为一个数字?
  2. 给定根节点和需要删除的节点的ptr,编写用于删除为其指定ptr的节点的代码?

如有其他疑问,请查看以前的文章-2018/2019年度IOS面试常见问题解答

如果您有任何评论,问题或建议,请随时在下面的评论部分中发布它们! 您也可以在Medium上关注我以获取新文章,并在LinkedIn上与我联系。

参考文献

  1. https://softwareengineering.stackexchange.com/questions/105352/why-should-i-use-an-mvc-pattern
  2. https://stackoverflow.com/questions/1644453/why-mvvm-and-what-are-its-core-benefits
  3. https://www.quora.com/Why-must-the-UI-always-be-updated-on-Main-Thread
  4. https://developer.apple.com/documentation/objectivec/nsobject/1418815-load
  5. https://medium.com/@kostiakoval/load-vs-initialize-a1b3dc7ad6eb
  6. https://developer.apple.com/documentation/objectivec/nsobject/1418639-initialize
  7. https://www.quora.com/Is-recursion-faster-than-loops
  8. https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH
  9. https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html