Tìm hiểu khoá cho người mới bắt đầu Lập trình iOS Swift

Kiểm tra trắc nghiệm đầu vào 👉 để Rinh quà ưu đãi!

Học Swift qua các ví dụ căn bản:

👍 Code swift online: http://online.swiftplayground.run/

1. Hello World

  • Lệnh print() để in ra màn hình console dữ liệu mong muốn
print("Hello World")```

### **2. Values**

-  thể cộng biểu thức trong lệnh **print()**

```swift
print("swift" + "lang")                  // swiftlang

print(1 + 1)                             // 2```

-  thể kết hợp cả chuỗi và biểu thức trong lệnh **print()**

```swift
print("1+1 = " + String(1 + 1))          // 1+1 = 2

print(7.0 / 3.0)                         // 2.33333333333333

print(String(7.0) + " / " + String(3.0)) // 7.0 / 3.0```

- Biểu thức đúng sai

```swift
print(true && false)                     // false
print(true || false)                     // true
print(!true)                             // false```

### 3. Variables

 - Biến có thể thay đổi giá trị

- Khai báo bằng từ khoá `var`

```swift
var yo = 1.0
yo += 1
print(yo)                      // 2.0```

- Không thể thay đổi kiểu dữ liệu

```swift
var yo = 2.0
yo = "yo" // lỗi: không thể chuyển đổi kiểu 'String' thành kiểu 'Double' ```

- Khai báo nhiều biến trên một dòng, phân tách bằng dấu phẩy

```swift
var a = 1.0, b = 2.0, c = 3.0
print(a + b + c)              // 6.0```

- Khai báo kiểu dữ liệu nếu không khởi tạo ngay một giá trị

```swift
var hey: String
/* print(hey)*/
hey = "there"
print(hey)                    // there
  • Có thể đặt tên biến là emoji
var 🐮 = "ridiculous"
print(🐮)                    // ridiculous```

### 4. Constants

- Khai báo hằng số sử dụng từ khoá `let`

- Một hằng số có thể xuất hiện bất cứ nơi nào một câu lệnh var có thể

```swift
let s = "string"
print(s)            // string

let n = 500000000
print(n)            // 500000000```

- Khi khao báo hằng số, luôn luôn phải có giá trị khởi tạo, nếu không trình biên dịch sẽ báo lỗi

```swift
let r: Double // error```

### 5. Strings

- Kiểu dữ liệu String

- Biểu thị một chuỗi văn bản, giá trị chuỗi được đặt trong cặp dấu nháy kép `" "`

```swift
var str: String = "Hello"
var smile = "😄"
var combined = str + " " + smile```

- Chuỗi là tập hợp các kí tự, một chuỗi có thể tách thành một mảng các kí tự và ngược lại, một mảng kí tự có thể ghép lại thành một chuỗi

```swift
let dogCharacter: [Character] = ["D", "o", "g", "🐶"]
let dogString: String(dogCharacter)

print(dogString)

for character in dogString {
    print(character)
}
  • Một số thuộc tính
let currentDay = "Tuesday"
let prefix = "Today is "

let today = prefix + currentDay
print(today)

// .isEmpty để kiểm tra xem chuỗi có rỗng hay không, isEmpty = true là rỗng
print(currentDay.isEmpty)

// nối chuỗi = appending
let anotherToday = prefix.appending(currentDay)
print(anotherToday)

// viết hoa
print(today.uppercased())

// viết thường
print(today.lowercased())

// Kiểm tra đầu chuỗi, cuối chuỗi
print(today.prefix(5)); print(today.suffix(6))

// Kiểm tra xem trong chuỗi có chứa chuỗi mình muốn tìm
print(today.contains("Monday"))

// đảo chuỗi
today.reversed()```

### 6. Vòng lặp for

- Vòng lặp sử dụng để duyệt một tập hợp

- Toán tử nửa kín: Phạm vi không bao gồm số cuối cùng

