苹果在2014年的年度开发者大会上推出了Swift编程语言,这令开发人员社区感到惊讶。 该公司对Swift持认真态度,这不是实验。 Swift的目标是为Apple平台提供下一代应用程序。
先决条件
程式设计
一两篇文章不可能涵盖编程的基础知识和学习Swift。 因此,我假设您已经有一些编程经验。 Ruby,PHP或JavaScript是学习Swift的良好起点。 如果您来自Web开发背景,那么通过阅读下面的两篇文章,学习Swift的基础应该不会有问题。
Swift
在接下来的两篇文章中,我将向您展示Xcode 6中引入的游乐场功能。我们还将介绍Swift编程语言的基础知识,例如变量,常量和数据类型,包括集合,数组和字典。
您还将学习类和结构的基础知识。 在下一篇文章中,我们将放大闭包,函数,协议和访问控制。 这应该使您对语言有足够的了解,以完成本系列的其余部分。
物镜
严格来说,如果您有兴趣为iOS平台开发,则不需要C和Objective-C。 也就是说,我们将用于开发iOS应用程序的大多数框架都是用C和Objective-C编写的。 这意味着我偶尔会谈论C和Objective-C。 不过,请放心,我将确保您了解使自己步入正轨并成为iOS开发人员的一切必要条件。
Xcode和Swift
在整个系列中,我将使用Xcode 7.1和Swift 2.1 。 如果您使用的是旧版本的Xcode,请记住您将无法使用Swift 2.1。 Swift继续快速变化,语法随着语言的每次迭代而发展。 因此,我建议使用包含Swift 2.1的Xcode 7.1。
1.游乐场
2014年,Apple引入了Xcode 6的一部分作为运动场。运动场非常适合学习Swift编程语言。 使用运动场,您可以专注于正在编写的代码,而不会弄乱项目设置,文件和文件夹。
让我们创建一个操场来开始学习Swift的基础知识。 启动Xcode 7.1,然后从Xcode的“ 文件”菜单中选择“ 新建”>“游乐场...” 。 游乐场支持OS X,iOS和tvOS。 将平台设置为iOS并命名游乐场 简而言之Swift 。
告诉Xcode您想在哪里保存游乐场,然后单击“ 创建” 。 乍一看,游乐场似乎是一个带有.playground扩展名的简单文件,但实际上它是一个包含少量文件的文件夹。 幸运的是,这不是我们需要担心的事情。 游乐场比带有许多文件和文件夹的Xcode项目要容易得多。
游乐场的用户界面简洁明了。 您可以在左侧看到代码编辑器,在右侧看到输出。 Xcode已经用三行代码填充了操场。 如果您已阅读上一教程,则第一行看起来应该很熟悉。
//: Playground - noun: a place where people can play
该行以两个正斜杠//
开头,表示该行是注释,编译器将其忽略。 跨越多行的注释以/*
开头,以*/
结尾。
/*
This is a longer
comment spanning
multiple lines.
*/
Xcode还为UIKit框架添加了import语句。 UIKit是iOS开发中最重要的框架。 它定义了构建iOS应用程序的基础。 在Swift中,导入框架就像使用import
关键字和框架名称UIKit一样简单。
import UIKit
最后一行可能会让您想起JavaScript。 我们使用var
关键字声明一个变量str
,并为其分配一个值"Hello, playground"
。 此示例立即显示Swift的一个关键功能, 类型推断 。
var str = "Hello, playground"
上面的示例有点误导。 您可能会认为Swift是一种弱类型语言,但事实并非如此。 str
变量的类型为String
。 Swift足够聪明,可以通过查看分配给它的值来推断str
的类型。
以下示例是等效的。 在此示例中,我们显式指定str
变量的类型。 变量名称后的冒号可以原样读取。
var str: String = "Hello, playground"
2.变量和常量
Swift还定义了let
关键字。 此关键字用于声明常量。 Swift编程语言鼓励在可能的情况下使用常量。 如果变量的值在其生存期内没有变化,则应为常数。 顾名思义,一旦给定常数一个值,就不能更改它。 在下面的示例中对此进行了说明。
在上面的示例中,我们声明一个常量message
并为其分配一个值。 往后几行,我们为message
常量分配一个新值。 因为我们尝试更改message
的值,所以编译器将引发错误。 幸运的是,编译器提出了解决此问题的建议,将message
常量变为变量。
3.数据类型
Swift定义了多种数据类型,但让我们看一下您会遇到的一些最常见的数据类型。
布尔值
让我们从一个简单的类型Bool
。 Swift中的布尔值与其他语言一样简单易用。 以下示例可能就像在Swift中一样简单。
let myBool = true
var notTrue = false
notTrue = true
号码
数字由Int
, UInt
, Float
或Double
。 还有其他用于存储数字值的数据类型,但这是最常见的数据类型。 这些数据类型类似于您在其他编程语言中找到的数据类型。
由于Swift是一种强类型语言,因此您需要时常处理类型转换。 例如,不可能将Int
和Float
相乘。 请看以下示例,以更好地理解问题。
最初,这似乎是Swift语言的主要缺点。 事实是,这种行为是大多数强类型语言所固有的。 幸运的是,解决方案很简单,如下所示。
尽管它可能看起来好像我们铸造a
到一个Float
,这不是发生了什么。 我们正在创造或初始化Float
使用存储在值a
。
有两种创建变量或常量的方法,即文字语法和初始化器语法 。 常量a
和b
是使用文字语法创建的。 我们前面讨论的str
变量是文字语法的另一个示例。
要创建一个Float
从存储在值a
,我们使用的初始化程序语法。 我们创建Float
使用类型的名称, Float
,后面两个括号,在传递a
作为参数。
弦乐
在本教程中,我们已经遇到了一些字符串。 字符串不过是一个字符序列。 实际上,可以访问字符集合,如下例所示。
let city = "Brussels"
let chars = city.characters
在上面的示例中,我们使用字符串文字。 下一个示例说明如何使用String
类型的初始化程序。 语法与在前面有关数字和类型转换的示例中看到的语法相同。
let country = String("Belgium")
馆藏
Swift标准库定义了三种常见的集合类型: Array
, Dictionary
和Set
。 如果您熟悉Objective-C或任何其他编程语言,则这些收集类型几乎不需要解释。 在某些语言中,字典称为哈希,而数组称为列表。 但是,想法是相同的。
let myArray = [1, 2, 3, 4, 5]
let myDictionary = ["One": 1, "Two": 2, "Three": 3]
let mySet = Set(["One", "Two", "Three", "Four", "Five"])
数组和字典使用文字语法初始化。 因为Set
类型没有文字语法,所以我们使用初始化语法创建mySet
常量。
我已经提到过,Swift是一种强类型语言,这对集合类型也有影响。 以下示例说明了这一点。 我们首先创建一个[Int]
类型的变量arr1
。 这意味着arr1
只能包含Int
类型的值。
第二和第三句话证实了这一点。 附加整数可以很好地工作,但是附加字符串会导致编译器错误。 编译器尝试将"Two"
转换为Int
,但无法这样做。 结果是一个错误。
以下示例会使情况更加混乱。 为何编译器不抱怨包含不同类型值的数组? 原因可能会让您感到惊讶。 arr2
常量的类型为[AnyObject]
。
let arr2 = [1, 2, 3, "Four", "Five"]
Any
和AnyObject
Swift标准库定义了两种特殊类型, Any
和AnyObject
。 Any
类型可以表示任何类型,而AnyObject
类型可以表示任何类或结构。 如果您感到困惑,那完全正常。 Swift设计为强类型化,似乎Any
和AnyObject
破坏了Swift的类型安全性。
引入Any
和AnyObject
原因主要是出于兼容性原因。 我已经提到过,用于Cocoa开发的大多数框架都是用C和Objective-C编写的。 Objective-C定义了代表任何对象的id
类型。 为了确保Swift和Cocoa框架可以一起工作,Swift标准库引入了Any
和AnyObject
类型。 当我们开始使用Cocoa框架时,我们将学到更多有关此的知识。
4.类和结构
班级
如果您熟悉面向对象的编程,那么您应该已经熟悉类。 在Swift中,类非常普通。 看看下面的例子中,我们定义一个类, Boat
,具有两个属性, speed
和lifeboats
,和一种方法, deployLifeboats()
class Boat {
var speed: Float = 0
var lifeboats: Int = 2
func deployLifeboats() {
// ...
}
}
初始化和修改Boat
类的实例非常简单,如下所示。 在实例上调用方法也不是不可思议的。 Swift类的基础很容易理解。 对?
var boat = Boat()
boat.speed = 10.5
boat.lifeboats++
boat.deployLifeboats()
结构体
现在让我们创建一个看起来与Boat
类非常相似的结构,并找出在Swift中将类和结构区分开来的原因。
struct Ship {
var speed: Float = 0
var lifeboats: Int = 2
func deployLifeboats() {
// ...
}
}
以下示例揭示了Swift类和结构之间最重要的区别。
此示例说明了类是通过引用传递的,而结构是通过值传递的。 那是什么意思? 我们初始化了一个Boat
实例,将其分配给boat1
,并将其speed
属性设置为11.0
。 我们将boat1
分配给boat2
。 这意味着boat2
引用了boat1
。 boat1
和boat2
指向同一个Boat
实例。 其结果是,设置speed
的财产boat2
还修改了speed
的属性boat1
。
对于结构而言并非如此。 我们使用Ship
结构重复相同的步骤。 最终结果却有所不同。 通过将ship1
分配给ship2
,可以复制ship1
的值并将其存储在ship2
。 这意味着ship1
和ship2
指向不同的对象, Ship
结构的不同实例。 这是一个非常重要的概念,因此请确保在继续操作之前先了解一下。
后果
已经向您介绍了Swift标准库定义的常见数据类型。 在那个讨论中我没有提到的是,到目前为止,我们讨论的每个Swift数据类型都是一个结构。
例如,Swift中的每个集合类型都是一个结构。 每种数字类型都是一个结构。 知道和理解这一点很重要,特别是如果您来自通过引用传递某些类型的语言(例如Ruby和Objective-C)。
更多差异
在Swift中,还有许多其他区别将类和结构区分开。 类支持继承,而结构不支持。 在下面的示例中,我们定义了一个从Boat
类继承的Speedboat
类。 Boat
类是Speedboat
的父类或超类。
class Speedboat: Boat {
}
var speedboat = Speedboat()
speedboat.speed = 100.0
speedboat.lifeboats = 0
speedboat.deployLifeboats()
由于Boat
是Speedboat
的父类,因此Speedboat
继承了Boat
类中定义的属性和方法。 该示例说明了这一点。 尽管实施Speedboat
类是空的, Speedboat
实例, myBoat
,具有speed
和lifeboats
性能以及一个deployLifeboats()
方法。
使类和结构区分开的另一个更细微的区别是在运行时进行类型检查。 您可以在运行时检查类实例的类型,而对于结构实例则不能。
5.可选
可选是Swift编程语言不可或缺的一部分。 让我们找出什么是可选的,以及为什么它们如此重要。 必须先初始化变量,然后才能使用它。 请看以下示例,以了解其含义。
var str: String
str.isEmpty
如果您习惯于使用其他编程语言的字符串,那么您可能会对编译器抛出错误感到惊讶。 让我们看看该错误告诉我们什么。
在许多编程语言中,变量具有初始默认值。 例如,在Objective-C中,以下代码段中的字符串等于nil
。
NSString *newString;
什么是可选的?
Swift使用可选选项来封装一个重要的概念,变量或常量具有值或没有值。 在Swift中就这么简单。 要将变量或常量声明为可选的,我们在变量或常量的类型后附加一个问号。
var str: String?
变量str
不再是String
类型。 现在它是可选 String
类型的。 了解这一点很重要。 结果是我们不能再直接与str
的值进行交互。 该值安全地存储在可选变量中,我们需要询问可选变量封装的值。
强制展开
访问可选值的一种方法是强制展开可选项。 我们可以通过添加!
来访问str
的值!
到变量的名称。
var str: String?
str = "Test"
println(str!)
重要的是,在强制打开可选选项时,请确保该可选选项包含一个值。 如果您强制解开一个没有值的可选值,Swift会引发错误并导致应用程序崩溃。
可选装订
有一种更安全的方法来访问可选值。 以下示例说明了如何安全访问存储在str
类型str
的值String?
。
var str: String?
if str != nil {
println(str!)
} else {
println("str has no value")
}
在打印其内容之前,我们首先检查str
是否等于nil
。 在此示例中, str
没有值。 这意味着它不会被意外打开。
有一种更优雅的方法称为可选绑定。 在下面的示例中,我们将存储在optional中的值分配给一个临时常量。 可选str
值绑定到常量strConst
并在if
语句的if
子句中可用。 这种方法也适用于while
语句。
var str: String?
str = "Test"
if let strConst = str {
println(strConst)
} else {
println("str has no value")
}
什么是nil
?
如果您来自像Objective-C这样的语言,那么您肯定会知道nil
是什么。 在Objective-C中, nil
是指向不存在的对象的指针。 Swift对nil
的定义有些不同,因此了解差异非常重要。
在Swift中, nil
表示不存在任何值。 虽然nil
仅适用于Objective-C中的对象,但在Swift中nil
可用于任何类型。
您是否错过了分号?
您是否注意到本教程的示例中未使用任何分号? 在Swift中,不需要使用分号,因为编译器足够聪明,可以理解一条语句何时结束而另一条语句何时开始。 如果您确实想念使用分号,则可以添加它们。 但是请记住,语言指南建议省略分号。
结论
即使我们只是在本教程中进行了初步介绍,您现在也对Swift编程语言有了基本的了解。 在下一个教程中,我们将探讨语言,闭包和函数的另一个关键组成部分。 我们还将讨论协议和访问控制。
如果您有任何问题或意见,可以将其留在下面的评论中,或通过Twitter与我联系。
翻译自: https://code.tutsplus.com/tutorials/ios-from-scratch-with-swift-swift-in-a-nutshell--cms-25168