iOS 2018系列:破解iOS采访或成为iOS专家(6)

第6章:DispatchGroup和OperationQueue

最近,我不得不做一堆异步任务,我只想在所有任务完成时得到通知。 该博客将介绍两种简单的方法:DispatchGroup和OperationQueue。 在这篇文章中,我们将同时介绍它们。

派遣组

如果您正在开发一个不使用Operations的项目,并且不想重构任何现有代码,则DispatchGroup是一个功能强大的API,可以将这些任务组合为一个任务。

情况1 :计算三个不同线程上三个数组的总和,一旦所有线程完成其执行,我想使用该结果。

在考虑解决方案之前,让我们学习一些与调度组相关的API。

enter () —明确指示一个块已进入该组。

leave () -明确表示该组中的一个块已经完成。

func notify (qos:DispatchQoS =默认值,标志:DispatchWorkItemFlags =默认值,队列:DispatchQueue,执行工作:@escaping @convention(block)()-> Swift.Void)–
当一组先前提交的块对象完成时,将要计划的块调度到具有指定服务质量类和配置的队列中。

解决方案 :这三个API将帮助我处理上述情况,让我们学习如何使用它们。

我在下面写了添加数组元素并返回的函数

此函数使用DispatchQueue.global()。async创建线程,并使用DispatchQueue.concurrentPerform创建循环以添加infoArr的所有元素(类似于for循环),然后返回名为block()的完成处理程序

下面的函数将创建三个并行计算总和的线程,一旦线程完成,它将调用dispatchgroup的notify函数。

调用notify函数后,我们将拥有所有三个数组的和,并且我们可以将其传递给completeizationBlock()。

操作和操作队列

它是一个抽象类,您需要对其进行子类化才能使用。 如果您只想执行一小段代码或调用一个方法,则可以使用BlockOperation和NSInvocationOperation代替子类化Operation。

情况2:使用操作计算三个不同线程上三个数组的总和,一旦所有线程完成其执行,我都想使用该结果。

解决方案:创建OperationQueue实例以添加操作,创建三个BlockOperation以添加数组的总和,然后在操作之间添加依赖项(因为我们需要获得实际上不依赖的最终总和),一旦我们以任何顺序将这三个块操作添加到操作队列中,这无关紧要,在第三块上注册完成块以获取最终总和。

输出:下图显示-调用块的顺序和最终求和结果

有障碍的并发队列

并发队列中的任务可以任何顺序执行,并且可以同时启动。 与上述串行队列相比,这是非常快的。 但是,由于我们可能在写书的同时阅读,所以我们会遇到读者-作家问题。

如果有一种方法可以确保在读取时不进行写入操作,而在使用并发写入时不进行读取操作,该怎么办? 好吧,有一种方法可以使用带有Barrier的Concurrent Queue 。 如果我们采用上面的并发代码,并为写操作插入一个障碍,那么我们将确保在执行队列中的所有读取之后进行写操作,并且确保在写入时不会发生任何读操作。

使用带有障碍的并发队列可以帮助我们改善和加快代码的速度,同时消除读写器问题,这对于单例来说也很重要。

奖励时间:#import和@class之间的区别

“ #import”将整个有问题的头文件带入当前文件; 还包括该文件#imports的所有文件。

另一方面@class (当单独使用带有某些类名的行时)告诉编译器“嘿,您很快就会看到一个新令牌; 这是一堂课,所以要这样对待)。

当您有可能使用“ 圆形包含 ”时,这非常有用。 即,Object1.h引用了Object2,而Object2.h引用了Object1。 如果将#import both文件都导入到另一个文件中,则编译器可能会在尝试导入Object1.h,查找其中并看到Object2.h时感到困惑。 它尝试#import Object2.h,并看到Object1.h,依此类推。

另一方面,如果每个文件都具有@class Object1, @class 0。 或@class Object2;,则没有循环引用。 只需确保实际上#import所需的标头到您的实现(.m)文件中。

变异关键字

从实例方法中修改值类型

结构和枚举是类型。 默认情况下,不能从其实例方法中修改值类型的属性。

但是,如果需要在特定方法中修改结构或枚举的属性,则可以选择对该方法进行行为更改。 然后,该方法可以从方法内部更改(即更改)其属性,并在方法结束时将其所做的任何更改写回到原始结构。 该方法还可以为其隐式的self属性分配一个全新的实例,并且该新实例将在方法结束时替换现有实例。

您可以通过将mutating关键字放在该方法的func关键字之前来选择这种行为

希望您能从中学习到Goto Core Data。