简体   繁体   English

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

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

Considering these facts: 考虑以下事实:

1) It is better to initialize objects as let (immutable) rather than var whenever possible. 1)尽可能将对象初始化为let(不可变)而不是var更好。

2) Some objects can throw when you call their initializer (such as AVAudioPlayer, for example ). 2)当你调用他们的初始化(如AVAudioPlayer, 例如某些对象可以抛出)。

3) Some objects have initializers that require arguments that are not available before "self is available," once again such as AVAudioPlayer, so if they are to be a class-level/non-local let, then they must be initialized not before or after, but only inside init(). 3)某些对象的初始化程序要求参数在“自身可用”之前不可用,例如AVAudioPlayer,因此,如果它们将成为类级别/非本地let,则必须在或之前不对其进行初始化。之后,但仅在init()内部。

So, for example, let's say we have a class where we want to define a class-level property of type AVAudioPlayer (or any other object whose init method throws), but we want it to be a let. 因此,举例来说,假设有一个类,我们想定义一个AVAudioPlayer类型的类级属性(或其他任何引发init方法的对象),但我们希望它成为一个let。

After much trial and error, negotiating my way around X-Code warnings, and experimenting with optionals, the best I have come up with (with help) is this: 经过大量的试验和错误,围绕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()
    }

}

So, now basically we have an immutable value which may be nil if AVAudioPlayer.init() throws... but at least it is a let, and since it is set as an optional, the app won't crash if AVAudioPlayer.init() throws. 因此,现在基本上我们有了一个不可变的值,如果AVAudioPlayer.init()抛出该值可能为零...但是至少它是一个让,并且由于将其设置为可选值,因此如果AVAudioPlayer.init不会使应用程序崩溃()抛出。

Is there a better way of doing this? 有更好的方法吗?

What is the best practice for initializing these types of objects (as a class level let)? 初始化这些类型的对象的最佳实践是什么(以类级别为准)?

Thanks so much for your time and consideration! 非常感谢您的时间和考虑! XD XD

Basically you have three options: 基本上,您有三个选择:

  1. forced try ( try! ), if you're 100% sure the AVAudioPlayer will succeed. 如果您100%确信AVAudioPlayer将成功,请尝试( try! )。 Note, however that even if the url has valid contents, the initializer might still fail due to some other internal conditions 但是请注意,即使该网址包含有效内容,初始化器仍可能由于其他一些内部条件而失败
  2. mark the properties as optionals (like you did), this will guard you against failures but will increase the complexity of the rest of your code as you'll need to always unwrap the properties. 将属性标记为可选属性(就像您所做的那样),这将防止出现故障,但会增加其余代码的复杂性,因为您需要始终解开属性。
  3. mark your initializer as throwing. 将您的初始化程序标记为throwing。 This will move upstream the burden of dealing with errors, but still at some point you're likely need to use the #1/#2 approaches . 这将把处理错误的负担移到上游,但是在某些时候,您可能仍需要使用#1 /#2方法。

All above solutions involve a compromise somewhere, as you'll need to handle initialization failures, sooner or later. 上述所有解决方案都会在某处做出折衷,因为您迟早需要处理初始化失败。 The question is how do you want to do this: 问题是您要如何执行此操作:

  • crash the app since AVAudioPlayer failure is not recoverable in your app 由于AVAudioPlayer故障无法在您的应用中恢复,导致应用崩溃
  • handle the initialization failure and provide another path through the app 处理初始化失败并通过应用程序提供另一条路径
  • silently ignore the failures and keep on going with the app 静默地忽略故障并继续使用该应用程序

And this all depends on the specifics of your app. 而这一切都取决于您的应用程序的细节。

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

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