Cowboy Tech

WWWDC2016学习笔记Getting_started_with_swift

Constants

常量为let,变量为var

let language: String = "Swift"
let introduced: Int = 2014
let isAwesome: Bool = true

Type Inference

let language = "Swift"    // Inferred as String
let introduced = 2014     // Inferred as Int
let isAwesome = true     // Inferred as Bool

String

Building Strings

let conference = "WWDC"
let message = "Hello, " + conference + "!"

// "Hello, WWDC!"

String Interpolation

let conference = "WWDC"
let year = 2016
let message = "Hello, \(conference) \(year + 1)!"

// "Hello, WWDC 2017!"

Characters

let dogString = "Dog⁈🐶"
print("\(dogString) is \(dogString.characters.count) characters long")

//Dog⁈🐶 is 5 characters long.

Array and Dictionary

let names: [String] = ["Lily", "Santiago", "Justyn", "Aadya"]    

let names = ["Lily", "Santiago", "Justyn", "Aadya"] // Type Inference

let ages = ["Mohsen": 17, "Amy": 40, "Graham": 5]

Modifying an Array

var packingList = ["Socks", "Shoes"]    
//["Socks", "Shoes"]

print(packingList[0])    
//"Socks"

packingList.append("Trousers")    
//["Socks", "Shoes", "Trousers"]

packingList[2] = "Jeans"    
//["Socks", "Shoes", "Jeans"]

packingList.append(contentsOf: ["Shorts", "Sandals", "Sunblock"])
//["Socks", "Shoes", "Jeans", "Shorts", "Sandals", "Sunblock"]

packingList[3...5] = ["Hoodie", "Scarf"]
//["Socks", "Shoes", "Jeans", "Hoodie", "Scarf"]

Modifying a Dictionary

var ages = ["Mohsen": 17, "Amy": 40, "Graham": 5]
//["Mohsen": 17, "Amy": 40, "Graham": 5]

ages["Justyn"] = 67 // Adds a new value for "Justyn"
//["Mohsen": 17, "Amy": 40, "Graham": 5, "Justyn": 67]

ages["Justyn"] = 68 // Changes the value for "Justyn"
//["Mohsen": 17, "Amy": 40, "Graham": 5, "Justyn": 68]

Retrieving a Value from a Dictionary

let ages = ["Mohsen": 17, "Amy": 40, "Graham": 5]
let possibleAge = ages["Amy"]    

While & For-In Loop

While and Repeat-While

while !endOfFile {
readLine()
}


repeat {
performTask()
} while tasksRemaining > 0

Characters

let dogString = "Dog⁈🐶"
for character in dogString.characters {
print(character)
}

Closed Ranges

for number in 1...5 {
print("\(number) times 4 is \(number * 4)")
}

Half-Closed Ranges

let results = [7, 52, 9, 33, 6, 12, 86, 4, 22, 18, 3]
let maxResultCount = 5
for index in 0..<maxResultCount {
print("Result \(index) is \(results[index])")
}

Arrays

for name in ["Lily", "Santiago", "Justyn", "Aadya"] {
print("Hello, \(name)!")
}   

Dictionaries

let ages = ["Mohsen": 17, "Amy": 40, "Graham": 5]
for (name, age) in ages {
print("\(name) is \(age) years old")
}

Condition

If Statement

let age = 32
if age == 1 {
print("Happy first birthday!")
} else if age == 40 {
print("Happy 40th birthday!")
} else {
print("Happy plain old boring birthday.")
} 

Switch Statement(需要将所有情况都考虑到)

例子1

let age = 32
switch age {
case 1:
    print("Happy first birthday!")
case 13...19:
    print("Happy birthday, teenager!")
case let decade where decade % 10 == 0:
    print("Happy significant \(decade)th birthday!")
default:
    print("Happy plain old boring birthday.")
}

例子2

let userName = "bob"
let passwordIsValid = false
switch (userName, passwordIsValid) {
    case ("admin", true):
print("Welcome back, administrator!")
    case ("guest", _):
print("Guests are not allowed in this restricted area.")
    case (_, let isValid):
print(isValid ? "Welcome to the restricted area!" : "ACCESS DENIED.")
}

Optional

Checking for an Optional Value

let ages = ["Mohsen": 17, "Amy": 40, "Graham": 5]

let possibleAge: Int? = ages["Daryl"]

if possibleAge == nil {
print("Age not found.")
}

If-Let Statement(when use optional)

let ages = ["Mohsen": 17, "Amy": 40, "Graham": 5]

if let age = ages["Amy"] {
print("An age of \(age) was found.")
}  

