Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/101.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 创建AVAUDIOPLAYER时理解Swift中的选项_Ios_Swift_Optional - Fatal编程技术网

Ios 创建AVAUDIOPLAYER时理解Swift中的选项

Ios 创建AVAUDIOPLAYER时理解Swift中的选项,ios,swift,optional,Ios,Swift,Optional,我是Swift新手,正在从Obj-C过渡,对其他语言没有太多经验 我已经读过关于期权的书,了解了它的总体前提,并了解了为什么它们可能是一件好事。但我很难理解它们在实践中是如何工作的。下面的代码工作得很好,但我想解释一下为什么会这样 我正在使用AVAudioPlayer制作一个从文件播放音频的应用程序。我首先创建AVAudioPlayer类的一个实例: var player: AVAudioPlayer? 问题1。为什么这必须是可选类型?大概是因为它尚未初始化/尚未包含任何数据 然后我用来将音频

我是Swift新手,正在从Obj-C过渡,对其他语言没有太多经验

我已经读过关于期权的书,了解了它的总体前提,并了解了为什么它们可能是一件好事。但我很难理解它们在实践中是如何工作的。下面的代码工作得很好,但我想解释一下为什么会这样

我正在使用
AVAudioPlayer
制作一个从文件播放音频的应用程序。我首先创建AVAudioPlayer类的一个实例:

var player: AVAudioPlayer?
问题1。为什么这必须是可选类型?大概是因为它尚未初始化/尚未包含任何数据

然后我用来将音频加载到
player
的代码如下:

guard let audioFile = Bundle.main.path(forResource: "sample-audio", ofType: "caf") else {
    print("sample-audio.caf does not exist in the bundle.")
    return
}
let audioURL = URL(fileURLWithPath: audioFile)
do {
    player = try AVAudioPlayer(contentsOf: audioURL)
    player?.delegate = self
    player?.prepareToPlay()
} catch {
    print(error)
}
问题2。如果
player
是可选类型,为什么在使用try/catch语句为其分配URL时这里省略了
符号

第三季度。如果可选项类似于“必须展开的框”,包含值或nothing/nil,那么如何直接调用其上的属性和函数,例如
player?.delegate
player?.prepareToPlay()

对不起,有三个问题,但相互关联


答案将真正帮助我了解Swift的这一基本方面。

Q1:它不必是可选的,但它当时还没有初始化。您有几个选项:
并在需要时初始化它,
并且您必须在尝试使用它之前对其进行初始化,否则您的程序将崩溃,或者在声明时对其进行初始化。你做什么完全取决于上下文。在这种特殊情况下,最好将其设置为可选

问题2:那行不需要
。它会去哪里?编译器知道
player
是可选的,没有任何内容被展开,您只是给可选变量赋值


Q3:允许您调用可选对象上的内容,而无需首先实际展开它们。它只是隐式地为您工作,因此您的代码可以更加简洁。如果对象为nil,则不会发生任何事情,否则将运行调用。请注意,它将可选性向下级联,因此即使属性etc不是可选的,它也将在这样的语句中继承可选性。

do catch
进程始终与可选性相关假设您这样声明了播放器

var player: AVAudioPlayer!
并且do块失败,这可能是VC使用播放器的其他部分,因此一旦被引用,应用程序将因而崩溃,这就是为什么它被声明为

//

这是什么意思?

player?.delegate = self
简单地说,如果player为nil,则语句将不会运行,如果不是,则将设置委托

//

你不会的

player? = //////
因为它没有意义,并且会导致语句无法运行,因为它后面的键是调用player的属性和方法,如果它不是nil,那么这里没有任何东西可以附加或调用

A1:是,因为它尚未初始化/尚未包含任何数据。但在这种情况下,属性将始终在使用之前进行初始化,您可以将其声明为隐式展开可选
AVAudioPlayer并去掉问号。在这种特殊情况下,您甚至可以使用非可选的默认初始值设定项
AVAudioPlayer
,但这不适用于任何类型

var player = AVAudioPlayer()
A2:您可以将非可选值和可选值分配给可选变量。
仅在从变量发送消息时相关

A3:
player?.delegate=self
称为
可选链接
。如果
player
nil
,则忽略该行的其余部分


由于音频文件必须存在,因为应用程序包在运行时是不可变的,所以可以省略所有
guard
s和
catch
s。代码不能崩溃。如果是这样,你就犯了一个设计错误

var player = AVAudioPlayer()

let audioURL = Bundle.main.url(forResource: "sample-audio", withExtension: "caf")!
player = try! AVAudioPlayer(contentsOf: audioURL)
player.prepareToPlay()

不清楚为什么您认为这需要是可选类型。只要它在声明范围结束之前有一个非nil值(
init
,如果这是一个属性),它就不必是可选的。如果在其声明范围之外的某个点没有值,那么您需要一个可选值来保持“it has no value”状态。请记住,您的问题似乎都不是特定于AVAudioPlayer的。关于Q2,不清楚您在这里指的是哪个
。没有为其分配URL的位置(您无法为其分配URL;它是AVPlayer)。对于Q3,您不直接调用属性和函数。您使用的是
?。
,这是您提到的“您必须打开的盒子”步骤。maddy,是的,但我想知道我的问题是否针对此上下文。也许标题应该不那么具体……Q1。好的,这是有道理的。为什么不是玩家试试AVAudioPlayer()那会怎么样?编译器已经知道它是可选值。您没有展开任何内容。因此,一旦在声明中将“player”确定为可选类型,您就不再需要继续使用?指代它时的符号。但“?”用于执行可选链接。。。认为云正在分开…注意
在Swift中有几种不同的用法。还有三元运算符,它与optionals无关,还有
,您可以将它与
一起用作铸造,并且
在必要时尝试跳过错误处理。(后两个也适用于
,但请注意不要过度使用强制展开,因为这会破坏这些Swift功能的用途。)并且您可以声明类型为可选类型,如上面所述的
var player:AVAudioPlayer?
。“您可以忽略所有的防护和捕捉。代码不得崩溃。如果它崩溃了,请执行以下操作。”