11/08/2018, 22:16

Tìm hiểu về Optional trong Swift

Trong bài viết này, người viết xin giới thiệu về Optional, một khái niệm mới trong ngôn ngữ lập trình Swift. Với việc sử dụng optional, ngôn ngữ Swift được Apple giới thiệu là ngôn ngữ “an toàn” hơn so với ngôn ngữ Objective-C trước đó 1. Overview Trong Swift, khi khởi tạo các biến, ...

Trong bài viết này, người viết xin giới thiệu về Optional, một khái niệm mới trong ngôn ngữ lập trình Swift. Với việc sử dụng optional, ngôn ngữ Swift được Apple giới thiệu là ngôn ngữ “an toàn” hơn so với ngôn ngữ Objective-C trước đó

1. Overview

Trong Swift, khi khởi tạo các biến, các biến này mặc định sẽ được khởi tạo dưới dạng non-optional: tức là phải được gán giá trị mà không được để nil(non-nil). Nếu chúng ta gán giá trị nil cho các biến non-optional này, trình biên dịch sẽ thông báo lỗi.

Ví dụ: Khi gán biến non-optional giá trị nil:

var message: String = “I’m learning Swift” // OK

message = nil // compile-time error

Khi khởi tạo biến non-optional mà không gán giá trị:

class Messenger {

    var message1: String = “I’m learning Swift” // OK

    var message2: String // compile-time error

}

Optional trong Swift được sử dụng để giải quyết vấn đề này, biến optional được khởi tạo bằng dấu hỏi “?” sau khai báo kiểu biến, như ví dụ sau

class Messenger {

    var message1: String = “I’m learning Swift” // OK

    var message2: String?// OK

}

2. Vì sao là optional

Swift được Apple nhắc đến là 1 “safe language”, optional là một ví dụ về tính an toàn của Swift. Như trong ví dụ trên, optional trong Swift cung cấp khả năng kiểm tra các lỗi thường sảy ra của chương trình trong “run-time” ngay từ trong “compile-time”. Lấy ví dụ dưới đây để hiểu rõ hơn về sức mạnh của optional

Với Objective-C

-(NSString *)findStockCode: (NSString *)company {

    if([company isEqualToString:@”Apple”]) {

        return @”AAPL”;

    } else if ([company isEqualToString:@”Google”]) {

        return @“GOOG”

    }

    return nil

}

NSString *stockCode = [self findStockCode:@”Facebook”] //nil is returned

NSString *text = @”Stock Code - ”;

NSString *message = [text stringByAppendingString: stockCode]; // runtime error

NSLog(@”%@”, message);

Trong đoạn code trên, compile-time sẽ không báo lỗi, chương trình có thể chạy, nhưng khi chạy chương trình, exception sảy ra, chương trình chạy lỗi Đoạn code trên được viết lại bằng Swift như sau:

func findStockCode(company: String) -> String? {

    if(company == “Apple”) {

        return “AAPL”

    } else if (company == “Google”) {

        return “GOOG”

    }

    return nil

}

var stockCode:String? = findStockCode(“Facebook”)

let text = “Stock Code - ”

let message = text + stockCode // compile-time error

println(message)

Trong ví dụ với Swift như trên, trình biên dịch bắt được lỗi ngay trong quá trình biên dịch, bạn phải sửa lỗi để chạy được chương trình, và khi chương trình đã chạy, lỗi sẽ không sảy ra. Optional làm chất lượng code tốt hơn, người lập trình quản lý được nil exception ngay trong quá trình biên dịch

3. Unswapping optional

Với ví dụ ở trên, để chương trình có thể chạy, chúng ta cần check giá trị nil cho biến như sau:

var stockCode: String? = findStockCode(Facebook)

let text = “Stock code - ”

if stockCode {

    let message = text + stockCode!

    Prinln(message)

}

