程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> Swift hello world!Swift疾速入門教程

Swift hello world!Swift疾速入門教程

編輯:更多關於編程

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>是等價的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved