Category: Swift

  • Swift — Optionals, Guard and Nil Coalescing

    Guard

    Guard cũng gần giống như “if let” (optionals binding), nó cũng được sử dụng để xử lý các object dạng Optionals, cũng check các điều kiện khác “nil” thì cho phép thực hiện các logic tiếp theo… Nhưng Guard còn được gọi với tên gọi khác là “Early Exit”, vậy Guard khác “if let” (Optional binding) ở điểm nào?

    Hãy xem xét ví dụ sau:

    Raw: https://gist.github.com/RioV/f551c21f3c2c16946f2bdd338c3fd24f

    Ví dụ trên là sự so sánh giữa việc sử dụng Optional Binding và Guard để xử lý việc check object có thoả mãn điều kiện là khác “nil” hay không.

    Với Optional Binding thì ta tập trung xử lý trường hợp có value trước. Còn với Guard thì ta ưu tiên xử lý trường hợp không có value trước. Hai khái niệm trên cùng xử lý việc tương tự nhau, nhưng tuỳ hoàn cảnh cụ thể mà ta dùng Optional binding hay Guard cho phù hợp.

    Tất nhiên là Guard còn được sử dụng để check hàng loạt các điều kiện khác nhau (không nhất thiết chỉ là check nil) xem các điều kiện có cùng thoả mãn hay không.

    Ví dụ:

    let name : String? = "Swift"
    let version : Int = 3
    let owner : String = "Apple"
    func checkMultiCondition(name : String?, version : Int, owner : String) {
    guard let name = name, version > 2, owner == "Apple" else {
    print("Input parameters not match!!!")
    return
    }
    print(name)
    print(version)
    print(owner)
    }

    Và dùng Guard để check các điều kiện tuần tự thì…tuyệt vời ông mặt giời luôn. (search thêm về Happy-Path Programming)

    struct Student {
    let name: String?
    let age: Int?
    let gender: String?
    }
    let student = Student(name: "Rio", age: 27, gender: "Male")
    func validateStudentInfo (_ student: Student) -> String {
    // We do NOT need to using student name, just want to check if
    // student name have value, so using underscore here
    if let _ = student.name {
    if let _ = student.age {
    if let _ = student.gender {
    return "OK"
    } else {
    return "Gender not valid"
    }
    } else {
    return "Age not valid"
    }
    } else {
    return "Name not valid"
    }
    }
    func validateStudentInfoWithGuard (_ student: Student) -> String {
    guard let _ = student.name else {
    return "Name not valid"
    }
    guard let _ = student.age else {
    return "Age not valid"
    }
    guard let _ = student.gender else {
    return "Gender not valid"
    }
    return "OK"
    }
    validateStudentInfo(student)
    validateStudentInfoWithGuard(student)

    Như đoạn code sample trên thì việc sử dụng Guard để check các điều kiện tuần tự nhau rất đơn giản và dễ đọc. Còn nếu sử dụng Optional Binding lồng nhau để check thì source code trông rất tệ và khó đọc. Hãy cân nhắc khi sử dụng 😉

    Có một điều cần chú ý là, với Guard statement thì trong trường hợp “else”, ta bắt buộc phải return ;). Và sử dụng Guard một cách hợp lý sẽ làm source code dễ đọc hơn, dễ maintain hơn.

    Nil Coalescing

    Còn một cách khác để unwrap một object Optionals là sử dụng “nil coalescing”, trong các ngôn ngữ khác thì quen thuộc với cái tên “Null Coalescing” https://en.wikipedia.org/wiki/Null_coalescing_operator

    Dùng “Nil Coalescing” khi mà bạn muốn có giá trị default nào đó cho Optional object, trong trường hợp nó bị nil, như dưới đây:

    Trong ví dụ này ta thấy rằng trường hợp biến “name” bị nil thì lập tức nó được gán value là “No Name”

    Chú ý rằng chỉ sử dụng “Nil Coalescing” với các Object optionals thôi nhé, nếu dùng cho object non-optionals thì compiler sẽ báo lỗi như dưới:

    Nó dụ dỗ xoá nil coalescing đi luôn

    Have Fun

  • Swift — Đôi nét về Optionals

    Swift — Đôi nét về Optionals

    Swift đã giới thiệu một khái niệm mới là Optionals. Vậy Optionals là gì?

    Optional là một khái niệm đặc biệt trong Swift dùng để xử lý việc thiếu giá trị (absence of value — của variable, const, object…)

    Thiếu giá trị là gì? Trong Objective-C, khi muốn thể hiện biến hay object nào đó không có giá trị (value) nào cả thì ta sẽ set chúng bằng “nil”, hay trong các ngôn ngữ khác là “Null”.

    Nhưng trong Swift, việc set một object thành “nil” là không thể, thay vào đó, ta sử dụng Optional.

    Quay trở lại với câu hỏi “Optionals là gì”, ta có thể hiểu một cách dân dã hơn như sau:

    Optional giống như cái hộp quà, có thể trong hộp có quà (optional bao hàm value), mà cũng có thể là không có (optional bao hàm nil). Cái hộp quà (tức optional) lúc nào cũng tồn tại, nhưng quà (value) thì có thể có, cũng có thể không.

    Cách khai báo một biến dưới dạng Optionals:

    Tại sao lại sinh ra Optionals?

    Swift sinh ra là để thay thế cho Objective-C, nên về mặt nào đó nó phải tốt hơn Objective-C. Và có lẽ, Optionals là để đảm bảo tính an toàn hơn của Swift so với Objective-C (Swift được gọi là type safe language :v)

    Xem ví dụ sau

    Objective — C
    Swift

    Ví dụ trên là tạo array chứa danh sách các String, trong đó có String sẽ bị nil. Với Objective-C thì compiler không báo lỗi khi add thêm biến có giá trị nil vào array, do đó khi run time sẽ bị crash (vì không thể add nil vào array). Tuy nhiên, với Swift thì compiler đã báo lỗi Optional type String? chưa được “unwrapped” -> Báo lỗi trong quá trình compile.

    Khi sử dụng Optionals, coder luôn được nhắc đến việc “unwrapped” — mở hộp — một biến để sử dụng (đảm bảo coder luôn chú ý đến việc chắc chắn rằng biến đó có bị nil hay không)

    Làm thế nào để sử dụng giá trị của biến dạng Optionals?

    Unwrapping Optionals — hay còn gọi là mở hộp lấy quà :v

    Các phương pháp unwrapped optionals

    Force unwrapping: sử dụng dấu “!” sau biến optionals:

    Khi sử dụng cách làm này, phải luôn chắc chắn rằng biến có values, nếu không sẽ gây crash chương trình (run time error: fatal error: unexpectedly found nil while unwrapping an Optional value)

    Optional binding: sử dụng “if let” hoặc “if var” để kiểm tra nếu như biến có gía trị thì unwrap và sử dụng giá trị của biến, nếu không thì thôi, ví dụ:

    Cách làm này an toàn hơn vì luôn đảm bảo biến được kiểm tra xem có giá trị hay không trước khi sử dụng, tránh các trường hợp crash chương trình đáng tiếc.

    Về quan điểm cá nhân thì tốt nhất là nên dùng Optional binding khi thao tác với các biến dạng Optionals, dài hơn một chút, nhưng an toàn hơn.

    Tổng kết lại: Optionals là khái niệm mới trong Swift dùng để xử lý việc biến không có giá trị. Khai báo biến dưới dạng Optionals bằng cách thêm “?” vào sau type của biến. Và nên dùng Optionals binding để lấy giá trị của biến optionals.

    !