//An age of 40 was found.

Functions

Multiple Parameters

func sendMessage(recipient: String, shouting: Bool) {
var message = "Hey there, \(recipient)!"
if shouting {
    message = message.uppercased()
}
    print(message)
}
sendMessage(recipient: "Morgan", shouting: false) 

Explicit Argument Labels

func sendMessage(to recipient: String, shouting: Bool) {
var message = "Hey there, \(recipient)!"
if shouting {
    message = message.uppercased()
}
    print(message)
}
sendMessage(to: "Morgan", shouting: false)

Omitting Argument Labels

func sendMessage(_ message: String, to recipient: String, shouting: Bool) {
var message = "\(message), \(recipient)!"
if shouting {
    message = message.uppercased()
}
    print(message)
}
sendMessage("See you at the Bash", to: "Morgan", shouting: false)

Parameters with Default Values

func sendMessage(_ message: String, to recipient: String, shouting: Bool = false) {
var message = "\(message), \(recipient)!"
if shouting {
    message = message.uppercased()
}
    print(message)
}
sendMessage("See you at the Bash", to: "Morgan")

Returning Optional Values

func firstString(havingPrefix prefix: String, in strings: [String]) -> String? {
for string in strings {
if string.hasPrefix(prefix) {
return string
}
}
return nil
}

使用if-let,当使用optional value时

var guests = ["Jack", "Kumar", "Anita", "Anna"]
if let guest = firstString(havingPrefix: "A", in: guests) {
print("See you at the party, \(guest)!")
} else {
print("Invite must be in the mail.")
}

//See you at the party, Anita!

Closure

Functions as Parameters

func filterInts(_ numbers: [Int], _ includeNumber: (Int) -> Bool) -> [Int] {
var result: [Int] = []
for number in numbers {
if includeNumber(number) {
    result.append(number)
}
}
    return result
}

let numbers = [4, 17, 34, 41, 82]

func divisibleByTwo(_ number: Int) -> Bool {
    return number % 2 == 0
}
let evenNumbers = filterInts(numbers, divisibleByTwo)

//let evenNumbers = filterInts([4, 17, 34, 41, 82], divisibleByTwo)


print(evenNumbers)

Implicit Arguments in Closures

func filterInts(_ numbers: [Int], _ includeNumber: (Int) -> Bool) -> [Int] {…}
let evenNumbers = filterInts(numbers, { $0 % 2 == 0 })
print(evenNumbers)

Trailing Closures

func filterInts(_ numbers: [Int], _ includeNumber: (Int) -> Bool) -> [Int] {…}

方式1.如果传递的闭包是最后一个参数,可以将其大括号移除到小括号后面方便阅读. $0代表第一个参数

let evenNumbers = filterInts(numbers) { $0 % 2 == 0 }
print(evenNumbers)

方式2.

let evenNumbers = filterInts(numbers) { (firstItem) -> Bool in
    return firstItem % 2==0
}
print(evenNumbers)

如果闭包是唯一参数,可以将前面的小括号移除

let names = ["Lily", "Santiago", "Aadya", "Jack", "Anna", "Andrés"]
let shortNames = names.filter { name in name.characters.count < 5 }

Filter and Map Methods

let names = ["Lily", "Santiago", "Aadya", "Jack", "Anna", "Andrés"]

let capitalizedShortNames = names.filter { name in name.characters.count < 5 }
    .map { name in name.uppercased() }

print(capitalizedShortNames)

Generic

Calling Generic Functions

let numbers = [24,45,65,76,84,200,4]
let names = ["Lily", "Santiago", "Aadya", "Jack", "Anna", "Andrés"]

func filter<Element>(_ source: [Element], _ includeElement: (Element) -> Bool) -> [Element] {
    var result: [Element] = []
    for element in source {
        if includeElement(element) {
            result.append(element)
        }
    }
    return result
}

let evenNumbers = filter(numbers) { $0 % 2 == 0 }
let shortNames = filter(names) { name in name.characters.count < 5 }

print(evenNumbers)
print(shortNames)

Generic Types

struct NamedArray<Element> {
    var name: String
    var items: [Element]
}

let boardGames: NamedArray<String> = NamedArray(name: "Board Games", items: ["Chess", "Go"])
let primes: NamedArray<Int> = NamedArray(name: "Primes", items: [1, 3, 5, 7, 13])

//Infer types
//let boardGames: NamedArray = NamedArray(name: "Board Games", items: ["Chess", "Go"])
//let primes: NamedArray = NamedArray(name: "Primes", items: [1, 3, 5, 7, 13])

print(boardGames)
print(primes)

