Swift 权威指南

978-7-115-36847-8
作者: 李宁
译者:
编辑: 张涛

图书目录:

详情

本书除介绍了Swift语言开发必备的的语法、语言编程技术外,主要是结合大量的案例来讲解Swift的应用,通过贴近实战的案例讲解,尽快让读者达到学以致用的目标,让读者尽快进入实战角色,以便在工作中应用好Swift语言进行开发。

图书摘要

Swift权威指南
李宁 编著
人民邮电出版社

北京

前言

为什么要写这本书

由于苹果公司一直以来以生产硬件闻名,在2014年的WWDC上竟然发布了一种新的编程语言—— Swift。这一举动引起了业界不小的震动。在不到1 个月的时间里,Swift 就挤进流行语言前列,这在以前从未发生过。

Swift目前可用于开发iOS和OS X 平台的应用和游戏程序。但由于Swift刚诞生不久,中文资料还不多,而且由于 Swift 语言具有功能强大和效率开发高的特点,很有可能在将来取代Objective-C,成为iOS 和OS X平台上的主流开发语言。所以,为了让国内广大程序员能尽早掌握Swift开发技术,特意撰写了本书,以便可以让更多的人对Swift语言有所了解,更希望让更多的人成为国内乃至世界上第一批Swift语言专家。

本书的内容

Swift语言基础部分(第1章~第17章)主要介绍了Swift语言的基本语法,尤其是和其他语言不同的地方。项目实战部分(第18章~第20章)主要介绍了如何使用Swift语言开发iOS平台的应用和游戏,在最后一章还给出了一个Flappybird游戏以供大家学习Swift项目开发的全过程。

本书适合我吗

当您走进书店,看到书的标题中熟悉的字眼“Swift”,想了解这本书是否适合自己时,下面的提示对您的选购很有帮助:

● 您听说过iOS吗?

● 您知道App Store吗?

● 您听说过擅长做硬件的苹果公司居然推出了Swift开发语言了吗?

如果上述问题中有一个以上是肯定的,可以很高兴地告诉您,拿在手中的这本书确实是这个方向上的,下面需要进一步确认:

● 您对软件开发有经验或者有兴趣吗?

● 您对开发语言有了解吗?

● 您做过手机应用开发吗?

● 您是iOS或移动开发爱好者吗?

如果上述问题,您的回答中有肯定的,那么您已经具备了阅读本书需要的基础,不用担心读不懂了,那么:

● 您想快速了解并进入Swift应用开发吗?

● 您想找到一本系统介绍Swift开发的参考资料吗?

● 您想选择一本有原理剖析又有真实例子演示的教材吗?

● 您想选一本通俗易懂,符合自己阅读习惯的图书吗?

如上问题中,如果您有大多数回答都是肯定的,那么非常恭喜您,现在拿着的这本书差不多正是您需要的,可以放心地带回去开始自己的Swift之旅了。

如果还在犹豫,那么让下面几个提示告诉您,尽早开始学习的重要性:

● IT界中移动开发的热潮推动了移动互联网的快速发展,而Swift是一个非常强大的开发语言,其让您可以快速切入无线互联网领域;

● 在 App Store 发布应用的数量在快速增长,早日发布自己的 App 可以体现自己的开发价值和乐趣;

● 掌握了 Swift 开发就可以很快开发出供全球 iOS 用户使用的应用,有人已经在 App Store上赚到许多钱了!

本书的特点

● 国内第一本含金量超过Swift官方文档的原创图书。

● 第一本将Swift和最新的SpriteKit游戏引擎深度结合的原创图书。

● 实战性地讲解了Swift的开发技术和和技巧。

● 精彩游戏应用Flappybird让读者一览Swift项目开发全过程。

● 不仅介绍了Swift语言方面的知识,还结合了iOS应用和游戏开发进行讲解。尤其是讨论了基于SpriteKit的2D游戏开发技术。

