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
可以复制,不相互影响的object,采用structure。例如两个球员,他们各自的比分
可以方便被多处访问的同一个object,采用class。例如比赛记分册,需要被多个球员同时访问。一旦更新,大家都能看见
需要被继承的,采用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
}