Structures

struct Rectangle {
    var width = 12
    var height = 10
}

var rectangle = Rectangle()
rectangle.height = 4


struct Rectangle {
var width: Int
var height: Int
}
var rectangle = Rectangle(width: 4, height: 5)

Computed Properties

struct Rectangle {
    var width: Int
    var height: Int
    var area: Int {
        return width * height
    }
}
let rectangle = Rectangle(width: 4, height: 5)
print("Width is \(rectangle.width) and area is \(rectangle.area).")

Methods

struct Rectangle {
    var width: Int
    var height: Int
    func fitsInside(_ other: Rectangle) -> Bool {
        return (width < other.width) && (height < other.height)
    }
}
let small = Rectangle(width: 1, height: 2)
let large = Rectangle(width: 5, height: 5)

print(small.fitsInside(large)) // Returns true

Initializers

自动生成init method

struct Rectangle {
    var width: Int
    var height: Int
}

var rectangl = Rectangle(width: 4, height: 5)

也可以自己明确的写一个init method

struct Rectangle {
    var width: Int
    var height: Int

    init(width: Int, height: Int) {
        self.width = width
        self.height = height
    }
}
var rectangle = Rectangle(width: 4, height: 5)

Classes

class ScoreLogFile {
    var highScores: [Score]
    func record(score: Score, for player: Player) -> Void {…}
}

Subclasses Can Add Functionality

class Fish {
    func swim() {
        print("I'm swimming.")
    }
}

class FlyingFish: Fish {
    func fly() {
        print("Flying throught the air!")
    }
    // Inherits swim() with no changes.
}

Subclasses Can Override Functionality

需要加上override字符,否则会报错

class Fish {
    func swim() {
        print("I'm swimming.")
    }
}

class ComplainingFish: Fish {
   override func swim() {
        print("Grumble grumble grumble...")
        //super.swim()
    }
}

Subclass Initializers

class Fish {
    var name: String
    init(name: String) {
        self.name = name
    }
}

class ComplainingFish: Fish {
    var complaint: String
    init(name: String, complaint: String) {
        self.complaint = complaint
        super.init(name: name)
    }
}

Class vs. Structure

  1. 可以复制,不相互影响的object,采用structure。例如两个球员,他们各自的比分

  2. 可以方便被多处访问的同一个object,采用class。例如比赛记分册,需要被多个球员同时访问。一旦更新,大家都能看见

  3. 需要被继承的,采用Class

Enumerations

enum Alignment {
    case left, right, center
}

let textAlignment = Alignment.left
switch textAlignment {
case .left:
    print("Lean to the left")
case .right:
    print("Lean to the right")
case .center:
    print("Stand up straight")
}

Enumerations with Associated Values

enum Alignment {

    case left(padding: Double), right(padding: Double), center
}

let textAlignment = Alignment.left(padding: 42.7)

switch textAlignment {

case .left(let padding):
    print("Left with \(padding) pixels of padding")

default:
    print("this is default")
}

Enumerations with Raw Values

enum ServerAddress: String {
    case staging = "https://staging.example.com"
    case production = "https://example.com"
}

func findPhotos(matchingQuery query: String, from server: ServerAddress) {
    let serverAddress = server.rawValue
    …
}

findPhotos(matchingQuery: "strawberry", from: .staging)

Protocols & Extension

Protocols

protocol is like blueprint ,like interface or abstract classes

protocol Player {
    func takeTurn(on board: Board)
}
struct HumanPlayer: Player {
    func takeTurn(on board: Board) { /* Show move UI and wait */ }
}
struct ComputerPlayer: Player {
    func takeTurn(on board: Board) { /* Pick the best legal move using AI */ }
}

Extensions for additional functionality

struct Rectangle {
    var width: Int
    var height: Int
}

extension Rectangle {
    func fitsInside(_ other: Rectangle) -> Bool {…}
    var area {…}
}

Protocols + Extensions

struct HumanPlayer: Player {…}
extension HumanPlayer: CustomStringConvertible {
    var description: String {
        return "Human player \(name) has a score of \(score)"
    }
}
let player = HumanPlayer(name: "Lynn", score: 0)
print(player)

Error Handling

enum SomeError: ErrorProtocol {
    case somethingWentWrong, somethingFailed
}
func doSomething() throws -> Data {
    progressBar.visible = true
    defer { progressBar.visible = false }
    let data: Data?
    do {
        data = try somethingThatMightFail()
    } catch SomeError.somethingWentWrong {
        data = nil
    }
    guard let result = summarize(data) else { throw SomeError.somethingFailed }
    return result
}