With ARC, I can just set all of an object's strong references to nil
to deallocate it.
With an UnsafePointer
or UnsafeMutablePointer
, I need to manage its memory explicitly:
let buffer = sizeof(Int8) * 4
var ptr = UnsafeMutablePointer<Void>.alloc(buffer)
defer {
ptr.destroy()
ptr.dealloc(someVal)
ptr = nil
}
But the documentation is ambiguous for AutoreleasingUnsafeMutablePointer
objects. I cannot explicitly call destroy
or dealloc
on a AutoreleasingUnsafeMutablePointer
.
var ptr: AutoreleasingUnsafeMutablePointer<Void> = nil
defer {
ptr = nil
}
// assign something to ptr
The name implies that it is autoreleased after it falls out of scope, but do I need to set a AutoreleasingUnsafeMutablePointer
to nil
in order for it to be autoreleased?
Here's an example where I use an AutoreleasingUnsafeMutablePointer
to get a list of all of the classes currently loaded by the runtime. Note that when invoking the power of the Objective-C runtime some functions require a AutoreleasingUnsafeMutablePointer
rather than just a UnsafeMutablePointer
:
var numClasses: Int32 = 0
var allClasses: AutoreleasingUnsafeMutablePointer<AnyClass?> = nil
defer {
allClasses = nil // is this required?
}
numClasses = objc_getClassList(nil, 0)
if numClasses > 0 {
var ptr = UnsafeMutablePointer<AnyClass>.alloc(Int(numClasses))
defer {
ptr.destroy()
ptr.dealloc(Int(numClasses))
ptr = nil
}
allClasses = AutoreleasingUnsafeMutablePointer<AnyClass?>.init(ptr)
numClasses = objc_getClassList(allClasses, numClasses)
for i in 0 ..< numClasses {
if let currentClass: AnyClass = allClasses[Int(i)] {
print("\(currentClass)")
}
}
}
You don't need to set it to
nil
. It is supposed to be constructed from an autoreleased pointer (assuming it was constructed correctly, it will release itself). At the same time, don't hold onto it past the current stack frame. TheAutoreleasingUnsafeMutablePointer
does not keep the object alive. When the enclosing autorelease pool is popped, the wrapped object will be released and probably deallocated. Like the name says: it is unsafe.Avoid problems by never creating
AutoreleasingUnsafeMutablePointer
yourself in Swift (edit: except when it's really an UnsafeMutablePointer and the C header import has made a mistake, see below). If you're using it correctly, it should be transparent glue between Swift'sinout
and an Objective-C return-by-pointer parameter.You generally create a
var
matching the contained type and pass it in byinout
.e.g. if you want to call the function:
then you invoke it like this:
and everything will work out.
I'm not aware of any other situation where you should hold an
AutoreleasingUnsafeMutablePointer
. I don't think you should be manually constructing one at all on the Swift side except asnil
. It is precariously difficult in Swift to construct anAutoreleasingUnsafeMutablePointer
with non-nil
contents since the only way to autorelease is usingUnmanaged
.Responding to your update...
The
objc_getClassList
function signature is a glitch in Swift's automatic C importing. It incorrectly assumes that aClass *
parameter should be imported asAutoreleasingUnsafeMutablePointer<AnyObject?>
. You really just need anUnsafeMutablePointer
which you can get from an array: