Swift多线程编程

时间:2022-04-14 02:31:30

Swift多线程编程

摘要:Swift日渐成为iOS的主流开发语言,并有取代Objective-C之势,本文通过实例介绍了Swift开发中使用GCD方案进行多线程开发的方法,从而将App开发中多线程、异步运行、定时器等实际需求的复杂性充分简化。

关键词:iOS;Swift;多线程

中图分类号:TP393 文献标识码:A 文章编号:1009-3044(2017)02-0024-02

iOS开发方兴未艾,越来越多的开发者关注并加入iOS开发的行列。传统上进行iOS开发的唯一编程语言是Objective-C,作为上世纪八十年代出现的语言,Objective-C在语法和机制上与大众熟知的C/C++、Java等现代编程语言大相径庭,尤其它“怪异”的语法使得学习难度较大,许多初学者甚至是有经验的开发者也经常对此抱怨吐槽。为了解决这种不协调性,Apple公司在经过深思熟虑之后,在2014年WWDC上了新一代开发语言Swift,这种全新设计的语言一经问世便广受开发者欢迎,短短2年的时间,Swift在TIOBE编程语言排行榜上就上升到第12位,市场份额直追Objective-C。众多分析均认为,根据Apple的战略思路,Swift取代Objective-C成为Apple平台的主打语言只是时间的问题。

众所周知,受限于设备的软硬件环境,App的开l难度要远远大于PC平台,为了在移动设备上完成一些丰富的功能,需要使用很多复杂的技术,多线程编程便是其中最为典型、最为普遍的一种,本文试图从Swift的角度,探讨其进行多线程开发的一些思路与方法。

无论是Android还是iOS的开发,都涉及一个几乎每个App都无法逃避的问题:UI和业务逻辑的并行运行。几乎所有的移动操作系统都不约而同地采用相同的架构:界面的更新必须在UI线程中进行,在UI以外的线程中更新界面都会造成软件的崩溃。这使得在移动平台上进行多线程开发变得更为复杂。

在iOS平台上,多线程开发基本上有三种思路:NSThread、NSOperation、GCD,三种方法各有优缺点,Apple官方推荐的是GCD方法。GCD 是用C语言开发并完整封装的多线程方案,通过使用 GCD,开发者可以利用简单的语法进行灵活的多线程编程。在多线程编程素有“复杂必死” 的名声,所以保持简单就是避免错误的金科玉律。在 Swift 中可以无缝使用 GCD 的 API 的,尤其得益于闭包特性的加入,使用起来比之前在 Objective-C 中更加简单方便。

关于GCD的介绍与教程有很多,初学者开始使用时往往被其复杂外表所吓退,其实GCD的使用非常简单,尤其是日常常见的多线程场景。GCD核心的概念是队列,我们需要在一个线程中执行某段代码时,只需要将这段代码提交给GCD的队列,剩下的线程的创建、调度、运行、销毁等操作,均由GCD帮我们自动完成。下面是一个简单的例子:

例1:

1 let gQueue : dispatch_queue_t =

dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 )

2 // 提交/派发到全局队列,GCD会负责线程调度

3 dispatch_async( gQueue,

4 {

5 sleep(5)

6 //在主线程中更改UI

7 dispatch_async(dispatch_get_main_queue(),

8 {

9 self.Label.text = "5秒钟过去的新消息"

10 })

11 }

行1声明了一个“全局队列”,供我们提交线程里运行的代码段。

行3使用dispatch_async来提交代码段到刚声明的队列中,async表示这是一个异步任务。

行7-10的代码段会由GCD自动创建一个新的线程,并在新线程中运行。

行7再次提交一个代码段,这个代码段并不是提交到刚才声明的全局队列中,而是提交到“主队列”,主队列对应App的主线程,即UI线程;这部分代码段完成的工作是刷新界面,而刷新界面的操作必须在主线程中完成。

在例1中,我们接触到GCD的几个基本概念:队列、提交,其中,队列分为三种:

1)主队列(main):使用dispatch_get_main_queue()获取,提交到主队列的代码段会在主线程中运行。

2)全局队列(global):使用dispatch_get_global_queue()获取,提交到全局队列的代码段将在新建线程中运行。

3)用户创建队列(create):使用dispatch_queue_create()创建,用户队列和全局队列的区别是:全局队列只有一个,提交的代码段(线程)是并行运行的;用户队列可以创建多个,提交的代码段(线程)是穿行运行的。

dispatch_async()用于将代码段提交到指定队列,开发者在提交之后就无须关心其他操作了,线程的创建、调度等操作均由GCD负责完成。

这个例子虽然简单,但这种结构却几乎可以占到实际开发中GCD使用的50%左右,所有需要在后台线程完成业务逻辑然后根据结果进行界面刷新的需求,皆可通过这种结构来完成。由此我们可以看到,通过GCD进行多线程编程是极其简单方便的,开发者唯一需要了解的就是GCD的一些基本概念。

在日常的开发工作中,我们经常会遇到这样的需求:在 xx 秒后执行某个方法。比如切换界面 1 秒后开始播放一段动画,或者提示框显示 3 秒后自动消失等等。在 Objective-C 中,我们可以使用一个 NSObject 的实例方法,-performSelector:withObject:afterDelay: 来指定在若干时间后执行某个selector。在Swift中,我们则可以利用NSTimer+GCD来完成这个工作,下面是完成这个需求的进行封装后的代码段:

例2:

import Foundation

typealias Task = (cancel : Bool) -> Void

func delay(time:NSTimeInterval, task:()->()) -> Task? {

func dispatch_later(block:()->()) {

dispatch_after(

dispatch_time(

DISPATCH_TIME_NOW,

Int64(time * Double(NSEC_PER_SEC))),

dispatch_get_main_queue(),

block)

}

var closure: dispatch_block_t? = task

var result: Task?

let delayedClosure: Task = {

cancel in

if let internalClosure = closure {

if (cancel == false) {

dispatch_async(dispatch_get_main_queue(), internalClosure);

}

}

closure = nil

result = nil

}

result = delayedClosure

dispatch_later {

if let delayedClosure = result {

delayedClosure(cancel: false)

}

}

return result;

}

有了以上的封b代码,当我们需要完成诸如“延迟3秒后做点什么事儿”的任务时,只需要简单地进行以下调用:

delay(2) { print("3秒后显示信息") }

这个例子虽然有点长,但是原理和结构与例1基本相同,只不过增加了dispatch_later()和dispatch_time()两个新的调用,理解了例1之后,例2也是很容易理解的。

综上所述,在进行Swift开发时,当遇到多线程、异步运行、定时器之类的需求时,我们都可以利用GCD这个利器来简化我们的工作,同时兼顾简单、快捷和优雅。当然,GCD的功能并不仅限于以上的介绍,熟练掌握GCD的应用,是成熟的iOS程序员必备的技能,每一个Swift开发者都应该将GCD放入自己的工具箱。

参考文献:

[1] Apple Swift官方文档: https:///swift/

[2] Grand Central Dispatch In-Depth: https:///60749/grand-central-dispatch-in-depth-part-1

[3] 欧阳坚. Swift开发实战权威指南[M]. 北京: 清华大学出版社, 2015.

上一篇:让孩子在情景中学语文 下一篇:“动态教学” 正确读时