trong ví dụ trên, chúng ta kiểm tra để chắc chắn rằng biến stockCode chứa giá trị, khi chúng ta biết chắc chắn biến có chứa giá trị, chúng ta “unswap optional” bằng cách đặt dấu chấm than “!” ngay sau biến. bằng cách này, chúng ta loại bỏ optional trong biến điều gì sẽ sảy ra trong trường hợp chúng ta quên không kiểm tra biến chắc chắn chứa giá trị, như trong ví dụ sau:

var stockCode: String? = findStockCode(Facebook)

let text = “Stock code - ”

let message = text + stockCode!

prinln(message)

Trình biên dịch sẽ không phát hiện ra lỗi, nhưng trong khi chương trình chạy, sẽ có lỗi sảy ra với thông báo trả về:

fatal error: Can’t unwrap Optional.None

4. Optional binding

Thay vì unswap biến như trên, có một cách tốt hơn được khuyên dùng để unswap optional trong Swift: “optional binding”. Chúng ta sử dụng optional binding để kiểm tra optional có chứa giá trị hay không, nếu nó có chứa giá trị, unswap optional và gán 1 biến tạm thời cho optional đó. Ví dụ:

var stockCode:String? = findStockCode(“Facebook”)

let text = “Stock Code - ”

if let tempStockCode = stockCode {

    let message = text + tempStockCode

    println(message)

}

“if let” và “if var” là 2 keyword của optional binding. Đoạn code trên nghĩa là: nếu biến stockCode chứa giá trị, unswap optional của nó, tạo biến tempStockCode và gán giá trị cho biến này bằng giá trị của stockCode và thực hiện đoạn code bên trong. Ngược lại, nếu biến stockCode bằng nil, bỏ qua đoạn code này

chúng ta có thể viết lại code như sau:

let text = “Stock Code - ”

if var stockCode = findStockCode(“Facebook”) {

    let message = text + stockCode

    print(message)

}

Trong ví dụ trên, stockCode không phải optional, vì thế chúng ta không cần phải unswap biến stockCode

5. Optional Chaining

Lấy ví dụ sau:

class Stock = {

    var code: Sring?

    var price: Double?

}

func findStockCode(company:String) -> Stock? {

    if(company == “Apple”) {

        let appl: Stock = Stock()

        appl.code = “APPL”

        appl.price = 90.32

        return appl

    }else if (company == “Google”) {

        let goog: Stock = Stock()

        goog.code = “GOOG”

        goog.price = 90.32

        return appl

    }

    return nil
}

if let stock = findStockCode(“Apple”) {

    if let sharePrice = stock.price {

        let totalPrice = sharePrice * 100

        println(totalPrice)

    }

}

Trong ví dụ ở trên, cả biến stock và property của nó là stock.price đều là optional, chúng ta lần lượt dùng optional binding cho stock và stock.price để unswap các optional

Tuy nhiên, chúng ta có thể sử dụng “optional chaining” để làm code ngắn hơn, giảm các hàm if phải sử dụng như sau:

if let sharePrice = findStockCode(“Apple”)?.price {

    let totalPrice = sharePrice * 100

    println(totalPrice)

}

Như chúng ta thấy trong đoạn code trên, thay vì sử dụng nhiều hàm if lồng nhau, chúng ta chỉ phải sử dụng 1 hàm if, code của chúng ta sẽ sạch hơn và đơn giản hơn

Kết luận

Trong bài viết này, người viết đã giới thiệu đến các bạn khái niệm optional, một khái niệm mới của Swift mà trong Objective-C chưa tồn tại. Hi vọng bài viết này có thể giúp ích các bạn mới học lập trình iOS và ngôn ngữ Swift.

Để tìm hiểu rõ hơn về ngôn ngữ Swift, các bạn có thể tham khảo thêm tại https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html

Bài viết này được viết dựa trên tutorial từ trang http://www.appcoda.com. Các bạn có thể tham khảo bài viết gốc của tutorial ở link sau http://www.appcoda.com/beginners-guide-optionals-swift/

Cuối cùng, người viết xin cảm ơn các bạn đã theo dõi bài viết này!

0