Swift hello world!Swift疾速入門教程。本站提示廣大學習愛好者:(Swift hello world!Swift疾速入門教程)文章只能為提供參考,不一定能成為您想要的結果。以下是Swift hello world!Swift疾速入門教程正文
平日來講,編程說話教程中的第一個法式應當在屏幕上打印“Hello, world”。在 Swift 中,可以用一行代碼完成:
println("hello, world")
假如你寫過 C 或許 Objective-C 代碼,那你應當很熟習這類情勢——在 Swift 中,這行代碼就是一個完全的法式。你不須要為了輸出輸入或許字符串處置導入一個零丁的庫。全局感化域中的代碼會被主動當作法式的進口點,所以你也不須要main函數。你異樣不須要在每一個語句開頭寫上分號。
這個教程會經由過程一系列編程例子來讓你對 Swift 有初步懂得,假如你有甚麼不睬解的處所也不消擔憂——任何本章引見的內容都邑在前面的章節中具體講授。
留意:為了取得最好的體驗,在 Xcode 傍邊應用代碼預覽功效。代碼預覽功效可讓你編纂代碼並及時看到運轉成果。Open Playground
簡略值
應用let來聲明常量,應用var來聲明變量。一個常量的值在編譯時其實不須要獲得,然則你只能為它賦值一次。也就是說你可以用常量來表現如許一個值:你只須要決議一次,然則須要應用許多次。
var myVariable = 42
myVariable = 50
let myConstant = 42
常量或許變量的類型必需和你賦給它們的值一樣。但是,聲明時類型是可選的,聲明的同時賦值的話,編譯器會主動揣摸類型。在下面的例子中,編譯器揣摸出myVariable是一個整數(integer)由於它的初始值是整數。
假如初始值沒有供給足夠的信息(或許沒有初始值),那你須要在變量前面聲明類型,用冒號朋分。
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70
演習:創立一個常量,顯式指定類型為Float並指定初始值為4。
值永久不會被隱式轉換為其他類型。假如你須要把一個值轉換成其他類型,請顯式轉換。
let label = "The width is"
let width = 94
let widthLabel = label + String(width)
演習:刪除最初一行中的String,毛病提醒是甚麼?
有一種更簡略的把值轉換成字符串的辦法:把值寫到括號中,而且在括號之前寫一個反斜槓。例如:
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."
演習:應用\()來把一個浮點盤算轉換成字符串,並加上或人的名字,和他打個召喚。
應用方括號[]來創立數組和字典,並應用下標或許鍵(key)來拜訪元素。
var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"
var occupations = [
"Malcolm": "Captain",
"Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"
要創立一個空數組或許字典,應用初始化語法。
let emptyArray = String[]()
let emptyDictionary = Dictionary<String, Float>()
假如類型信息可以被揣摸出來,你可以用[]和[:]來創立空數組和空字典——就像你聲明變量或許給函數傳參數的時刻一樣。
shoppingList = [] // 去逛街並買點器械
掌握流
應用if和switch來停止前提操作,應用for-in、for、while和do-while來停止輪回。包裹前提和輪回變量括號可以省略,然則語句體的年夜括號是必需的。
let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
if score > 50 {
teamScore += 3
} else {
teamScore += 1
}
}
teamScore
在if語句中,前提必需是一個布爾表達式——像if score { ... }如許的代碼是毛病的。
你可以一路應用if和let來處置值缺掉的情形。有些變量的值是可選的。一個可選的值能夠是一個詳細的值或許是nil,表現值缺掉。在類型前面加一個問號來標志這個變量的值是可選的。
var optionalString: String? = "Hello"
optionalString == nil
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
}
演習:把optionalName改成nil,greeting會是甚麼?添加一個else語句,當optionalName
是nil時給greeting賦一個分歧的值。
假如變量的可選值是nil,前提會斷定為false,年夜括號中的代碼會被跳過。假如不是nil,會將值賦給let前面的常量,如許代碼塊中便可以應用這個值了。
switch支撐隨意率性類型的數據和各類比擬操作——不只僅是整數和測試相等。
let vegetable = "red pepper"
switch vegetable {
case "celery":
let vegetableComment = "Add some raisins and make ants on a log."
case "cucumber", "watercress":
let vegetableComment = "That would make a good tea sandwich."
case let x where x.hasSuffix("pepper"):
let vegetableComment = "Is it a spicy \(x)?"
default:
let vegetableComment = "Everything tastes good in soup."
}
演習:刪除default語句,看看會有甚麼毛病?
運轉switch中婚配到的子句以後,法式會加入switch語句,其實不會持續向下運轉,所以不須要在每一個子句開頭寫break。
你可使用for-in來遍歷字典,須要兩個變量來表現每一個鍵值對。
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
}
}
}
largest
演習:添加另外一個變量來記載哪一種類型的數字是最年夜的。
應用while來反復運轉一段代碼直到不知足前提。輪回前提可以在開首也能夠在開頭。
var n = 2
while n < 100 {
n = n * 2
}
n
var m = 2
do {
m = m * 2
} while m < 100
m
你可以在輪回中應用..來表現規模,也能夠應用傳統的寫法,二者是等價的:
var firstForLoop = 0
for i in 0..3 {
firstForLoop += i
}
firstForLoop
var secondForLoop = 0
for var i = 0; i < 3; ++i {
secondForLoop += 1
}
secondForLoop
應用..創立的規模不包括上界,假如想包括的話須要應用...。
函數和閉包
應用func來聲明一個函數,應用名字和參數來挪用函數。應用->來指定函數前往值。
func greet(name: String, day: String) -> String {
return "Hello \(name), today is \(day)."
}
greet("Bob", "Tuesday")
演習:刪除day參數,添加一個參數來表現明天吃了甚麼午餐。
應用一個元組來前往多個值。
func getGasPrices() -> (Double, Double, Double) {
return (3.59, 3.69, 3.79)
}
getGasPrices()
函數的參數數目是可變的,用一個數組來獲得它們:
func sumOf(numbers: Int...) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
sumOf()
sumOf(42, 597, 12)
演習:寫一個盤算參數均勻值的函數。
函數可以嵌套。被嵌套的函數可以拜訪外側函數的變量,你可使用嵌套函數來重構一個太長或許太龐雜的函數。
func returnFifteen() -> Int {
var y = 10
func add() {
y += 5
}
add()
return y
}
returnFifteen()
函數是一等國民,這意味著函數可以作為另外一個函數的前往值。
func makeIncrementer() -> (Int -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(7)
函數也能夠當作參數傳入另外一個函數。
func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, lessThanTen)
函數現實上是一種特別的閉包,你可使用{}來創立一個匿名閉包。應用in來朋分參數並前往類型。
numbers.map({
(number: Int) -> Int in
let result = 3 * number
return result
})
演習:重寫閉包,對一切奇數前往0.
有許多種創立閉包的辦法。假如一個閉包的類型已知,好比作為一個回調函數,你可以疏忽參數的類型和前往值。單個語句閉包會把它語句的值當作成果前往。
你可以經由過程參數地位而不是參數名字來援用參數——這個辦法在異常短的閉包中異常有效。當一個閉包作為最初一個參數傳給一個函數的時刻,它可以直接跟在括號前面。
sort([1, 5, 3, 12, 2]) { $0 > $1 }
對象和類
應用class和類名來創立一個類。類中屬性的聲明和常量、變量聲明一樣,獨一的差別就是它們的高低文是類。異樣,辦法和函數聲明也一樣。
class Shape {
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
演習:應用let添加一個常量屬性,再添加一個吸收一個參數的辦法。
要創立一個類的實例,在類名前面加上括號。應用點語法來拜訪實例的屬性和辦法。
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
這個版本的Shape類缺乏了一些主要的器械:一個結構函數來初始化類實例。應用init來創立一個結構器。
class NamedShape {
var numberOfSides: Int = 0
var name: String
init(name: String) {
self.name = name
}
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
留意self被用來差別實例變量。當你創立實例的時刻,像傳入函數參數一樣給類傳入結構器的參數。每一個屬性都須要賦值——不管是經由過程聲明(就像numberOfSides)照樣經由過程結構器(就像name)。
假如你須要在刪除對象之進步行一些清算任務,應用deinit創立一個析構函數。
子類的界說辦法是在它們的類名前面加上父類的名字,用冒號朋分。創立類的時刻其實不須要一個尺度的根類,所以你可以疏忽父類。
子類假如要重寫父類的辦法的話,須要用override標志——假如沒有添加override就重寫父類辦法的話編譯器會報錯。編譯器異樣會檢測override標志的辦法能否確切在父類中。
class Square: NamedShape {
var sideLength: Double
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 4
}
func area() -> Double {
return sideLength * sideLength
}
override func simpleDescription() -> String {
return "A square with sides of length \(sideLength)."
}
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()
演習:創立NamedShape的另外一個子類Circle,結構器吸收兩個參數,一個是半徑一個是稱號,完成area和describe辦法。
屬性可以有 getter 和 setter 。
class EquilateralTriangle: NamedShape {
var sideLength: Double = 0.0
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 3
}
var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}
override func simpleDescription() -> String {
return "An equilateral triagle with sides of length \(sideLength)."
}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength
在perimeter的 setter 中,新值的名字是newValue。你可以在set以後顯示的設置一個名字。
留意EquilateralTriangle類的結構器履行了三步:
1.設置子類聲明的屬性值
2.挪用父類的結構器
3.轉變父類界說的屬性值。其他的任務好比挪用辦法、getters和setters也能夠在這個階段完成。
假如你不須要盤算屬性然則須要在設置一個新值之前運轉一些代碼,應用willSet和didSet。
好比,上面的類確保三角形的邊長老是和正方形的邊長雷同。
class TriangleAndSquare {
var triangle: EquilateralTriangle {
willSet {
square.sideLength = newValue.sideLength
}
}
var square: Square {
willSet {
triangle.sideLength = newValue.sideLength
}
}
init(size: Double, name: String) {
square = Square(sideLength: size, name: name)
triangle = EquilateralTriangle(sideLength: size, name: name)
}
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
triangleAndSquare.square.sideLength
triangleAndSquare.triangle.sideLength
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
triangleAndSquare.triangle.sideLength
類中的辦法和普通的函數有一個主要的差別,函數的參數名只在函數外部應用,然則辦法的參數名須要在挪用的時刻顯式解釋(除第一個參數)。默許情形下,辦法的參數名和它在辦法外部的名字一樣,不外你也能夠界說第二個名字,這個名字被用在辦法外部。
class Counter {
var count: Int = 0
func incrementBy(amount: Int, numberOfTimes times: Int) {
count += amount * times
}
}
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)
處置變量的可選值時,你可以在操作(好比辦法、屬性和子劇本)之前加?。假如?之前的值是nil,?前面的器械都邑被疏忽,而且全部表達式前往nil。不然,?以後的器械都邑被運轉。在這兩種情形下,全部表達式的值也是一個可選值。
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength
列舉和構造體
應用enum來創立一個列舉。就像類和其他一切定名類型一樣,列舉可以包括辦法。
enum Rank: Int {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
func simpleDescription() -> String {
switch self {
case .Ace:
return "ace"
case .Jack:
return "jack"
case .Queen:
return "queen"
case .King:
return "king"
default:
return String(self.toRaw())
}
}
}
let ace = Rank.Ace
let aceRawValue = ace.toRaw()
演習:寫一個函數,經由過程比擬它們的原始值來比擬兩個Rank值。
在下面的例子中,列舉原始值的類型是Int,所以你只須要設置第一個原始值。剩下的原始值會依照次序賦值。你也能夠應用字符串或許浮點數作為列舉的原始值。
應用toRaw和fromRaw函數來在原始值和列舉值之間停止轉換。
if let convertedRank = Rank.fromRaw(3) {
let threeDescription = convertedRank.simpleDescription()
}
列舉的成員值是現實值,其實不是原始值的另外一種表達辦法。現實上,假如原始值沒成心義,你不須要設置。
enum Suit {
case Spades, Hearts, Diamonds, Clubs
func simpleDescription() -> String {
switch self {
case .Spades:
return "spades"
case .Hearts:
return "hearts"
case .Diamonds:
return "diamonds"
case .Clubs:
return "clubs"
}
}
}
let hearts = Suit.Hearts
let heartsDescription = hearts.simpleDescription()
演習:給Suit添加一個color辦法,對spades和clubs前往“black”,對hearts和diamonds前往“red”。
留意,有兩種方法可以援用Hearts成員:給hearts常量賦值時,列舉成員Suit.Hearts須要用全名來援用,由於常量沒有顯式指定類型。在switch裡,列舉成員應用縮寫.Hearts來援用,由於self的值曾經曉得是一個suit。已知變量類型的情形下你可使用縮寫。
應用struct來創立一個構造體。構造體和類有許多雷同的處所,好比辦法和結構器。它們構造體之間最年夜的一個差別就是 構造體是傳值,類是傳援用。
struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The \(rank.simpleDescription()) of \
(suit.simpleDescription())"
}
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
演習:給Card添加一個辦法,創立一副完全的撲克牌並把每張牌的rank和suit對應起來。
一個列舉成員的實例可以有實例值。雷同列舉成員的實例可以有分歧的值。創立實例的時刻傳入值便可。實例值和原始值是分歧的:列舉成員的原始值關於一切實例都是雷同的,並且你是在界說列舉的時刻設置原始值。
例如,斟酌從辦事器獲得日出和日落的時光。辦事器會前往正常成果或許毛病信息。
enum ServerResponse {
case Result(String, String)
case Error(String)
}
let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Error("Out of cheese.")
switch success {
case let .Result(sunrise, sunset):
let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
case let .Error(error):
let serverResponse = "Failure... \(error)"
}
演習:給ServerResponse和switch添加第三種情形。
留意若何從ServerResponse中提取日升和日落時光。
接口和擴大
應用protocol來聲明一個接口。
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
類、列舉和構造體都可以完成接口。
class SimpleClass: ExampleProtocol {
var simpleDescription: String = "A very simple class."
var anotherProperty: Int = 69105
func adjust() {
simpleDescription += " Now 100% adjusted."
}
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription
struct SimpleStructure: ExampleProtocol {
var simpleDescription: String = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription
演習:寫一個完成這個接口的列舉。
留意聲明SimpleStructure時刻mutating症結字用來標志一個會修正構造體的辦法。SimpleClass的聲明不須要標志任何辦法由於類中的辦法常常會修正類。
應用extension來為現有的類型添加功效,好比添加一個盤算屬性的辦法。你可使用擴大來給隨意率性類型添加協定,乃至是你從內部庫或許框架中導入的類型。
extension Int: ExampleProtocol {
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {
self += 42
}
}
7.simpleDescription
演習:給Double類型寫一個擴大,添加absoluteValue功效。
你可以像應用其他定名類型一樣應用接口名——例如,創立一個有分歧類型然則都完成一個接口的對象聚集。當你處置類型是接口的值時,接口外界說的辦法弗成用。
let protocolValue: ExampleProtocol = a
protocolValue.simpleDescription
// protocolValue.anotherProperty // Uncomment to see the error
即便protocolValue變量運轉時的類型是simpleClass,編譯器會把它的類型當作ExampleProtocol。這表現你不克不及挪用類在它完成的接口以外完成的辦法或許屬性。
泛型
在尖括號裡寫一個名字來創立一個泛型函數或許類型。
func repeat<ItemType>(item: ItemType, times: Int) -> ItemType[] {
var result = ItemType[]()
for i in 0..times {
result += item
}
return result
}
repeat("knock", 4)
你也能夠創立泛型類、列舉和構造體。
// Reimplement the Swift standard library's optional type
enum OptionalValue<T> {
case None
case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)
在類型名前面應用where來指定一個需求列表——例如,要限制完成一個協定的類型,須要限制兩個類型要雷同,或許限制一個類必需有一個特定的父類。
func anyCommonElements <T, U where T: Sequence, U: Sequence, T.GeneratorType.Element: Equatable, T.GeneratorType.Element == U.GeneratorType.Element> (lhs: T, rhs: U) -> Bool {
for lhsItem in lhs {
for rhsItem in rhs {
if lhsItem == rhsItem {
return true
}
}
}
return false
}
anyCommonElements([1, 2, 3], [3])
演習:修正anyCommonElements函數來創立一個函數,前往一個數組,內容是兩個序列的共有元素。
簡略起見,你可以疏忽where,只在冒號前面寫接口或許類名。<T: Equatable>和<T where T: Equatable>是等價的。