Kết hợp khoảng (Interval Matching)
Trong switch nhiều trường hợp giá trị có thể được kiểm tra và đưa vào một khoảng . Ví dụ sau sử dụng các khoảng số quy ước cách gọi tự nhiên cho các số có kích thước bất kỳ:
let approximateCount = 62
let countedThings = "moons orbiting Saturn"
let naturalCount: String
switch approximateCount {
case 0:
naturalCount = "no"
case 1..<5:
naturalCount = "a few"
case 5..<12:
naturalCount = "several"
case 12..<100:
naturalCount = "dozens of"
case 100..<1000:
naturalCount = "hundreds of"
default:
naturalCount = "many"
}
print("There are \(naturalCount) \(countedThings).")
// Prints "There are dozens of moons orbiting Saturn."
Trong ví dụ trên, approximateCount được xác định trong một câu lệnh switch. Mỗi case so sánh giá trị đó với một số hoặc một khoảng. Bởi vì giá trị của approximateCount nằm trong khoảng 12 đến 100, naturalCount được gán giá trị "dozens of", và được thực hiện chuyển ra khỏi câu lệnh switch.
Tuples
Tuples là gì?
Tuples nhóm nhiều giá trị đơn thành một giá trị ghép. Các giá trị trong một tuple có thể thuộc bất kỳ loại nào và không cần thiết là cùng loại với nhau. Ví dụ:
let tuple = ("one", 2, "three")
// Values are read using index numbers starting at zero
print(tuple.0) // one
print(tuple.1) // 2
print(tuple.2) // three
Bạn có thể sử dụng tuples để kiểm tra nhiều giá trị trong một câu lệnh switch. Mỗi phần tử của tuple có thể được kiểm tra đối với một giá trị hoạc khoảng giá trị khác nhau. Ngoài ra, sử dụng dấu gạch dưới (_), còn được biết đến như một mẫu ký tự đại diện, có thể thay thế nhiều giá trị.
Ví dụ dưới đây lấy một điểm (x, y), biểu thị một bộ dữ liệu đơn giản kiểu (Int, Int), phân loại nó trên biểu đồ theo ví dụ.
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
print("\(somePoint) is at the origin")
case (_, 0):
print("\(somePoint) is on the x-axis")
case (0, _):
print("\(somePoint) is on the y-axis")
case (-2...2, -2...2):
print("\(somePoint) is inside the box")
default:
print("\(somePoint) is outside of the box")
}
// Prints "(1, 1) is inside the box"
Câu lệnh switch xác định điểm gốc (0, 0), trục x, trục y, bên trong, bên ngoài hộp xanh 4 x 4.
Không giống như C, Swift cho phép nhiều trường hợp chuyển đổi xem xét một giá trị hoặc nhiều giá trị giống nhau. Trong thực tế, điểm (0, 0) có thể khớp với cả bốn trường hợp trong ví dụ này. Tuy nhiên, nếu có thể có nhiều kết quả khớp, trường hợp khớp đầu tiên luôn được sử dụng. Điểm (0, 0) sẽ khớp với trường hợp (0, 0) trước và vì vậy tất cả các trường hợp khớp khác sẽ bị bỏ qua.
Value Bindings
Trong một swift trường hợp có thể đặt tên cho giá trị hoặc nhiều giá trị mà nó khớp với các hằng hoặc biến tạm thời, để sử dụng trong phần thân case. Hành vi này được gọi là ràng buộc giá trị, bởi vì các giá trị được liên kết với các hằng hoặc biến tạm thời trong thân case.
Ví dụ dưới đây lấy một điểm (x, y), được biểu thị dưới dạng một tuple kiểu (Int, Int) và phân loại nó trên biểu đồ sau:
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
print("on the x-axis with an x value of \(x)")
case (0, let y):
print("on the y-axis with a y value of \(y)")
case let (x, y):
print("somewhere else at (\(x), \(y))")
}
// Prints "on the x-axis with an x value of 2"
Câu lệnh Swift xác định xem điểm nằm trên trục x đỏ, trên trục y màu cam hay ở nơi khác (trên cả hai trục).
Ba trường hợp Swift khai báo giữ chỗ hằng số x và y, tạm thời đảm nhận một hoặc cả hai giá trị tuple từ AnotherPoint. Trường hợp thứ nhất (let x, 0), khớp với bất kỳ điểm nào có giá trị y là 0 và gán giá trị điểm x cho hằng số x tạm thời. Trường hợp thứ hai, trường hợp (0, let y), khớp với bất kỳ điểm nào có giá trị x là 0 và gán giá trị điểm y cho hằng số y tạm thời.
Sau khi các hằng số tạm thời được khai báo, chúng có thể được sử dụng trong khối mã trường hợp. Ở đây, chúng được sử dụng để in phân loại điểm.
Câu lệnh Swift này không có trường hợp mặc định. Trường hợp cuối cùng, trường hợp let (x, y), khai báo một bộ gồm hai hằng số giữ chỗ có thể khớp với bất kỳ giá trị nào. Vì AnotherPoint luôn là một bộ gồm hai giá trị, trường hợp này khớp với tất cả các giá trị còn lại có thể và không cần trường hợp mặc định để làm cho câu lệnh swift trở nên toàn diện.
Where
Swift có thể sử dụng mệnh đề where để kiểm tra các điều kiện bổ sung.
Ví dụ dưới đây phân loại một điểm (x, y) trên biểu đồ:
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
print("(\(x), \(y)) is just some arbitrary point")
}
// Prints "(1, -1) is on the line x == -y"
Câu lệnh chuyển đổi xác định xem điểm có nằm trên đường chéo màu xanh lá cây where x == y, trên đường chéo màu tím where x == -y hoặc không.
Ba trường hợp swift khai báo các hằng số giữ chỗ x và y, tạm thời lấy hai giá trị tuple từ yetAotherPoint. Các hằng số này được sử dụng như một phần của mệnh đề where, để tạo bộ lọc động. Trường hợp swift chỉ khớp với giá trị hiện tại của điểm nếu điều kiện mệnh đề where đánh giá là đúng với giá trị đó.
Như trong ví dụ trước, trường hợp cuối cùng khớp với tất cả các giá trị còn lại có thể, và do đó không cần phải có trường hợp mặc định để làm cho câu lệnh swift trở nên toàn diện.
Compound Cases
Nhiều trường hợp swift chia sẻ thân giống nhau có thể được kết hợp bằng cách viết một số mẫu sau trường hợp, với dấu phẩy giữa mỗi mẫu. Nếu bất kỳ mô hình nào khớp, thì trường hợp được coi là khớp. Các mẫu có thể được viết trên nhiều dòng nếu danh sách dài. Ví dụ:
let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
print("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
print("\(someCharacter) is a consonant")
default:
print("\(someCharacter) is not a vowel or a consonant")
}
// Prints "e is a vowel"
Trường hợp đầu tiên của câu lệnh swift phù hợp với tất cả năm nguyên âm chữ thường trong ngôn ngữ tiếng Anh. Tương tự, trường hợp thứ hai của nó phù hợp với tất cả các phụ âm tiếng Anh viết thường. Cuối cùng, trường hợp mặc định phù hợp với bất kỳ ký tự khác.
let stillAnotherPoint = (9, 0)
switch stillAnotherPoint {
case (let distance, 0), (0, let distance):
print("On an axis, \(distance) from the origin")
default:
print("Not on an axis")
}
// Prints "On an axis, 9 from the origin"
Control Transfer Statements
continue
break
fallthrough
return
throw
Các câu lệnh c
ontinue
, break và
fallthrough
được mô tả dưới đây. Câu lệnh return được mô tả trong Function, và câu lệnh throw được mô tả trong https://docs.swift.org/swift-book/LanguageGuide/ErrorHandling.html#ID510
Continue
Câu lệnh continue dùng cho một vòng lặp để dừng những gì nó đang làm và bắt đầu lại từ đầu của lần lặp tiếp theo thông qua vòng lặp.
let puzzleInput = "great minds think alike"
var puzzleOutput = ""
let charactersToRemove: [Character] = ["a", "e", "i", "o", "u", " "]
for character in puzzleInput {
if charactersToRemove.contains(character) {
continue
}
puzzleOutput.append(character)
}
print(puzzleOutput)
// Prints "grtmndsthnklk"
Break
Khi được sử dụng trong một câu lệnh lặp, break kết thúc việc thực thi vòng lặp ngay lập tức và chuyển điều khiển sang mã sau khi kết thúc vòng lặp (}). Không có mã nào khác từ lần lặp hiện tại của vòng lặp được thực thi và không có lần lặp tiếp theo.
Khi được sử dụng bên trong chương trình swift, break làm cho chương trình swift kết thục thực thi ngay lặp tức và chuyển điều khiển sang mã sau khi câu lệnh swift kết thúc cú đúp (}).
Hành vi này có thể được sử dụng để khớp và bỏ qua một hoặc nhiều trường hợp trong câu lệnh swift. Bởi vì ngôn ngữ swift các câu lệnh đầu đủ và không cho phép các trường hợp trống rỗng, đôi khi cần phải cố tình khớp và bỏ qua một trường hợp để làm cho ý định của bạn rõ ràng. Chúng ta thực hiện nó bằng cách viết câu lệnh break bỏ qua toàn bộ phần thân chương trình. Khi trường hợp đó khớp với trong swift, câu lệnh break kết thúc thực thi lệnh swift ngay lập tức.
- NOTE: Một trường hợp Swift chỉ chứa một nhận xét được báo cáo là lỗi thời gian biên dịch. Nhận xét không phải là tuyên bố và không làm cho trường hợp swift bị bỏ qua. Luôn luôn sử dụng một câu lệnh swift để bỏ qua một trường hợp swift.
let numberSymbol: Character = "三" // Chinese symbol for the number 3
var possibleIntegerValue: Int?
switch numberSymbol {
case "1", "١", "一", "๑":
possibleIntegerValue = 1
case "2", "٢", "二", "๒":
possibleIntegerValue = 2
case "3", "٣", "三", "๓":
possibleIntegerValue = 3
case "4", "٤", "四", "๔":
possibleIntegerValue = 4
default:
break
}
if let integerValue = possibleIntegerValue {
print("The integer value of \(numberSymbol) is \(integerValue).")
} else {
print("An integer value could not be found for \(numberSymbol).")
}
// Prints "The integer value of 三 is 3."
default
xử lý bất kỳ ký tự nào không khớp. Trường hợp default
này không cần thực hiện bất kỳ hành động nào, và do đó, nó được viết với một mình câu lệnh break. Ngay sau khi khớp với trường hợp default, câu lệnh break kết thúc thực thi câu lệnh swift, và thực thi mã tiếp tục từ câu lệnh if let.Fallthrough
Trong swift, câu lệnh swift không rơi xuống dưới cùng của mỗi trường hợp hay trường hợp tiếp theo. Mà là toàn bộ câu lệnh chuyển đổi hoàn thành việc thực hiện ngay khi trường hợp khớp đầu tiên được hoàn thành. Ngược lại, C yêu cầu bạn chèn một câu lệnh break vào cuối mỗi trường hợp chuyển đổi để ngăn chặn sự sụp đổ.
let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += " a prime number, and also"
fallthrough
default:
description += " an integer."
}
print(description)
// Prints "The number 5 is a prime number, and also an integer."
Ví dụ này khai báo một biến String mới gọi là description và gán cho nó một giá trị ban đầu. Sau đó, hàm sẽ xem xét giá trị của integerToDescribe bằng cách sử dụng câu lệnh switch. Nếu giá trị của integerToDescribe là một trong những số nguyên tố trong danh sách, hàm sẽ nối văn bản vào cuối description
, để lưu ý rằng số là số nguyên tố. Sau đó, nó cũng sử dụng từ khóa fallthrought để rơi vào trường hợp default. Trường hợp default thêm một số văn bản bổ sung vào cuối mô tả và hoàn tất lệnh switch.
Trừ khi giá trị của intederToDescribe nằm trong danh sách các số nguyên tố đã biết, nó hoàn toàn không khớp với trường hợp switch đầu tiên. Bởi vì nếu không có trường hợp cụ thể nào khác, integerToDescribe được khớp với trường hợp default.
Sau khi câu lệnh switch đã thực hiện xong, mô tả về số được in bằng cách sử dụng lệnh print(_: separator: terminator :). Trong ví dụ này, số 5 được xác định chính xác là số nguyên tố.
- NOTE từ khóa fallthrough không kiểm tra các điều kiện trường hợp cho trường hợp switch mà nó khiến cho việc thực thi rơi vào. Từ khóa fallthroughchỉ đơn giản là khiến cho việc thực thi mã di chuyển trực tiếp đến các câu lệnh bên trong khối trường hợp tiếp theo (hoặc trường hợp default), như trong hành vi câu lệnh swift tiêu chuẩn C.
Labeled Statements
label name: while condition {
statements
}
Ví dụ sau sử dụng câu lệnh break và continue
- Để giành chiến thắng, bạn phải hạ cánh chính xác trên ô vuông 25.
The game board is the same as before.
Các giá trị của finalSquare
, board
, square
, và diceRoll
được khởi tạo theo cách tương tự như trước:
let finalSquare = 25
var board = [Int](repeating: 0, count: finalSquare + 1)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
var square = 0
var diceRoll = 0
while square != finalSquare
,
gameLoop: while square != finalSquare {
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare:
// diceRoll will move us to the final square, so the game is over
break gameLoop
case let newSquare where newSquare > finalSquare:
// diceRoll will move us beyond the final square, so roll again
continue gameLoop
default:
// this is a valid move, so find out its effect
square += diceRoll
square += board[square]
}
}
print("Game over!")
- Nếu cuộn súc sắc sẽ di chuyển người chơi vào ô vuông cuối cùng, trò chơi kết thúc. Lệnh break gameLoop chuyển điều khiển sang dòng mã đầu tiên bên ngoài vòng lặp while, kết thúc trò chơi.
- Trong tất cả các trường hợp khác, cuộn súc sắc là một động thái hợp lệ. Người chơi di chuyển về phía trước bởi các ô vuông diceRoll và logic trò chơi kiểm tra xem có con rắn và thang nào không.Vòng lặp sau đó kết thúc và điều khiển quay trở lại điều kiện while để quyết định xem có phải rẽ khác không.NOTENếu câu lệnh break ở trên không sử dụng nhãn gameLoop, nó sẽ thoát ra khỏi câu lệnh switch, không phải câu lệnh while.Sử dụng nhãn gameLoop cho thấy rõ câu lệnh điều khiển nào nên được chấm dứt.Không nhất thiết phải sử dụng nhãn gameLoop khi gọi tiếp tục gameLoop để chuyển sang lần lặp tiếp theo của vòng lặp. Chỉ có một vòng lặp trong trò chơi, và do đó không có sự mơ hồ về việc vòng lặp continue sẽ ảnh hưởng đến điều gì.Tuy nhiên, không có bất tiện trong việc sử dụng nhãn gameLoop với câu lệnh continue.Làm như vậy phù hợp với nhãn sử dụng cùng với câu lệnh break và giúp làm cho logic của trò chơi rõ ràng hơn để đọc và hiểu.
Early Exit
Một câu lệnh guard, giống như một câu lệnh if, thực thi các câu lệnh tùy thuộc vào giá trị Boolean của một biểu thức. Bạn sử dụng một câu lệnh guard để yêu cầu một điều kiện phải đúng để mã sau khi câu lệnh guard được thực thi. Không giống như if, một câu lệnh guard luôn có một mệnh đề esle—mã bên trong mệnh đề else được thực thi nếu điều kiện không đúng.
func greet(person: [String: String]) {
guard let name = person["name"] else {
return
}
print("Hello \(name)!")
guard let location = person["location"] else {
print("I hope the weather is nice near you.")
return
}
print("I hope the weather is nice in \(location).")
}
greet(person: ["name": "John"])
// Prints "Hello John!"
// Prints "I hope the weather is nice near you."
greet(person: ["name": "Jane", "location": "Cupertino"])
// Prints "Hello Jane!"
// Prints "I hope the weather is nice in Cupertino."
Nếu điều kiện đó không được đáp ứng, mã bên trong nhánh else được thực thi. Nhánh đó phải chuyển điều khiển để thoát khỏi khối mã trong đó câu lệnh guard xuất hiện. Nó có thể thực hiện điều này bằng một câu lệnh chuyển điều khiển như return, break, continue hoặc throw hoặc nó có thể gọi một hàm hoặc phương thức không quay trở lại, như fatalError (_: file: line :).
Checking API Availability
Trình biên dịch sử dụng thông tin sẵn có trong SDK để xác minh rằng tất cả các API được sử dụng trong mã của bạn đều có sẵn trên mục tiêu triển khai được chỉ định bởi dự án của bạn. Swift báo cáo lỗi tại thời điểm biên dịch nếu bạn cố gắng sử dụng API không có sẵn.
if #available(iOS 10, macOS 10.12, *) {
// Use iOS 10 APIs on iOS, and use macOS 10.12 APIs on macOS
} else {
// Fall back to earlier iOS and macOS APIs
}
if #available(platform name version, ..., *) {
statements to execute if the APIs are available
} else {
fallback statements to execute if the APIs are unavailable
}
Bình luận