更新于2014年7月22日 基于Xcode6-beta 4的系列更新
Swift是苹果公司今年在WWDC新推出的标牌语言。伴随着这门语言, 苹果公司给出了参考文档 Swift reference guide ,我强烈建议大家去学习下。
然而,该参考文档很长!所以,如果你没有足够多的时间,或者你想快速的学习Swift,那么这篇教程很适合你。
这篇Swift教程将历时15分钟左右,它将引领你快速浏览Swift语言,内容包括变量,控制流,类,最佳实践,以及更多。
在学习的历程中,你甚至可以做个方便的小费计时器。
这篇教程,我们需要最新版本的Xcode(写这篇教程时,最新版本是Xceode 6-Beta版)。你并不需要有Swift或者Objective-C开发经验,但是如果你有开发经验会更好些。
注:在写这篇教程时,我们的理解是,因为Xcode 6仍然是beta版,所以我们不能提供截图。因此直到我们确定可以提供截图为至在这篇教程中我们将不提供截图。
Playgrounds介绍
打开Xcode 6,前往File\New\File.选择iOS\Source\Playground, 点击下一步。
为文件命名为 SwiftTutorial.playground, 单击下一步,保存文件至合适的位置。删除文件所有内容,以确定我们有一个全新的开始。
注:创建playground之后,我们将得到一个错误提示,Error running playground: Failed to prepare for communication with playground”。如果这种情况发生,关闭Xcode然后重启,这个错误就会消失了。
playground一个新的文件类型,它帮我们测试我们的Swift代码,并将每行的测试结果在侧边栏显示出来。例如,添加下面代码至playground:
let tutorialTeam = 56 let editorialTeam = 23 let totalTeam = tutorialTeam + editorialTeam |
当我们写下这些代码,我们将在侧边栏看到测测试结果。很方便,不是吗?
Playgrounds是学习Swift(就像你在这篇教程里正在做的一样),检验新的APIs,原型代码或算法,使我们的代码可视化的很好的方法。在接下来的教程中,我们将在playground下工作。
注:关于这点,我同样建议我们把playground文件(SwiftTutorial.playground) 拖拽到OS X的Dock。然后每当我们想测试我们的Swift代码,我们就可以快速使用这个文件了。
Variables vs. Constants in Swift
添加如下代码至playground的底部:
totalTeam += 1 |
添加这一行后你将发现会报错误。这是因为totalTeam是常量,它的值不可修改。我们以关键词let声明常量。
我们想要把tutorialTeam设置为值可变的变量,所以我们需要用另外一个关键字var去声明它。
用下面代码取代totalTeam的初始化:
var totalTeam = tutorialTeam + editorialTeam |
现在代码无误了。我们会想,“为什么不把所有的都设为变量呢,仅仅因为这样不够严格?”
额,以let声明常量自有其好处的,它可以是编译器最优化变现,编译器不用再格式转换了。因此,该有let就用let!
Explicit vs. Inferred Typing
目前为止,我们还没有显示的为这些常量变量设置类型,因为编译器拥有足够的信息推断出该怎样自动处理。
例如,我们设置tutorialTeam为56,编译器知道56是整型,所以它自动设置tutorialTeam为int型。
然而,如果我们想,我们也可以显示设置。用下面代码取代设置tutorialTeam的那行代码。
let tutorialTeam: Int = 56 |
我们可能想是否需要显示设置类型,或者让编译器为我们推断类型。我们相信让编译器尽可能的为我们自动推断类型是比较好的,因为这样我们就可以体验到Swift的一个主要优势:代码简洁且宜读。
因为这些,改变之前的推断类型:
let tutorialTeam = 56 |
Basic Types and Control Flow in Swift
现在为止,我们已经看到了Int的一个例子。Int在Swift中用来标识 integer类型,但是Swift中除了Int还有很多类型。
Floats and Doubles
let priceInferred = 19.99 let priceExplicit: Double = 19.99 |
有两种类型可以定义带小数点的十进制类型:Float
和 Double。
Double 有更好的精度,而且是推断类型的默认选择。也就意味着priceInferred也是Double类型。
Bools
let onSaleInferred = true let onSaleExplicit: Bool = false |
要注意在Swift中我们使用true/false作为布尔值,不像在Objective-C那样使用YES/NO。
Strings
let nameInferred = "Whoopie Cushion" let nameExplicit: String = "Whoopie Cushion" |
字符串,就像你所期望的,不再像在Objective-C那样使用@标记。这可能会使我们很不习惯,要慢慢适应了。
If statements and string interpolation
if onSaleInferred { println("\(nameInferred) on sale for \(priceInferred)!") } else { println("\(nameInferred) at regular price: \(priceInferred)!") } |
这是个像其它语言一样的if语句例子。条件语句中的大括号是可选的,而即使只有一行代码括号也是必须的。
这里也展示了一个名唤字符串插值的新技术的例子。在Swift中,当你想替代字符串中某些东西,就用这样的语法 \(your expression)
.
这里,我们也许想知道println代码输出去哪儿了,想看println输出,打开助理编辑,像这样 View\Assistant Editor\Show Assistant Editor.
这是这篇教程目前为止的工程 playground file .
Classes and Methods
在Swift开发中一个很平常的事就是我们要创建类和方法。让我们现在看看怎么弄!
首先,删除playground文件中所有代码,确保我们有一个干净的开始。
接下来,我们将创建一个小费计时器类,这个类用来指出在餐厅里我们该如何付小费。我们将一次只写一点代码,每步辅以解释。
// 1 class TipCalculator { } |
创建类,键入class关键字,然后命名我们的类。我们给该类添加了两个大括号。
如果我们子类化另外一个类,我们需要添加a :
然后我们正在子类化的类名。注意我们没有必要什么都子类化(不像在Objective-C中我们必须让类继承于NSObject或者其子类)。
添加如下代码至大括号内:
// 2 let total: Double let taxPct: Double let subtotal: Double |
这是创建类的属性,像创建变量和常量的方式一样。这里我们创建了三个常量属性–一个用作小费的总数(税后),一个用作标示税_收所占小费比例,一个用作小费的小计(税后)。
注意,我们声明的属性在声明的时候或者实例化的时候必须设置初始值。不然我们必须声明它们为可选型(之后教程会详细介绍)。
注:根据 Emily Post Etipedia,小费应当是税前的。这就是为什么该类在提交小费之前计算税前数量。
在前面的块儿之后添加如下代码(在大括号之内):
// 3 init(total:Double, taxPct:Double) { self.total = total self.taxPct = taxPct subtotal = total / (taxPct + 1) } |
这里为类创建了实例化,类含有两个参数。在Swift中初始化总是命名为init –如果需要,我们可以不仅仅只有一个初始化,但是每个初始化必须使用不同的参数。
注意,我们给方法的参数类的属性同样的名字。因为这儿,我们需要在属性前添加self关键字以此区分方法的参数类的属性。
因为没有和subtotal属性冲突的名字,所以我们不需要在其之前添加self关键字,编译器会自动推断。相对酷,是不?!
subtotal = total / (tipPct + 1)
calculation comes from:
(subtotal * taxPct) + subtotal = total subtotal * (taxPct + 1) = total subtotal = total / (taxPct + 1) |
Thanks to @chewbone for pointing this out!
在上面代码之后继续添加如下代码(写在大括号之内):
// 4 func calcTipWithTipPct(tipPct:Double) -> Double { return subtotal * tipPct } |
我们使用func关键词声明方法。然后我们列出参数(我们必须显示出类型),添加->符号,最后列出返回类型。
这是决定小费多少的类,subtotal乘以tip percentage,就是如此简单。
继续添加如下代码(写在大括号内):
// 5 func printPossibleTips() { println("15%: \(calcTipWithTipPct(0.15))") println("18%: \(calcTipWithTipPct(0.18))") println("20%: \(calcTipWithTipPct(0.20))") } |
这是一个新方法,它打印出三种可能的tips.
注意,当我们在类的实例中调用方法的时候,第一个参数不用给出名字(但是其它的需要)。
同样注意,字符串插值不仅限于打印出变量。如果我们乐意,我们可以有各种更加复杂的方法调用以及内嵌操作。
在playground最后添加如下代码(在大括号之内):
// 6 let tipCalc = TipCalculator(total: 33.25, taxPct: 0.06) tipCalc.printPossibleTips() |
最后,我们创建一个小费计算器的实例,该实例调用方法打印可能的小费。
现在playground应该看起来像现在这样:
// 1 class TipCalculator { // 2 let total: Double let taxPct: Double let subtotal: Double // 3 init(total:Double, taxPct:Double) { self.total = total self.taxPct = taxPct subtotal = total / (taxPct + 1) } // 4 func calcTipWithTipPct(tipPct:Double) -> Double { return subtotal * tipPct } // 5 func printPossibleTips() { println("15%: \(calcTipWithTipPct(0.15))") println("18%: \(calcTipWithTipPct(0.18))") println("20%: \(calcTipWithTipPct(0.20))") } } // 6 let tipCalc = TipCalculator(total: 33.25, taxPct: 0.06) tipCalc.printPossibleTips() |
检查助理编辑器结果。
Arrays and For Loops
到目前为止,上面的代码有一些重复,我们以不同小费比率调用了calcTipWithTotal方法几次。我们可以使用array减少重复。
使用以下代码取代printPossibleTips的内容:
let possibleTipsInferred = [0.15, 0.18, 0.20] let possibleTipsExplicit:[Double] = [0.15, 0.18, 0.20] |
这里展示了一个创建推断型和显式型doubles型数组的例子。 [Double]
是Array<Double>的缩写。
然后在下面继续添加如下代码:
for possibleTip in possibleTipsInferred { println("\(possibleTip*100)%: \(calcTipWithTipPct(possibleTip))") } |
在数组中枚举内容就像在Objective-C中快速枚举,只是这里不需要分号。
我们也可以像这样写循环:
for i in 0..<possibleTipsInferred.count { let possibleTip = possibleTipsInferred[i] println("\(possibleTip*100)%: \(calcTipWithTipPct(possibleTip))") } |
<运算符是一种非包容性的范围操作符,不包括上界值。还有一个...运算符是包容性的。
数组有一个数量属性,该属性标志数组中内容个数。我们也可以在数组中定位某个特定的元素,像这样arrayName[index]
。
Dictionaries
让我们为我们的小费计算器做最后的修改。取代仅仅打印小费,我们返回一个包含结果的字典。这使得在某些用户界面的应用程序中更容易将结果显示出来。
删除printPossibleTips方法,以如下方法更新:
// 1 func returnPossibleTips() -> [Int: Double] { let possibleTipsInferred = [0.15, 0.18, 0.20] let possibleTipsExplicit:[Double] = [0.15, 0.18, 0.20] // 2 var retval = Dictionary<Int, Double>() for possibleTip in possibleTipsInferred { let intPct = Int(possibleTip*100) // 3 retval[intPct] = calcTipWithTipPct(possibleTip) } return retval } |
让我们一点点来分析:
- 我们标记方法返回类型为字典,key类型为Int(小费比率是整型,如15或20),value类型为Double(计算小费)。
[Int: Double]
是Dictionary<Int, Double>的缩写。 - 创建一个空字典。因为要修改字典值,我们应该设置字典类型为可变字典(使用var)而不是常量(像let)。不然我们将得到编译错误。
- 给字典添加项,很像Objective-C语法。
最后,修改playground最后一行,调用该方法:
tipCalc.returnPossibleTips() |
Once the playground evaluates, you should see the results as a dictionary in the inspector (click the eyeball for an expanded view).
一旦playground评估,我们在检查器应该看到返回值为字典的结果(点击eyeball看扩展视图)。
O(∩_∩)O哈哈~,就是这了–恭喜!使用Swift我们已经有了一个完全的高效的小费计算器。
Where To Go From Here?
这是最终这篇教程的最终demo final playground file.
想要学更多?那么接着读下篇( next part of this series)吧!下篇我们将学习如何为该应用创建用户界面。或者点击我的新书new Swift books!
希望这篇教程让您享用了。欢迎来到Swift世界!:]
再次做翻译,感觉翻译真不易哦!翻译出来容易,翻译成经典就太难了!鉴于目前个人能力所限,不免有误。望读到的朋友指点扶正!