Cách viết một Singleton sao cho đúng trong lập trình IOS với Swift

Trong lập trinh IOS chẳng mấy xa lạ với design pattent Singleton. Nhưng đã bao giờ bạn thực sự để ý cách viết và dùng nó sao cho thực sự hợp lý. Trong bài này ta cùng nhau tìm hiểu cách viết và dùng singleton trong lập trình IOS cụ thể là ngôn ngữ swift sao cho đúng và hợp lý.
Về cơ bản có 3 điều cần nhớ về singleton:

Singleton phải là duy nhất. Tức là chỉ có duy nhất một cho xem trong suốt vòng đời của app. Nó được xậy dựng như một biến global. Để singleton là duy nhất thi khi khởi tạo cần được private. Từ quan tâm số 1, chỉ cấp quyền có một instance được tạo ra trong suốt quá trình chạy app, điều này có nghĩa nó cần một thread an toàn. Nếu một singleton được tạo ra không chính xác trong code, bạn có thể sẽ có 2 thread cùng khở tạo một singleton tại cùng một lúc. Điều này khiến nó không còn là duy nhất trừ khi ta đưa nó vào một thread an toàn. Cách giải quyết ở đây là đưa hàm khởi tạo vào một dispatch_once GCD block. Nó giúp đỡ cam kết rằng singleton chỉ được chạy một lần duy nhất.
giờ đây ta cùng đi qua các cách để tạo ra một singleton thông qua các thời điểm bằng ngồn ngữ swift
Swift 1.0
Đây là lúc khi swift mới thành lập. Chưa có nhiều giúp đỡ và ảnh hưởng nhiều bởi objective-C. Một ví dụ dễ hiểu

class TheOneSingleton {     class var sharedInstance: TheOneSingleton {         struct Static {             static var oneToken: dispatch_once_t = 0             static var instance: TheOneSingleton? = nil         }         dispatch_once(&Static.oneToken) {             Static.instance = TheOneSingleton()         }         return Static.instance!     } } 

Đây là một cách viết điển hình hồi đó và có thể rất dễ tim ra trên các nguồn khác nhau. Nhưng đây là cách viết khá tệ vì nó đi ngược lại các phương châm cơ bản của ngôn ngữ swift: terse and expressive
dùng struct
Để giải quyết các nhược điểm trên, lúc này họ dùng một cách thức khác. Bằng cách lồng thêm struct vào. Cách này tuy cũ nhưng đến nay vẫn thi thoảng được dùng.

class TheOneSingleton {     class var sharedInstance: TheOneSingleton {         struct Static {             static let instance = TheOneSingleton()         }         return Static.instance     } } 

Cách viết này cơ bản giải quyết được các nhược điểm của cách đầu tiên, mặc dù vậy nó chỉ là có tác dụng nhất tại lúc đó mà thôi.
One Line Singleton
Bắt đầu từ swift 1.2. có mặt một cách để viết một singleton ngắn hơn nhiều. Đó là dùng biết global.

class TheOneSingleton {     class var sharedInstance: TheOneSingleton {         return shared     } } private let shared = TheOneSingleton() 

Có một điều đặc sắc rằng vì sao ở đây ta không còn thấy dispatch_once. Nhưng đầy là điều apple muốn. https://lập trình viêneloper.apple.com/swift/blog/?id=7 Đoạn trích dẫn sau chứng minh rằng chúng được gói trong một dispatch_once

“The lazy initializer for a global variable (also for static members of structs and enums) is run the first time that global is accessed, and is launched as `dispatch_once` to make sure that the initialization is atomic. This enables a cool way to use `dispatch_once` in your code: just declare a global variable with an initializer and mark it private.” — Apple's Swift Blog 

mặc dù vậy với cách viết này đưa khiến ta gắp chuyện khi đặt tên, trùng tên biến. Điều này khiến một cách có tác dụng được đưa ra

class TheOneSingleton {     static let sharedInstance = TheOneSingleton() } 

Rõ ràng hơn nữa là kể từ swift 3 dispatch_once không còn được giúp đỡ nữa. mặc dù vậy để cam kết tính duy nhất của singleton bạn đừng quên private phương thức khởi tạo của class nhé

class TheOneSingleton {     static let sharedInstance = TheOneSingleton()     private init() {} } 

Điều này ngăn cản người khác có thể dùng phương thức khởi tạo default để phá vỡ tinh duy nhất của singleton
Kết Luận
Trong phần này mình đã nói về một vài cách để viết ra một singleton dùng swift, mặc dù vậy với bạn có thể chứng mình cả 3 cách thức đều chỉ khởi tạo một lần bằng cách đưa cả 3 cách thức này vào source code đặt fixbug để kiểm tra. Nếu có thắc mắc gì vui long comment bên dưới nhé.

Nguồn viblo.asia