我在Objective-C
遇到了一种不熟悉的初始化模式,我正在努力在Swift中复制。
在示例代码中,他们定义了一个C结构,例如this(缩写为原始here):
struct AQPlayerState {
AudioFileID mAudioFile;
}
以下是使用AQPlayerState
的示例:
AQPlayerState aqData; // 1
OSStattus result =
AudioFileOpenURL(
audioFileURL,
fsRdPerm,
0,
&aqData.mAudioFile // 2
);
上面的关键点是,aqData
目前有未初始化的属性,AudioFileOpenURL
代表它正在初始化aqData.mAudioFile
。
我试图在Swift中复制这种行为。这是我到目前为止所尝试的内容:
class Person {
var name: String
init(name: String) {
self.name = name
}
}
class Foo {
var person: Person?
}
我的想法是通过将Foo.person
的引用传递给一个将代表它实例化的函数来复制Objective-C代码。
func initializeWithBob(_ ptr: UnsafeMutablePointer<Person?>) {
ptr.pointee = Person(name: "Bob")
}
initializeWithBob
获取指向Person?
类型地址的指针,并使用Person(name: "Bob")
对象对其进行初始化。
这是我的测试代码:
let foo = Foo()
let ptr = UnsafeMutablePointer<Person?>.allocate(capacity: 1)
ptr.initialize(to: foo.person)
defer {
ptr.deinitialize()
ptr.deallocate(capacity: 1)
}
initializeWithBob(ptr)
print(foo.person) // outputs nil
initializeWithBob
未能&#34;安装&#34;我的Person
实例中的Foo
类型的实例。我认为我的一些假设是错误的。寻求帮助纠正我的假设和对这种情况的理解。
提前致谢!
答案 0 :(得分:1)
您可以通过withUnsafeMutablePointer(to:_:)来实现您的目标:
let foo = Foo()
withUnsafeMutablePointer(to: &foo.person) { (ptr) -> Void in
initializeWithBob(ptr)
}
print(foo.person!.name) // outputs Bob
但是,我不推荐这种方法。恕我直言,将你正在使用的API包装在一个C函数中是更有意义的,你可以从Swift调用“很好”。您当前的方法存在的问题是,Swift开发人员难以阅读此类Swift,而且Audio Toolbox开发人员也很难阅读。
答案 1 :(得分:0)
@kelvinlau这是你想要实现的目标吗?
func initializeWithBob(_ ptr: UnsafeMutablePointer<Foo>) {
ptr.pointee.person = Person(name: "Bob")
}
let foo = Foo()
let ptr = UnsafeMutablePointer<Foo>.allocate(capacity: 1)
ptr.initialize(to: foo)
initializeWithBob(ptr)
print(foo.person?.name ?? "nil")
ptr.deinitialize()
ptr.deallocate(capacity: 1)
print(foo.person?.name ?? "nil")
答案 2 :(得分:0)
Objective-C中的代码模式是 out参数,即返回值的参数,或 in out parameters ,这两个参数都通过一个值并返回一个。 Objective-C不直接支持这些,因此指针用于产生语义。
Swift在函数声明中有关键字inout
指示的 in 参数。在函数内,对inout
参数的赋值有效地为作为参数传递的变量赋值。在函数调用站点,变量必须以&
作为前缀,以表明它本身就是变量,而不是有效传递的值。
保持您的Person
和Foo
与您的职能相同:
func initializeWithBob(_ ptr: inout Person?)
{
ptr = Person(name: "Bob")
}
可以使用它,例如:
var example = Foo()
initializeWithBob(&example.person)
在Swift中使用inout
比尝试使用指针构建相同的语义要好。
HTH
注意:除非您好奇,否则可以跳过此
&#34;有效&#34;曾经使用过几次。通常 out 参数由参数传递方法按结果调用实现,而 in out 使用按值调用 - 结果。使用这些方法之一,返回的值仅分配给函数返回的传递变量。
另一个参数传递方法是按引用调用,它类似于按值调用 除之外的每个和函数内的每个参数赋值都会立即传递给变量。这意味着在函数返回之前,对传递的变量的更改可能是。
Swift by design没有指定其inout
是使用按值调用还是使用call-by引用。因此,而不是在答案中指定确切的语义,并且有效地&#34;使用。