Singleton พร้อมคุณสมบัติใน Swift 3


88

ในเอกสารการใช้ Swift กับ Cocoa และ Objective-Cของ Apple (อัปเดตสำหรับ Swift 3) พวกเขาให้ตัวอย่างรูปแบบ Singleton ต่อไปนี้:

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

        // setup code

        return instance
    }()
}

ลองจินตนาการว่าซิงเกิลตันนี้ต้องจัดการสตริงตัวแปร ฉันจะประกาศคุณสมบัตินั้นได้อย่างไร / ที่ไหนและตรวจสอบให้แน่ใจว่าได้เริ่มต้นอย่างถูกต้องไปยัง[String]อาร์เรย์ว่างเปล่า

คำตอบ:


236

สำหรับฉันแล้วนี่เป็นวิธีที่ดีที่สุดทำให้ init เป็นส่วนตัว ไวยากรณ์ของ 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
ฉันเพิ่มคะแนนคำตอบนี้ แต่เพื่อให้ตรงกับไวยากรณ์ของ Swift 3 "sharedInstance" ควรเปลี่ยนเป็น "shared" เท่านั้น
B-Rad

1
เว้นแต่จะมีการถดถอยจาก swift 2 เป็น swift 3 คุณไม่ทำ
thibaut noah

1
ประเภทหลังแชร์สามารถเว้นได้ใช่ไหม static let shared = Singleton()
chriswillow

1
@YannickSteph คุณไม่ต้องเขียนstatic let shared: Singleton = Singleton()แทนก็เขียนได้static let shared = Singleton()
chriswillow

3
@RomanN ไม่คุณไม่สามารถแทนที่ init ได้เนื่องจากไม่ได้สืบทอดคลาส ถ้าคุณทำได้ด้วยตัวอย่างนี้ final class Singleton: NSObject { private override init() { } }
YannSteph

59

คุณสามารถเริ่มต้นอาร์เรย์ว่างเช่นนี้

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
    }
}

หรือหากคุณต้องการแนวทางอื่นวิธีนี้ก็ทำได้ดี

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
    }
}

วิธีนี้ใช้ไม่ได้กับส่วนขยายหรือไม่? extension Cache { static let sharedInstance: Cache = { let instance = Cache() return instance }() }
Andrew

1
น่าสนใจที่ Apple ใช้class varใน iOS 10 สำหรับ singletons (เช่น UIApplication) การนำไปใช้งานจะเหมือนกับสิ่งนี้หรือไม่
jjatie

2
ฉันชอบวิธี init เดี่ยวเป็นวิธีการไม่ได้private internalซึ่งจะป้องกันไม่ให้ผู้อื่นใช้ตัวเริ่มต้น '()' เริ่มต้นสำหรับคลาสนี้
Kumar C

1
@KumarC คุณถูกต้องมันจะไม่ช่วยแก้ปัญหานี้ถ้าเราเพิ่มprivateในinit.

@TikhonovAlexander คุณช่วยนำข้อมูลเพิ่มเติมได้ไหม?
Dominique Vial

30

ตามเอกสารที่แอปเปิ้ลที่: ในสวิฟท์คุณก็สามารถใช้สถานที่ให้บริการประเภทคงที่ซึ่งรับประกันได้ว่าจะสามารถเริ่มต้นอย่างเฉื่อยชาเพียงครั้งเดียวแม้ในขณะที่เข้าถึงได้ในหลายหัวข้อพร้อมกัน

class Singleton {

    // MARK: - Shared

    static let shared = Singleton()
}

ด้วยวิธีการเริ่มต้น:

class Singleton {

    // MARK: - Shared

    static let shared = Singleton()

    // MARK: - Initializer

    private init() {
    }

}

3
ทำไม init () ไม่เป็นส่วนตัว
XcodeNOOB

0

การเริ่มต้นใด ๆ จะทำได้ในวิธีการเริ่มต้น ไม่มีความแตกต่างระหว่าง singleton และ non-singleton


26
ข้อมูลโค้ดเพิ่มเติมที่ตอบคำถามโดยตรงจะช่วยให้คำตอบนี้มีประโยชน์มากขึ้น
Reda Lemeden
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.