```swift
for index in 1..<5 {
    print(index)           // 1 2 3 4
}```

- Toán tử khép kín: Phạm vi bao gồm số cuối cùng

```swift
for index in 1...5 {
    print(index)           // 1 2 3 4 5
}```

### 7. If/else

**Cấu trúc rẽ nhánh trong swift** sử dụng để kiểm tra một hoặc nhiều điều kiện. Một hoặc nhiều câu lệnh sẽ được thực thi nếu điều kiện được xác định là **đúng (true)** và ngược lại những câu lệnh khác sẽ được thực thi nếu điều kiện được xác định là sai (xử lý ngược lại là không bắt buộc).

![](https://media.techmaster.vn/api/static/8103/bo9ek5451coco9d0vvvg)

- Cấu trúc if: kiểm tra một biểu thức nào đó có hợp lệ hay không

```swift
let x: Int = 10
if x > 9 {
    print("Giá trị x lớn hơn 9")
}
  • Cấu trúc if … else: mở rộng cấu trúc của if, quan tâm đến việc nếu biểu thức không hợp lệ thì làm gì
let a: Int = 20
if a % 2 == 0 {
    print("\(a) là số chẵn")
} else {
    print("\(a) là số lẻ")
}
  • Cấu trúc if … else if … else: kiểm tra nhiều trường hợp
let n: Int = -20
if n < 0 {
    print("n âm")
} else if n > 0 {
    print("n dương")
} else {
    print("n = 0")
}

8. Switch

  • switch: xét và so sánh đối tượng xem đúng giá trị với case nào

  • case: là một trường hợp để so sánh giá trị. Có thể là 1 hoặc nhiều giá trị

  • default: nếu không đúng với case nào thì sẽ thực hiện khối lệnh trong default

  • fallthrough: cho phép thực hiện case kế tiếp

// khai báo biến option
let option = 15

switch option {
case 0...10:
    print("Case 0...10")
    // fallthrough: Thực thi trường hợp tiếp theo
    fallthrough
case 11...20:
    print("Case 11...20")
    // fallthrough: Thực thi trường hợp tiếp theo
    fallthrough
case 21...30:
    print("Case 21...30")
default:
    print("Default case")
}

9. Arrays

Nhiều phần tử cùng kiểu, tập hợp lại với nhau thành một thứ tự tạo thành mảng

  • Khởi tạo mảng:
// Một mảng các số nguyên 1, 2, 3
let myNumbers: [Int] = [1, 2, 3]

// Mảng String rỗng
var emptyStrings: [String] = [] // hoặc var emptyStrings = [String]()

// Khởi tạo mảng có 10 phần tử số nguyên, các phần tử có giá trị giống nhau
var digits = [Int](repeating: 0, count: 10)

Thao tác với mảng:

var numberArray = [1, 43, 23, 0]

// Kiểm tra mảng rỗng
numberArray.isEmpty

// Kiểm tra mảng có bao nhiêu phần tử
numberArray.count

// Truy cập phần tử trong mảng bằng index
print(numberArray[2])

// Truy cập nhanh đến phần tử đầu / cuối mảng
numberArray.first; numberArray.last

// Duyệt mảng
for i in numberArray {
    print(i)
}

// Duyệt mảng lấy cả index và giá trị
for (index, value) in numberArray.enumerated() {
    print("Chỉ số \(index) có giá trị \(value)")
}

// Thêm một phần tử
numberArray.append(19)

// Thêm một mảng phần tử
numberArray += [12, 0, 5] // hoặc: numberArray.append(contentOf: [12, 0, 5])

// Chèn 1 phần tử vào vị trí index
numberArray.insert(28, at: 2)

// Xoá khỏi mảng một phần tử theo vị trí index
numberArray.remove(at: 3)

// Xoá phần tử đầu, cuối của mảng
numberArray.removeFirst(); numberArray.removeLast()

// Xoá tất cả phần tử của mảng
numberArray.removeAll()

10. Dictionaries

Dictionary giống mảng đều là một collection type, là tập hợp gồm nhiều phần tử

Mảng quản lý phần tử theo index, Dictionary quản lý phần tử theo định danh (key)

  • Khởi tạo dictionary:
// tạo dictionary rỗng
var dictionaryOne = [String: String]()
var dictionaryTwo = [Int: String]()

// tạo dictionary 2 phần tử
var airports: [String: String] = ["NoiBai": "Hà Nội", "SaoVang": "Thanh Hoá"]
  • Thao tác với dictionary:
// Thêm phần tử
airports["TanSonNhat"] = "TP. Hồ Chí Minh"

// Sửa giá trị phần tử
airports.updateValue("Thành phố Hồ Chí Minh", forKey: "TanSonNhat")

// Xoá phần tử
airports.removeValue(forKey: "TanSonNhat")

// Duyệt dictionary
for (aiportCode, airportName) in airports {
    print("\(aiportCode) - \(airportName)")
}

// Duyệt theo key hoặc value
for airportCode in airports.keys {
    print(airportCode)
}

for airportName in airports.values {
    print(airportName)
}

11. Tuples

Tuples trong Swift chiếm không gian giữa các Dictionary và Struct, chúng chứa các loại dữ liệu rất cụ thể (như một cấu trúc) nhưng có thể được tạo ra một cách nhanh chóng (như từ điển). Chúng thường được sử dụng để trả về nhiều giá trị:

var letters = ("a", "b")

let (first, second) = letters

print(first)                      // a
print(second)                     // b

print(letters.0)                 // a
print(letters.1)                 // b

var letters2 = (first: "a", second: "b")
print(letters2.first)            // a
print(letters2.second)           // b```

### 12. Optional

- Optional là một khái niệm đặc biệt trong Swift dùng để xử lý việc thiếu giá trị của biến, object,  Thiếu giá trị là khi đối tượng đó không có giá trị (gọi là nil), hay trong các ngôn ngữ khác là “null”

- ?! là một thể hiện để nói về optional của đối tượng đó

- Khi sử dụng ? là khi muốn nói rằng “đối tượng đó có thể có giá trị hoặc không” tức là có thể bị nil

- Khi sử dụng ! là khi muốn nói rằng “đối tượng này chắc chắn có giá trị” khi sử dụng. Chỉ nên dùng ! khi đã biết chắc chắn đối tượng mình sử dụng sẽ được gán giá trị trước khi dùng nếu không app sẽ bị crash

```swift
var yearOfBirth: Int?

if yearOfBirth != nil {

    var age = 2018 - yearOfBirth!

}```

### 13. Funtions

Hàm gồm 2 phần là **khai báo hàm****định nghĩa hàm**

**Khai báo hàm** là thông báo với trình biên dịch về tên hàm, tham số truyền vào, kiểu trả về

**Định nghĩa hàm** là phần thân hàm (xử lý của hàm)

 dụ 1:

```swift
// Định nghĩa một hàm
// Tên hàm: sayHello
// Tham số: name, kiểu String
// Trả về (return): String

func sayHello(name: String) -> String {

    // Nếu name rỗng
    if name.isEmpty {
        return "Hello every body!"
    }

    // Nếu name có giá trị
    return "Hello" + name
}

Ví dụ 2:

// Định nghĩa một hàm, không có tham số, không có kiểu trả về
func testSayHello(){

    // Gọi hàm sayHello(), truyền vào một string rỗng
    let greeting1 = sayHello(name: "")
    print("greeting1: " + greeting1)

    // Gọi hàm sayHello(), truyền vào một string rỗng
    let greeting2 = sayHello(name: "Swift")
    print("greeting2: " + greeting2)
}

// Gọi hàm testSayHello()
testSayHello()

Hàm trả về 1 giá trị:

// Định nghĩa một hàm tính tổng 3 số Int, trả về kiểu Int.
func sum(a: Int, b: Int, c: Int) -> Int {
    return a + b + c
}

// Định nghĩa một hàm để tìm số lớn nhất trong 3 số
func max3So(a: Int, b: Int, c: Int) -> Int {

    var m = a
    if m < b {
        m = b
    }
    if m > c {
        return m
    }

    return c
}

Hàm trả về nhiều giá trị (Tuples):

func getMinMax(arrs: [Int]) -> (min: Int, max: Int) {

    // Nếu mảng không có phần tử thì trả về (0, 0)
    if arrs.count == 0 {
        return (0, 0)
    }

    var min = arrs[0]
    var max = arrs[0]

    for a in arrs {
        if min > a {
            min = a
        }

        if max < a {
            max = a
        }
    }

    return (min, max)
}

Swift sử dụng variableName: DataType… để đánh dấu một tham số là Variadic

// Một hàm với các tham số variadic: nums
// Tham số nums: giống như một mảng các số Int
func sum(nums: Int...) -> Int {
    var tong = 0
    for i in nums {
        tong += i
    }
    return tong
}

// in hàm truyền vào 3 số
print(sum(nums: 1, 2, 4))

// in hàm truyền vào 7 số
print(sum(nums: 3, 23, 1, 0, 58, 5, 9))

Tham số của hàm mặc định là hằng số, do đó nếu muốn thay đổi giá trị của các tham số và muốn nó tồn tại sau lời gọi hàm kết thúc thì chúng ta định nghĩa hàm với tham số inout

// Hàm hoán vị 2 số nguyên
func swap( a: inout Int, b: inout Int) {
    let t = a
    a = b
    b = t
}

var a = 10
var b = 17

// Gọi hàm
swap(&a, &b)

// Sau khi chạy hàm: a là 17, b là 10
print("a = \(a), b = \(b)")```

Swift cho phép viết một hàm bên trong một hàm khác, hàm này được sử dụng trong nội bộ của hàm cha

```swift
// Hàm trả về tiền thuế, dựa trên mã quốc gia và lương
func getTaxAmount(countryCode: String, salaryAmount: Int) -> Int {
    func getUSATaxAmount(salaryAmount: Int) -> Int {
        return 15 * salaryAmount / 100
    }

    func getVietNamTaxAmount(salaryAmount: Int) -> Int {
        return 10 * salaryAmount / 100
    }

    if countryCode == "$" {
        // USA
        return getUSATaxAmount(salaryAmount: salaryAmount)
    } else if countryCode == "VND" {
        // VietNam
        return getVietNamTaxAmount(salaryAmount: salaryAmount)
    }

    // Các quốc gia khác
    return 5 * salaryAmount / 100
}

14. Closures

  • Closure có cú pháp bao đóng, là một hàm không tên
/*
{ (parameters) -> return type in
body
}
*/

var numbers = [1, 2, 3, 4]

var reversed = numbers.sorted(by: {(a: Int, b: Int) -> Bool in
    return a > b
})
// Khai báo một biến myVar1, với kiểu dữ liệu, và gán giá trị cho nó.
var myVar1 : () -> () =  {

    print("Hello from Closure 1");
}

// Khai báo một biến myVar2, với kiểu dữ liệu, và gán giá trị cho nó.
var myVar2 : () -> (String)  = { () -> (String) in

    return "Hello from Closure 2"

}

// Khai báo một biến myVar3, với kiểu dữ liệu, và gán giá trị cho nó.
var myVar3 : (Int, Int) -> (Int)  =  { (a : Int, b: Int) -> (Int) in

    var c : Int =  a + b

    return c
}

15. Enums

Enum xác định một loại cấu trúc phổ biến cho một nhóm các giá trị liên quan và cho phép làm việc với các giá trị đó theo cách an toàn.

enum Example {
    case A
    case B
    case C
    case D
}

var example = Example.A          // (Enum Value)
example = .B

switch example {
case .A:
    print("A")
case .B:
    print("B")                               // B
case .C:
    print("C")
case .D:
    print("D")
}```

```swift
enum Types {
    case Str(String)
    case Num(Double)
}

var a = Types.Str("hello")
a = .Num(1.0)

switch a {
case .Str(let val):
    print(val)
case .Num(let val):
    print(val)                             // 1.0
}```

### 16. Classes

Swift là ngôn ngữ kế thừa ngôn ngữ **C****Objective-C**, nó vừa là một ngôn ngữ hướng thủ tục, vừa là một ngôn ngữ hướng đối tượng.

**Class** chính là khái niệm của các ngôn ngữ lập trình hướng đối tượng

**Class** có các **thuộc tính (properties)** và phương thức **(method)**, về bản chất phương thức được hiểu là một hàm của lớp.

Từ một lớp, có thể tạo ra các đối tượng

```swift
class <tên Class>: <Kế tha Class cha, nếu > {
    // Khai báo thuộc tính
    // Khởi tạo phương thức
}

Khai báo class và khởi tạo không tham số

- init là trình khởi tạo - một phương thức (method) mà class sẽ gọi đến khi chúng ta tạo một đối tượng Person.

class Rectangle1  {

    // thuộc tính chiều rộng, chiều cao
    var width: Int = 5
    var height: Int = 10

    // Constructor (khởi tạo) mặc định (Không tham số)
    // (Được sử dụng để tạo ra đối tượng)
    init()  {
    }

    // Phương thức dùng để tính diện tích hình chữ nhật.
    func getArea()  -> Int  {

        var area = self.width * self.height
        return area
    }
}

=> Khởi tạo đối tượng, kiểu Rectangle1:

// Tạo một đối tượng Rectangle1
// thông qua Constructor mặc định: init()
var rec1  = Rectangle1()

// In ra width, height.
print("rec1.width = \(rec1.width)")
print("rec1.height = \(rec1.height)")

// Gọi phương thức để tính diện tích.
 print("area = \(rec1.getArea())")
  • Khai báo class và khởi tạo có tham số:
class Rectangle2 {

    // thuộc tính chiều rộng, chiều cao
    var width: Int
    var height: Int

    // Một Constructor có 2 tham số.
    // (Được sử dụng để tạo ra đối tượng)
    // self.width trỏ tới thuộc tính (property) width của class.
    init (width: Int, height: Int)  {
        self.width = width
        self.height = height
    }

    // Phương thức dùng để tính diện tích hình chữ nhật.
    func getArea()  -> Int  {

        var area = self.width * self.height
        return area
    }
}

=> Khởi tạo đối tượng Rectangle2:

// Tạo đối tượng Rectangle2
// thông qua Constructor có 2 tham số: init(Int,Int)
var rec2 = Rectangle2(width: 10, height: 15)

// In ra width, height.
print("rec2.width = \(rec2.width)")
print("rec2.height = \(rec2.height)")

// Gọi phương thức để tính diện tích.
print("area = \(rec2.getArea())")

Deinitializer

Một hàm deinitializer được gọi ngay trước khi instance của một class được giải phóng

Hàm deinit chỉ có sẵn trong class

class D {
    deinit {
        print("Deinit ")
    }
}

var d: D? = D()
d = nil

17. Structs

Trong Swift, Struct (cấu trúc) là một kiểu giá trị đặc biệt, nó tạo ra một biến để lưu trữ nhiều giá trị riêng lẻ, mà các các trị này có liên quan tới nhau

struct <tên Struct>: <kế tha 1 hoc nhiu giao thc> {
    // Khai báo thuộc tính
    // Khai báo phương thức
}
  • Khai báo struct:
struct Employee {

    // khai báo thuộc tính
    var empNumber: String
    var empName: String
    var position: String

    // Constructor (khởi tạo)
    init(empNumber:String, empName:String, position:String) {
        self.empNumber = empNumber;
        self.empName = empName;
        self.position = position;
    }
}

=> Khởi tạo một đối tượng kiểu Employee

func test_EmployeeStruct()     {

    // Tạo một biến kiểu struct Employee.
    let john = Employee(empNumber:"E01",empName: "John", position: "CLERK")

    print("Emp Number: " + john.empNumber)
    print("Emp Name: " + john.empName)
    print("Emp Position: " + john.position)

}
  • Phương thức khởi tạo trong struct

Struct có thể có các Constructor (Phương thức khởi tạo), nhưng không có Destructor (Phương thức huỷ đối tượng)

Bạn có thể không viết, viết một hoặc nhiều constructor cho Struct

Trong khởi tạo, chúng ta phải gán tất cả các trường chưa có giá trị

// struct không có hàm khởi tạo
struct Employee {

    var empNumber:String
    var empName:String
    var position:String

}
  • Phương thức và thuộc tính của Struct

Struct cũng có các phương thức và thuộc tính như Class

struct Book  {

    // thuộc tính
    var title: String
    var author: String

    // Khởi tạo
    init(  title:String, author:String) {
        self.title = title
        self.author = author
    }

    // Phương thức
    func getInfo() -> String {
        return "Book Title: " + self.title + ", Author: " + self.author
    }
}

18. Values and references

  • Class là kiểu tham chiếu
class Job {
    var title = ""
}

var job1 = Job()
var job2 = job1
job1.title = "singer"
print(job2.title)                   // singer

Triple equals checks identity.
print(job1 === job2)                // true```

- Struct, dictionary, array đều là kiểu tham trị

```swift
var band1 = ["bob": "singer", "dan": "guitarist"]
var band2 = band1

band2["bob"] = "drummer"
print(band1["bob"])                // singer```

```swift
var bands1 = ["radiohead", "telekinesis", "nada surf"]
var bands2 = bands1
print(bands1 == bands2)           // true

bands1[0] = "the orwells"

print(bands2[0])                  // radiohead```

### 19Class extensions

- Sử dụng extension để mrng cho các class hin :

```swift
var someInt = 3

extension Int {
    func isOdd () -> Bool{
        return self % 2 != 0
    }

    func isEven() -> Bool {
        return !isOdd()
    }

    func times(task: (Int)->()) {
        for i in 0..<self {
            task(i)
        }
    }
}

print(someInt.isOdd())                 // true
print(2.isEven())                      // true

2.times({(Int i) in
    print(i)                           // 0, 1
})```

### 20. Protocols

- Khi nói đến Protocol nghĩa là ta đang nói đến 1 cái gì đó trừu tượng

```swift
protocol Image {
    var filename: String { get set }
    var filesize: Double { get }
    var mimetype: String { get }
    var height: Double { get }
    var width: Double { get }

    func save ()

    mutating func resize(width: Double, height: Double)
}```

- Struct hoặc class  thkế tha  thc thi các method ca protocol

```swift
struct Gif : Image {
    var filename: String
    var filesize: Double
    var mimetype = "image/gif"
    var height: Double
    var width: Double

    func save() {

    }

    mutating func resize(width: Double, height: Double) {

    }
}

class Png : Image {
    var filename: String
    var filesize: Double
    var mimetype = "image/png"
    var height: Double
    var width: Double

    init(filename: String, filesize: Double, width: Double, height: Double) {
        self.filename = filename
        self.filesize = filesize
        self.width = width
        self.height = height
    }

    func save() {

    }

    func resize(width: Double, height: Double) {

    }
}

var gif = Gif(filename: "rainbow.gif", filesize: 2.3, mimetype: "image", height: 50, width: 50)
var png = Png(filename: "carry.png", filesize: 3.4, width: 100, height: 54)```

Chúc các bạn học Swift vui vẻ 🥰!