代码之家  ›  专栏  ›  技术社区  ›  Nerdy Bunz

如何正确初始化init()抛出的非本地不可变项?

  •  -1
  • Nerdy Bunz  · 技术社区  · 6 年前

    考虑到这些事实:

    1) 只要可能,最好将对象初始化为let(不可变)而不是var。

    2) 某些对象在调用其初始值设定项时会抛出(如AVAudioPlayer、, ).

    3) 有些对象的初始值设定项需要在“self is available”之前不可用的参数,例如AVAudioPlayer,因此如果它们要成为类级/非本地let,则必须在init()内部初始化,而不是在其之前或之后初始化。

    例如,假设我们有一个类,我们想在其中定义类型为AVAudioPlayer(或init方法抛出的任何其他对象)的类级属性,但我们希望它是一个let。

    经过多次尝试和错误,协商解决X代码警告问题,并尝试使用optionals,我(在帮助下)得出的最好结果是:

    import AVFoundation
    
    class MySoundPoolPlayer {
    
        private let dingURL = Bundle.main.url(forResource: "ding", withExtension: "wav")
        private let dongURL = Bundle.main.url(forResource: "dong", withExtension: "wav")
    
        private let dingPlayer: AVAudioPlayer?
        private let dongPlayer: AVAudioPlayer?
    
        init() {
    
            dingPlayer = try? AVAudioPlayer(contentsOf: dingURL!)
            dongPlayer = try? AVAudioPlayer(contentsOf: dongURL!)
    
        }
    
        func playDing() {
            dingPlayer!.play()
        }
    
        func playDong() {
            dongPlayer!.play()
        }
    
        func stopAllSounds() {
            dingPlayer!.stop()
            dongPlayer!.stop()
        }
    
    }
    

    有更好的方法吗?

    初始化这些类型的对象(作为类级别let)的最佳实践是什么?

    非常感谢您的时间和考虑!除息的

    1 回复  |  直到 6 年前
        1
  •  1
  •   Cristik    6 年前

    1. try! ),如果你100%确定 AVAudioPlayer
    2. 将属性标记为optionals(就像您所做的那样),这样可以防止失败,但会增加代码其余部分的复杂性,因为您需要始终打开属性。
    3. 将初始值设定项标记为投掷。这将使处理错误的负担向上游移动,但在某些情况下,您可能需要使用#1/#2方法。

    以上所有解决方案都涉及到某种妥协,因为您迟早需要处理初始化失败。问题是您想如何做到这一点:

    • 崩溃应用程序,因为 无法在应用程序中恢复故障
    • 默默地忽略失败,继续使用应用程序

    这一切都取决于你的应用程序的细节。