繁体   English   中英

如何正确初始化init()引发的非局部不可变?

[英]How to Properly Initialize Non-Local Immutable Whose init() Throws?

考虑以下事实:

1)尽可能将对象初始化为let(不可变)而不是var更好。

2)当你调用他们的初始化(如AVAudioPlayer, 例如某些对象可以抛出)。

3)某些对象的初始化程序要求参数在“自身可用”之前不可用,例如AVAudioPlayer,因此,如果它们将成为类级别/非本地let,则必须在或之前不对其进行初始化。之后,但仅在init()内部。

因此,举例来说,假设有一个类,我们想定义一个AVAudioPlayer类型的类级属性(或其他任何引发init方法的对象),但我们希望它成为一个let。

经过大量的试验和错误,围绕X代码警告进行协商,并尝试了可选方法,我所能提供的最好的帮助是:

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

}

因此,现在基本上我们有了一个不可变的值,如果AVAudioPlayer.init()抛出该值可能为零...但是至少它是一个让,并且由于将其设置为可选值,因此如果AVAudioPlayer.init不会使应用程序崩溃()抛出。

有更好的方法吗?

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

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

基本上,您有三个选择:

  1. 如果您100%确信AVAudioPlayer将成功,请尝试( try! )。 但是请注意,即使该网址包含有效内容,初始化器仍可能由于其他一些内部条件而失败
  2. 将属性标记为可选属性(就像您所做的那样),这将防止出现故障,但会增加其余代码的复杂性,因为您需要始终解开属性。
  3. 将您的初始化程序标记为throwing。 这将把处理错误的负担移到上游,但是在某些时候,您可能仍需要使用#1 /#2方法。

上述所有解决方案都会在某处做出折衷,因为您迟早需要处理初始化失败。 问题是您要如何执行此操作:

  • 由于AVAudioPlayer故障无法在您的应用中恢复,导致应用崩溃
  • 处理初始化失败并通过应用程序提供另一条路径
  • 静默地忽略故障并继续使用该应用程序

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM