Singleton với các thuộc tính trong Swift 3


88

Trong tài liệu Sử dụng Swift với Cocoa và Objective-C của Apple (được cập nhật cho Swift 3), họ đưa ra ví dụ sau về mẫu Singleton:

class Singleton {
    static let sharedInstance: Singleton = {
        let instance = Singleton()

        // setup code

        return instance
    }()
}

Hãy tưởng tượng rằng singleton này cần quản lý một mảng chuỗi biến đổi. Làm thế nào / ở đâu tôi sẽ khai báo thuộc tính đó và đảm bảo nó được khởi tạo đúng cách vào một [String]mảng trống ?

Câu trả lời:


236

Đối với tôi đây là cách tốt nhất, hãy đặt init ở chế độ riêng tư. Cú pháp Swift 3 \ 4 \ 5

// MARK: - Singleton

final class Singleton {

    // Can't init is singleton
    private init() { }

    // MARK: Shared Instance

    static let shared = Singleton()

    // MARK: Local Variable

    var emptyStringArray = [String]()

}

4
Tôi đã ủng hộ câu trả lời này, nhưng để phù hợp với cú pháp Swift 3, "sharedInstance" phải được đổi thành chỉ "shared".
B-Rad

1
Trừ khi có một hồi quy từ nhanh chóng từ 2 đến nhanh chóng 3 bạn không
Thibaut noah

1
Loại sau khi chia sẻ có thể được bỏ qua đúng không? static let shared = Singleton()
chriswillow vào

1
@YannickSteph bạn không phải viết static let shared: Singleton = Singleton()thay vào đó bạn chỉ có thể viếtstatic let shared = Singleton()
chriswillow

3
@RomanN Không, bạn không thể ghi đè init vì nó không kế thừa một lớp. Nếu bạn có thể làm điều đó, với ví dụ này final class Singleton: NSObject { private override init() { } }
YannSteph

59

Bạn có thể khởi tạo một mảng trống như thế này.

class Singleton {

    //MARK: Shared Instance

    static let sharedInstance : Singleton = {
        let instance = Singleton(array: [])
        return instance
    }()

    //MARK: Local Variable

    var emptyStringArray : [String]

    //MARK: Init

    init( array : [String]) {
        emptyStringArray = array
    }
}

Hoặc nếu bạn thích một cách tiếp cận khác, cách này sẽ ổn.

class Singleton {

    //MARK: Shared Instance

    static let sharedInstance : Singleton = {
        let instance = Singleton()
        return instance
    }()

    //MARK: Local Variable

    var emptyStringArray : [String]? = nil

    //MARK: Init

    convenience init() {
        self.init(array : [])
    }

    //MARK: Init Array

    init( array : [String]) {
        emptyStringArray = array
    }
}

Phương pháp này không hoạt động trong một tiện ích mở rộng? extension Cache { static let sharedInstance: Cache = { let instance = Cache() return instance }() }
Andy

1
Điều thú vị là Apple sử dụng class vartrong iOS 10 cho các ứng dụng đơn lẻ (ví dụ: UIApplication). Việc triển khai của họ có giống như thế này không?
jjatie

2
Tôi thích các phương thức singleton init hơn là privatecác phương thức không phải internal. Điều này ngăn những người khác sử dụng bộ khởi tạo '()' mặc định cho lớp này.
Kumar C

1
@KumarC Bạn nói đúng, sẽ không giải quyết được vấn đề nếu chúng tôi thêm privatevào init.

@TikhonovAlexander Bạn có thể mang thêm thông tin không?
Dominique Vial,

30

Theo tài liệu của apple: Trong Swift, bạn có thể chỉ cần sử dụng thuộc tính kiểu tĩnh, được đảm bảo chỉ khởi tạo một cách lười biếng một lần, ngay cả khi được truy cập đồng thời trên nhiều luồng .

class Singleton {

    // MARK: - Shared

    static let shared = Singleton()
}

Với phương thức khởi tạo:

class Singleton {

    // MARK: - Shared

    static let shared = Singleton()

    // MARK: - Initializer

    private init() {
    }

}

3
tại sao init () không phải là private?
XcodeNOOB

0

Mọi khởi tạo sẽ được thực hiện trong một phương thức init. Không có sự khác biệt ở đây giữa một singleton và một non-singleton.


26
Một đoạn mã bổ sung trả lời trực tiếp câu hỏi sẽ làm cho câu trả lời này hữu ích hơn.
Reda Lemeden
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.