Appearance
Unmanaged in Swift
Unmanaged
is a struct type that is used to manage the memory of instances that have manual memory management, such as Core Foundation APIs.
In Swift, memory management is typically handled automatically through Automatic Refereces Counting (ARC). However, when dealing with Core Foundation or C APIs, you need to manage memory manually.
Unmanaged
struct type lets you create, pass, and return unmanaged objects without transfering ownership, meaning ARC won't release them automatically.
passRetained & takeRetainedValue
Unmanaged.passRetained(obj) static method creates an unmanaged reference to the object and increases its retain account by one.
Conversely, takeRetainedValue() instance method of an Unmanaged instance returns a managed reference to the object and decreases its retain count by one.
For example:
swift
import Foundation
class MyClass {
var value: Int
init(value: Int) {
self.value = value
}
}
func cFunction(_ obj: UnsafeMutableRawPointer) {
let unmanaged = Unmanaged<MyClass>.fromOpaque(obj)
let myObject = unmanaged.takeRetainedValue()
print("takeRetainedValue:\(CFGetRetainCount(myObject))")
// takeRetainedValue() -> retainAccount - 1
// myObject -> retainAccount + 1
}
func callCFunction() {
let myObject = MyClass(value: 42)
print("create:\(CFGetRetainCount(myObject))")
let ptr = Unmanaged.passRetained(myObject).toOpaque()
print("ptr:\(ptr)")
print("passRetained:\(CFGetRetainCount(myObject))")
cFunction(ptr)
}
callCFunction()
The result is
create:2
ptr:0x000060000161e760
passRetained:3
takeRetainedValue:3
passUnretained & takeUnretainedValue
Unmanaged.passUnretained(obj) static method creates an unmanaged reference to the object and does not change its retain account.
Conversely, takeRetainedValue() instance method of an Unmanaged instance will return a managed reference and does not change its retain count as well.
For example:
swift
import Foundation
class MyClass {
var value: Int
init(value: Int) {
self.value = value
}
}
func cFunction(_ obj: UnsafeMutableRawPointer) {
let unmanaged = Unmanaged<MyClass>.fromOpaque(obj)
let myObject = unmanaged.takeUnretainedValue()
print("takeUnretainedValue:\(CFGetRetainCount(myObject))")
// takeUnretainedValue() -> retainAccount does change
// myObject -> retainAccount + 1
}
func callCFunction() {
let myObject = MyClass(value: 42)
print("create:\(CFGetRetainCount(myObject))")
let ptr = Unmanaged.passUnretained(myObject).toOpaque()
print("ptr:\(ptr)")
print("passUnretained:\(CFGetRetainCount(myObject))")
cFunction(ptr)
}
callCFunction()
The result is
create:2
ptr:0x00006000030bd760
passUnretained:2
takeUnretainedValue:3
toOpaque & fromOpaque
Converting between an unmanaged class reference and an opaque C pointer.
swift
func toOpaque() -> UnsafeMutableRawPointer
static func fromOpaque(_ value: UnsafeRawPointer) -> Unmanaged<Instance>
Example code:
swift
let myObject = MyClass(value: 42)
let unmanaged1 = Unmanaged.passUnretained(myObject)
let ptr = unmanaged1.toOpaque()
print("ptr:\(ptr)")
let unmanaged2 = Unmanaged<MyClass>.fromOpaque(ptr)