● 推出了国内首套Swift视频课程:http://edu.51cto.com/course/course_id-1387.html。

● 随时提供答疑和完整资源下载:http://blog.csdn.net/nokiaguy。□ 从事iOS平台应用和游戏开发的程序员。

读者对象

□ 从事iOS平台应用和游戏开发的程序员。

□ 对Swift语言感兴趣的程序员。

□ 以前使用Objective-C,但想摆脱Objective-C繁琐的程序员。

□ 所有对新知识感兴趣的程序员。

源代码和工具下载

读者可以到作者的Blog:http://blog.csdn.net/nokiaguy下载相关的源程序和相关开发工具。

其他学习资源

由于目前Swift语言仍然是测试版,所以在读者拿到本书时,Swift的某些语法或API可能会有变化。为此,作者在51CTO上开了关于Swift的视频课程,这套教材会随着Swift的更新而不断更新。

视频地址:http://edu.51cto.com/course/course_id-1387.html。

勘误和支持

由于作者的水平有限,编写时间仓促,书中难免会出现一些错误或不准确的地方,恳请读者批评指正。如有问题或建议,请发送至 techcast@126.com 或在新浪微博(http://weibo.com/638012593)上留言。非常期待能够得到你们的真挚反馈。编辑联系邮箱为zhangtao@ptpress.com.cn。

致谢

感谢所有在本书写作过程中给予我指导、帮助和鼓励的朋友,尤其是人民邮电出版社的编辑,他们不仅对本书提出了宝贵的写作建议,而且还对本书进行了仔细的审阅。

感谢一直以来信任、鼓励、支持我的家人和朋友。

谨以此书献给我最亲爱的家人,以及众多热爱移动开发的朋友们!

第6章 丰富多彩的功能——函数

Swift语言为函数提供了丰富多彩的功能。但从功能上来说,Swift函数和其他语言的函数相比是非常强大的,在后面章节要介绍的方法与函数基本上一致。不过在本章先不讨论方法的细节,只介绍函数的各种功能和使用方法。

本章要点

□ 函数的定义和调用

□ 返回多种的函数

□ 扩展参数

□ 扩展参数和内部参数使用同一个名字

□ 默认参数值

□ 可变参数

□ 常量和变量参数

□ 输入/输出参数

□ 函数类型

□ 嵌套函数

6.1 函数的定义和调用

源代码文件:src/ch06/function/function/main.swift

Swift并不是纯的面向对象语言,所以和C++一样,支持函数。函数和方法的区别就是函数是全局的,而方法的作用域仅限于方法内。要想引用方法,必须先要引用包含该方法的对象。也可以将方法看成是定义在类中的函数。因此,函数和方法的定义规则基础一致。在后面讲到类时再详细讨论方法的细节。本节先来讨论如何定义一个函数。

不管是什么语言,函数都必须由下面几部分组成。

□ 函数名。

□ 返回值类型。

□ 函数的参数列表,在列表中包含参数名(形参)和参数类型。

□ 函数体。

定义Swift语言的函数也逃不出这几项。下面看一下Swift函数的语法形式。

func functionName(paramName1:paramType1, paramName2,paramType2,...) -> returnType

{

function body

}

很明显,Swift函数和C语言的函数在定义上差异很大。首先,Swift函数必须以func开头,然后跟着函数名,接下来是函数参数列表,最后是返回值类型。其中函数参数列表和返回值类型之间需要用“→”分隔。最后需要用一对花括号({...})将函数体括起来,这里面函数参数类型列表和返回值类型都是可选的。如果不指定函数参数列表,则函数没有参数,但必须在函数名后面指定一对圆括号。如果不指定返回值类型,则函数没有返回值,相当于C语言函数前面指定了void。

下面是一个标准的Swift函数的代码,该函数接收一个String类型的参数,返回一个String类型的值,最后调用了sayHello函数,并输出了函数的返回值。

func sayHello(personName: String) -> String

{

let greeting = "hello " + personName + "!"

return greeting

}

// 调用sayHello函数

println(sayHello("李宁"))

执行这段代码后,会输出如下内容。

hello 李宁!

下面是一些其他形式的函数(多个参数、没有参数、没有返回值)。

// 多个参数的函数

func add(a:Int, b:Int) -> Int

{

return a + b

}

// 调用add函数

println(add(20, 30))

// 没有参数,但又返回值的函数

func process() -> Float

{

return 3*20

}

// 调用process函数

println(process())

// 既没有参数,也没有返回值的函数

func method()

{

println("hello world")

}

// 调用method方法

method()

执行这段代码后,会输出如下内容。

50

60.0

hello world

6.2 返回多值的函数

源代码文件:src/ch06/function/function/main.swift

不管是数学上的定义,还是各种语言中的实现,函数都只能返回一个值,如果非要返回多个值,就返回一个对象,然后将要返回的值以字段、属性或方法形式体现,但这也是返回一个值。不过在Swift函数中,却彻底颠覆了我们对函数的印象。Swift函数是真真正正地可以返回多个值。

可能有的读者会想到,在前面学习数据类型时,有一个元组类型,这个类型可以同时表示多个值,难道函数返回的是这个类型的值?没错,Swift函数就是通过元组类型实现返回多个值的功能的。

其实函数返回元组类型和返回其他类型在写法上没什么区别,只是“→”后面需要用圆括号定义元组类型,定义方式如下。

(returnValue1:valueType1, returnValue2:valueType2,...)

下面是一个典型的返回元组类型的例子。在这个例子中,统计了一个字符串中有多少个元音字母,有多少个辅音字母,有多少个其他字符。很明显,这需要通过元组返回3个值。函数的实现调用代码如下。

func count(string: String) -> (vowels:Int, consonants:Int, others:Int)

{

var vowels = 0

var consonants = 0

var others = 0

for c in string

{

switch String(c).lowercaseString

{

case "a", "e", "i", "o", "u":

++vowels  // 元音计数器加1

case "b", "c", "d","f", "g", "h", "j", "k", "l", "m","n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":

++consonants // 辅音计数器加1

default:

++others  // 其他字符计数器加1

}

}

// 返回元组值

return (vowels, consonants, others)

}

// 调用count函数

let total = count("some arbitrary string!")

println("\(total.vowels) vowels and \(total.consonants) consonants")

执行这段代码,会输出如下内容。

6 vowels and 13 consonants

6.3 扩展参数

源代码文件:src/ch06/function/function/main.swift

我们发现,Swift 语言中的很多函数/方法在调用时不只是传入一个参数值,在前面还要跟一个有意义的英文名,该英文名和参数值之间用冒号(:)分隔。例如,Dictionary 有一个updateValue方法,该方法的第二个参数需要给一个forKey,然后才能传入参数值,调用形式如下。

dict.updateValue("飞机", forKey:21)

实际上,这个forKey就是扩展参数名,该参数也可以成为命名参数。也就是说,在定义函数时指定的参数名是函数内部使用的,可以成为函数的内部参数名。而为了让代码更容易理解,在定义函数时还为其指定了一个参数名,该参数名就是扩展参数名。只在调用函数时指定。定义扩展参数名也很简单,只需要在内部参数名之前指定扩展参数名即可,两侧参数之间用空格分隔。

例如,下面两个函数,前者(process)是没有扩展参数名的函数,后者(process1)是有扩展参数名的函数。我们可以观察它们在调用时的差别。

// 没有扩展参数名的函数

func process(p1: String, p2:Int) -> String

{

return "name:" + p1 + " age:" + String(p2)

}

process("bill", 20)

// 有扩展参数名的函数,其中name和age是扩展参数名,需要在调用时指定

func process1(name p1: String, age p2:Int) -> String

{

return "name:" + p1 + " age:" + String(p2)

}

// 调用process1函数,在调用时必须指定扩展参数名

println(process1(name: "Mike", age:17))

执行这段代码后,会输出如下的内容。

name:Mike age:17

注意

在使用扩展参数名调用函数时,不能将参数顺序写错了,否则无法成功编译 [1]

6.4 扩展参数和内部参数合二为一

源代码文件:src/ch06/function/function/main.swift

很多读者可能会抱怨,扩展参数是很好,但每次定义函数时都要为一个参数指定两个参数名,岂不是太麻烦了吗?别急!Swift已经考虑到了这一点,这就是将扩展参数和内部参数合二为一。其中做法很简单,只需要在内部参数名之前加一个井号(#)即可。

// name和age即时内部参数,又是扩展参数

func process2(#name: String, #age:Int) -> String

{

return "name:" + name + " age:" + String(age)

}

// 调用process2函数

println(process2(name:"Bill", age:30))

执行这段代码后,会输出如下的内容。

name:Bill age:30

6.5 默认参数值

源代码文件:src/ch06/function/function/main.swift

Swift函数支持对参数设置默认参数值 [2],当调用时不指定该参数值时,就会使用这个默认的参数值。默认参数值需要在实现函数时指定,直接在参数类型后面用等号赋值即可。下面是两个典型的使用默认参数值的函数的代码。

// 默认参数

func process3(name p1: String = "Mike", age p2:Int = 30) -> String

{

return "name:" + p1 + " age:" + String(p2)

}

// process3的两个参数都使用了默认参数值

println(process3())

// 只有第二个参数使用了默认参数值

println(process3(name:"John"))

func process4(name: String = "John", age:Int = 30) -> String

{

return "name:" + name + " age:" + String(age)

}

// 第二个参数使用了默认参数

println(process4(name:"Mike"))

6.6 可变参数

源代码文件:src/ch06/function/function/main.swift

可变参数必须是函数的最后一个参数,表示该参数可以传递任意多个值。在函数体中可以通过数组的方式读取这些值。定义的方法就是在参数类型后面加3个点(...)。这个定义方法和Java是相同的。

下面是使用可变参数的典型示例。

// strArray是可变参数

func process5(header:String, strArray:String...) -> String

{

var result = header

// 以数组的方式读取可变参数的值

for s in strArray

{

result += " " + s

}

return result

}

// 调用时最后一个参数可传递任意多个值("a","b","c","d"都是最后一个参数的值)

println(process5("bill", "a","b","c","d"))

执行这段代码,会输出如下内容。

bill a b c d

6.7 常量和变量参数

源代码文件:src/ch06/function/function/main.swift

Swift函数的所有参数默认都是常量,无法修改,如果要想修改参数,可以使用var将参数声明为变量。

// header参数是变量,可以在函数体内修改header的值

func process6(var header:String, strArray:String...) -> String

{

for s in strArray

{

header += " " + s

}

return header

}

println(process6("bill", "a","b","c","d"))

6.8 输入输出参数

源代码文件:src/ch06/function/function/main.swift

函数的参数都是值传递,即使参数是变量,在函数体内修改了参数值,当函数结束后,也不能将修改结果保留。如果要想利用参数传递值,可以用 inout 关键字将参数修改为输入输出参数。这样在函数体内修改该参数值后,当函数结束后,仍然可以保留修改的结构。

// name是输入输出参数

func process7(inout name:String, age:Int) -> String

{

name = "Mike"

return "Name:" + name + "Age:" + String(age)

}

var name:String = "bill"

println(process7(&name, 40));

// 输出name最后的值

println(name)

在传递输入输出参数值时应注意如下几点。

□ 指定输入输出参数值时必须使用变量,不能使用常量或值。

□ 指定变量时前面需要加&。

□ 在声明变量时,必须初始化。

}

6.9 函数类型

源代码文件:src/ch06/function/function/main.swift

Swift语言支持定义函数类型(类似于C语言的函数指针)。一个函数类型需要指定下面3个要素。

□ 函数参数个数。

□ 函数参数类型。

□ 函数返回值。

函数类型和其他数据类型的使用方法完全相同,在冒号(:)后面指定类型。定义函数类型时除了不需要指定参数名和函数体外,和函数定义完全相同。

下面的代码定义了两个函数类型变量(fun1和fun2)。

var fun1: (inout String, Int) -> String

var fun2: (String, String...) -> String

我们直接将符合要求的函数赋给对应的函数变量,例如,下面两个函数分别符合 fun1和fun2的要求,所以可以直接初始化这两个变量。

func myFun1(inout name:String, age:Int) -> String

{

return "name:" + name + " age:" + String(age)

}

func myFun2(var header:String, strArray:String...) -> String

{

for s in strArray

{

header += " " + s

}

return header

}

// 初始化fun1

fun1 = myFun1

// 初始化fun2

fun2 = myFun2

在调用时可以直接使用函数类型变量。例如,调用fun1和fun2的代码如下。

var name:String = "bill"

println(fun1(&name, 50))

println(fun2("Mike", "a","b"))

函数类型也可以作为函数的参数类型,这样就可以将外部函数传入另一个函数或方法,然后在方法中调用该外部函数了。这样可以很容易实现函数的多态。

// fun是函数类型参数

func myFun3(fun:(inout String, Int) -> String, str:String)

{

var name = ""

println(fun(&name, 40))

}

// 调用myFun3函数,fun1在前面的代码中已经定义了

myFun3(fun1, "hello")

当然,函数的返回值类型也可以是函数类型的,也就是说,函数可以返回另外一个函数。

func method1(n:Int) -> Int

{

return n*n

func method2(n:Int) -> Int

{

return 2*n

}

// myFun4的返回值是函数类型((Int) -> Int)

func myFun4(flag:Bool) -> (Int) -> Int

{

// 根据参数值返回method1或method2

return flag ? method1:method2

}

println(myFun4(true)(20))

println(myFun4(false)(20))

执行这段代码会输出如下的内容。

400

40

6.10 嵌套函数

源代码文件:src/ch06/function/function/main.swift

Swift函数还支持在函数内部嵌套定义函数,示例代码如下。

func myFun5(flag:Bool, m:Int, n:Int) -> Int

{

// method1为内嵌函数

func method1() ->Int{return m+n}

// method2为内嵌函数

func method2() ->Int{return m - n}

return flag ? method1() : method2()

}

println(myFun5(true, 10,20))

println(myFun5(false, 10,20))

执行这段代码,会输出如下的内容。

30

-10

6.11 小结

尽管函数不是一个程序中必须的要素,但有了函数,可以让代码更容易理解。函数是功能封装的最基本单元。在后面章节要介绍的类、方法、属性等元素都或多或少有一些函数的影子。

注 释

[1]. 个人认为Swift 应该加入这个功能,就是当使用扩展参数时可以改变参数的指定顺序。因为通过扩展参数名完全可以恢复正确的参数调用顺序。

[2]. 很多面向对象语言并不支持方法的默认参数,在这种情况下,可以使用方法的重载来实现默认参数值的功能。不过这仍然没有默认参数值方法。所以如果语言支持默认参数值,应尽量使用默认参数值。

相关图书

SwiftUI极简开发
SwiftUI极简开发
iOS 14开发指南【进QQ群414744032索取配套资源】
iOS 14开发指南【进QQ群414744032索取配套资源】
iOS 11 开发指南
iOS 11 开发指南
iOS和tvOS 2D游戏开发教程
iOS和tvOS 2D游戏开发教程
Swift 3开发指南
Swift 3开发指南
iOS  项目开发全程实录
iOS 项目开发全程实录

相关文章

相关课程