Written by chuotfx on October 9, 2019Basic Swift trong 10 phútiOS & Swift
Contents
Toggle
Chuẩn bị
1. Hello world
2. Biến & kiểu dữ liệu cơ bản
3. Collection Type
3.1. Array
3.2. Dictionary
3.3. Set
4. Control Flow
4.1. Lệnh điều kiện
4.2. Lệnh rẽ nhánh
4.3. Lệnh lặp
5. Function
6. Closure
7. Class & Object
7.1. Class
7.2. Object
8. Enumerations and Structures
8.1. Enumerations
8.2. Structures
9. Protocol & Extension
9.1. Protocol
9.2. Extension
10. Optional
11. Error handling
Tham khảo ví dụ sau
12. Generics
Tổng kết
Chào bạn đến với thế giới của ngôn ngữ lập trình Swift,
Lưu ý: bài viết này mang tính chất cưỡi ngựa xem hoa là chủ yếu. Nếu bạn muốn tìm hiểu hay học chi tiết hơn thì có có thể ghé trang “The Basic – Swift” của Apple.
Chuẩn bị
Đối tượng hướng tới:
Chọn ngôn ngữ Swift để học thêm.
Học nhanh Swift để qua học iOS và tiết kiệm thời gian.
Muốn xem thử Swift có gì không.
… học cho vui
Công cụ và môi trường:
MacOS 10.14.4 (hoặc mới hơn)
Xcode 11 (hoặc mới hơn)
Swift 5 (hoặc mới hơn)
1. Hello world
Mọi thứ sẽ bắt đầu bằng Hello world
Nó mang 2 ý nghĩa
Kiểm tra xem IDE (Xcode) và Swift của bạn OK chưa?
Build được Swift không?
print("Hello, world!")
2. Biến & kiểu dữ liệu cơ bản
Biến số khai báo với từ khoá là var
Có thể thay đổi giá trị
Hằng số khai báo với từ khoá là let
Không thể thay đổi giá trị
Cú pháp:
var/let <variable_name> : <type> = <value>
(hoặc không cần chỉ rõ kiểu dữ liệu cho biến)
var/let <variable_name> = <value>
Ví dụ:
var myVariable = 100 myVariable = 50 let myConstant = 99
Tất cả các biến/hằng của Swift thì phải được gán giá trị ngay lúc khai báo.
Giá trị mặc định cho biến/hằng
Khi không xét kiểu dữ liệu cho biến/hằng thì Swift sẽ tự động nội suy kiểu dữ liệu từ kiểu của giá trị được gán cho biến/hằng
var a = 10 //Int var b = 1.1 //Double var str = "hello" //String
Các giá trị không tự động ép kiểu (casting) mà bạn phải chịu khó ép kiểu để được dữ liệu như mong muốn.
let str = "apples" let number = 999 let countLabel = String(number) + str
(hoặc)
let a = 5.1 let b: Float = 10.7 let c: Float = Float(a) + b
In giá trị vào 1 chuỗi string
Dùng toán tử \
let apples = 3 let oranges = 5 let appleSummary = "I have \(apples) apples." let fruitSummary = "I have \(apples + oranges) pieces of fruit."
Sử dụng dấu """ cho:
Nhiều dòng đối với string
let quotation = """ I said "I have \(apples) apples." And then I said "I have \(apples + oranges) pieces of fruit." """
3. Collection Type
3.1. Array
Array là tập hợp các phần tử có cùng kiểu dữ liệu.
Sử dụng toán tử [] để khai báo
Swift sẽ tự động nhận diện được kiểu dữ liệu của array cho biến
Lưu ý: thời gian build sẽ rất lâu nếu không chỉ rõ kiểu dữ liệu cho array
var numbers = [1, 2, 3, 4, 5] var names: [String] = ["Nick", "Join", "Tom", "Mary"] print(numbers[2]) print(names[3])
var arr1 = [1, 2, 3] // tạo arr1 và gán mãng Int var arr2 = [] // arr2 với mảng Any var arr3: [Int] = [Int]() //Khởi tạo arr3 với kiểu mãng Int var arr4: [Int] = [] //tạo arr4 và gán mãng rỗng
Set là tập hợp các phần tử có cùng kiểu dữ liệu mà các giá trị tồn tại duy nhất.
Dễ hiểu là 1 Set các số Int thì không có 2 phần tử mang giá trị là 1.
let newString = "Hello Swift AAAA" let array = Array(newString) //["H", "e", "l", "l", "o", " ", "S", "w", "i", "f", "t", " ", "A", "A", "A", "A"] let set = Set(array) print(set) //[" ", "e", "l", "o", "S", "H", "t", "f", "w", "A", "i"]
4. Control Flow
4.1. Lệnh điều kiện
If
var temperatureInFahrenheit = 30 if temperatureInFahrenheit <= 32 { print("It's very cold. Consider wearing a scarf.") } // Prints "It's very cold. Consider wearing a scarf."
If else
temperatureInFahrenheit = 40 if temperatureInFahrenheit <= 32 { print("It's very cold. Consider wearing a scarf.") } else { print("It's not that cold. Wear a t-shirt.") } // Prints "It's not that cold. Wear a t-shirt."
If else if
temperatureInFahrenheit = 90 if temperatureInFahrenheit <= 32 { print("It's very cold. Consider wearing a scarf.") } else if temperatureInFahrenheit >= 86 { print("It's really warm. Don't forget to wear sunscreen.") } else { print("It's not that cold. Wear a t-shirt.") } // Prints "It's really warm. Don't forget to wear sunscreen."
If let
Dùng để kiểm tra các giá trị bằng nil
Hay đảm bảo giá trị của biến tồn tại
var myName: String? if let myName = myName { print("My name is \(myName)") } else { print("Sorry") }
Guard let
Hay còn gọi là if ngược
Sẽ thực thi khi điều kiện bị sai
Dùng làm bảo vệ các biến khi nhập xuất và đảm bảo đoạn code dưới chạy được
Yêu cầu phải có return để kết thúc function
func sayName(name: String?) { guard let name = name else { print("Sorry") return } print("My name is \(name)") } sayName(name: myName)
4.2. Lệnh rẽ nhánh
switch case
switch được nhiều kiểu dữ liệu
Int, Float, Array … object
let anotherCharacter: Character = "a" switch anotherCharacter { case "a": // Invalid, the case has an empty body case "A": print("The letter A") default: print("Not the letter A") } // This will report a compile-time error.
Kết hợp nhiều điều kiện
từ khoá where
let temp = 9 switch temp { case 0: print("Number 0") case 1: print("Number 1") case 2: print("Number 2") case 3: print("Number 3") case 4: print("Number 4") case 5: print("Number 5") case 6...10: print("6 <= && >= 10") default: print("unknown") }
4.3. Lệnh lặp
For
Từ khoá
for
in
Lặp từ số tới đối tượng
Duyệt theo range hoặc array
for count in 0...100 { print(count) } for name in names { print("Hello, \(name)") } var dic: [String: String] = ["tree" : "cây", "love" : "tình yêu", "hate" : "ghét"] for item in dic { print(item.key + " is '" + item.value + "'" ) }
For phức tạp chút
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 } } } print(largest) // Prints "25"
while
Kiểm tra trước & làm sau
var i = 0 while i < 10 { print("i = \(i)") i += 1 }
repeat-while
làm trước & kiểm tra sau
var j = 0 repeat { print("j = \(j)") j += 1 } while j < 10
Không muốn sử dụng argument label thì có thể dùng _ để thay thế. Sẽ trở thành giống như các ngôn ngữ khác.
func greet(_ person: String, on day: String) -> String { return "Hello \(person), today is \(day)." } greet("John", on: "Wednesday")
Function trả về nhiều giá trị
Return về kiểu là Tuple
let numbers = [1, 3, 10, -11, 98, 45] func getMinMax(numbers: [Int]) -> (Int, Int) { return (numbers.min()!, numbers.max()!) } let result = getMinMax(numbers: numbers) print("Min = \(result.0) & Max = \(result.1)")
6. Closure
Đã có 1 bài viết chi tiết, đọc thêm ở đây : Closure trong 10 phút
Ví dụ cơ bản nhất
let myClosure = {(name: String) -> Void in print("Hello, \(name)") } myClosure("Nick")
7. Class & Object
7.1. Class
Khai báo class
Từ khoá : class
Các thuộc tính (property)
khai báo như biến/hằng
Các phương thức (method)
khai báo như function
Hàm khởi tạo
Từ khoá init
Nếu tất cả các thuộc tính được gán giá trị ban đầu hay là kiểu optional thì không cần hàm init
Ví dụ:
class NamedShape { var numberOfSides: Int = 0 var name: String init(name: String) { self.name = name } func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." } }
Thừa kế
Dùng toán tử :
Ghi đè phương thức lớp cha, dùng từ khoá override
Sử dụng từ khoá final trước từ khoá class thì sẽ không được thừa kế tiếp
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)." } }
7.2. Object
Object là thể hiện của class
Sử dụng toán tử ( ) để tạo 1 object
Ví dụ:
class Shape { var numberOfSides = 0 func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." } } var shape = Shape() shape.numberOfSides = 7 var shapeDescription = shape.simpleDescription()
8. Enumerations and Structures
8.1. Enumerations
Enum là bảng liệt kê các trường hợp
Từ khoá enum
Dùng để tăng tính tường minh cho code
Swift thì enum khá là bá:
có thể kế thừa từ nhiều loại kiểu dữ liệu
có thể có function như class
khởi tạo thì dùng rawValue hoặc khởi tạo bằng case của enum
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()
Có thể thêm nhiều dữ liệu cho các case (tương tự Tuple)
Sử dụng phải switch case
enum ServerResponse { case result(String, String) case failure(String) } let success = ServerResponse.result("6:00 am", "8:09 pm") let failure = ServerResponse.failure("Out of cheese.") switch success { case let .result(sunrise, sunset): print("Sunrise is at \(sunrise) and sunset is at \(sunset).") case let .failure(message): print("Failure... \(message)") } // Prints "Sunrise is at 6:00 am and sunset is at 8:09 pm."
8.2. Structures
Struct kiểu dữ liệu kết hợp từ nhiều kiểu dữ liệu khác
Tương tự như class
Khác class một vài điểm cơ bản sau:
Không kế thừa được
Theo kiểu tham trị
Không cần định nghĩa hàm init
Với swift 5
Nếu các thuộc tính được gán trị ban đầu thì có thể lượt bỏ nó ở hàm init của struct
struct Point { var x: Float = 0.0 var y: Float = 0.0 func showInfo() { print("Point (\(x), \(y))") } } let point1 = Point() point1.showInfo() let point2 = Point(x: 10.0, y: 25) point2.showInfo() var point3 = Point() point3.x = 77.5 point3.y = -85 point3.showInfo()
9. Protocol & Extension
9.1. Protocol
Protocol là kiểu interface
Khái báo các thuộc tính và phương thức
Không định nghĩa chúng
Dùng xem là 1 hình thức đa kế thừa trong swift
Dùng được cho class, struct và enum
Khai báo dùng từ khoá protocol
protocol ExampleProtocol { var simpleDescription: String { get } mutating func adjust() }
Khi implement thì phải định nghĩa lại hết các phương thức & thuộc tính đã được khai báo
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
9.2. Extension
Khi muốn thêm function hay thuộc tính cho 1 class/struct/enum có sẵn mà không muốn tạo sub-class để kế thừa lại.
Từ khoá extension
extension Int: ExampleProtocol { var simpleDescription: String { return "The number \(self)" } mutating func adjust() { self += 42 } } print(7.simpleDescription) // Prints "The number 7"
10. Optional
Cho phép 1 biến vắng mặt giá trị của nó. Tức là bằng nil
Các toán tử
Khai báo sử dụng ?
Sử dụng giá trị mặc định dùng ??
var name: String? = nil print(name) //nil print(name ?? "no name") //no name
Implicitly Unwrapping: Khai báo với ! dùng để dùng trực tiếp
Khi sử dụng thì không cần toán tử ! hay ?
var name: String! = "Nick Lee" print(name ?? "no name")
Force Unwrap : dùng để truy cập trực tiếp
Chương trình có thể bị crash khi giá trị của biến bằng nil
Trong dự án iOS thường sẽ bị cấm cái này hay trong swiftlint cũng cấm
name = "abc" print(name) print(name!)
Optional binding : dùng để truy cập và sử dụng optional 1 cách an toàn hơn
if let name = name { print(name) } else { print("no name") }
11. Error handling
Dùng để xử lý các error và các ngoại lệ
Đảm bảo chương trình không bị crash
Tham khảo ví dụ sau
Khai báo 1 enum error
enum PrinterError: Error { case outOfPaper case noToner case onFire }