Swift UnsafeMutablePointerUnmanagedCFString? allocation and print
I have no experience with CoreMIDI and could not test it, but this is how it should work:
let midiEndPoint = MIDIGetSource(0)
var property : Unmanaged<CFString>?
let err = MIDIObjectGetStringProperty(midiEndPoint, kMIDIPropertyDisplayName, &property)
if err == noErr {
let displayName = property!.takeRetainedValue() as String
println(displayName)
}
As @rintaro correctly noticed, takeRetainedValue()
is the right choice here because it is the callers responsibility to release the string. This is different from the
usual Core Foundation memory management rules, but documented in the
MIDI Services Reference:
NOTE
When passing a Core Foundation object to a MIDI function, the MIDI
function will never consume a reference to the object. The caller
always retains a reference which it is responsible for releasing by
calling the CFRelease function.When receiving a Core Foundation object as a return value from a MIDI
function, the caller always receives a new reference to the object,
and is responsible for releasing it.
See "Unmanaged Objects" in "Working with Cocoa Data Types" for more information.
UPDATE: The above code works only when compiling in 64-bit mode. In 32-bit mode,MIDIObjectRef
and MIDIEndpointRef
are defined as different kind of pointers.
This is no problem in (Objective-)C, but Swift does not allow a direct conversion, an
"unsafe cast" is necessary here:
let numSrcs = MIDIGetNumberOfSources()
println("number of MIDI sources: \(numSrcs)")
for srcIndex in 0 ..< numSrcs {
#if arch(arm64) || arch(x86_64)
let midiEndPoint = MIDIGetSource(srcIndex)
#else
let midiEndPoint = unsafeBitCast(MIDIGetSource(srcIndex), MIDIObjectRef.self)
#endif
var property : Unmanaged<CFString>?
let err = MIDIObjectGetStringProperty(midiEndPoint, kMIDIPropertyDisplayName, &property)
if err == noErr {
let displayName = property!.takeRetainedValue() as String
println("\(srcIndex): \(displayName)")
} else {
println("\(srcIndex): error \(err)")
}
}
What does `UnsafeMutablePointer.initialize()`actually do?
One reason you need initialize()
, and the only one as for now maybe, is
for ARC.
You'd better think with local scope variables, when seeing how ARC works:
func test() {
var refVar: RefType = initValue //<-(1)
//...
refVar = newValue //<-(2)
//...
//<-(3) just before exiting the loacl scope
}
For a usual assignment as (2), Swift generates some code like this:
swift_retain(_newValue)
swift_release(_refVar)
_refVar = _newValue
(Assume _refVar
and _newValue
are unmanaged pseudo vars.)
Retain
means incrementing the reference count by 1, and release
means decrementing the reference count by 1.
But, think what happens when the initial value assignment as at (1).
If the usual assignment code was generated, the code might crash at this line:
swift_release(_refVar)
because newly allocated region for a var may be filled with garbages, so swift_release(_refVar)
cannot be safely executed.
Filling the newly region with zero (null) and release
safely ignoring the null could be one solution, but it's sort of redundant and not effective.
So, Swift generates this sort of code for initial value assignment:
(for already retained values, if you know ownership model, owned by you.)
_refVar = _initValue
(for unretained values, meaning you have no ownership yet.)
swift_retain(_initValue)
_refVar = _initValue
This is initialize
.
No-releasing the garbage data, and assign an initial value, retaining it if needed.
(The above explanation of "usual assignment" is a little bit simplified, Swift omits swift_retain(_newValue)
when not needed.)
When exiting the local scope at (3), Swift just generates this sort of code:
swift_release(_refVar)
So, this is deinitialize
.
Of course, you know retaining and releasing are not needed for primitive types like Int
, so initialize
and deinitialize
may be donothing
for such types.
And when you define a value type which includes some reference type properties, Swift generates initialize
and deinitialize
procedures specialized for the type.
The local scope example works for the regions allocated on the stack, and initialize()
and deinitialize()
of UnsafeMutablePointer
works for the regions allocated in the heap.
And Swift is evolving so swift, that you might find another reason for needing initialize()
and deinitialize()
in the future, you'd better make it a habit to initialize()
and deinitialize()
all allocated UnsafeMutablePointer
s of any Pointee
types.
Swift2: Correct way to initialise UnsafeMutablePointerUnmanagedCFMutableDictionary? parameter to pass to IORegistryEntryCreateCFProperties
A parameter of the type
UnsafeMutablePointer<Unmanaged<CFMutableDictionary>?>
means that you have to pass a variable of the type
Unmanaged<CFMutableDictionary>?
as an inout-argument with &
. On success, you can unwrap the optional
(with optional binding),
convert the unmanaged object to a managed object withtakeRetainedValue()
, and finally (if you want), cast the CFMutableDictionary
to NSDictionary
.
Example:
var props : Unmanaged<CFMutableDictionary>?
if IORegistryEntryCreateCFProperties(entry, &props, kCFAllocatorDefault, 0) == KERN_SUCCESS {
if let props = props {
let dict = props.takeRetainedValue() as NSDictionary
print(dict)
}
}
Convert UnsafeMutablePointerInt16 to UInt8
Casting an Unsafe(Mutable)Pointer<Int16>
to UnsafePointer<Int8>
would simply be:
let buffer: UnsafeMutablePointer<Int16> = ...
let count: Int = ... // # of Int16 values
let result = buffer.withMemoryRebound(to: UInt8.self, capacity: 2 * count) {
outputStream.write($0, maxLength: 2 * count)
}
What is UnsafeMutablePointerUnmanagedCMSampleBuffer? in Swift?
As you can see from the declaration of the last parameter,
sbufCopyOut: UnsafeMutablePointer<Unmanaged<CMSampleBuffer>?>
bufferCopy
must be declared as optional, not as a implicitly
unwrapped optional:
var bufferCopy: Unmanaged<CMSampleBuffer>?
Note that you have to call takeRetainedValue()
on the result,
so the complete solution would be:
var unmanagedBufferCopy: Unmanaged<CMSampleBuffer>?
if CMSampleBufferCreateCopy(kCFAllocatorDefault, sampleBuffer, &unmanagedBufferCopy) == noErr {
let bufferCopy = unmanagedBufferCopy!.takeRetainedValue()
// ...
} else {
// failed
}
Update: In Swift 4 (and probably already in Swift 4),CMSampleBufferCreateCopy()
returns a managed object, therefore
the code simplifies to
var bufferCopy: CMSampleBuffer?
if CMSampleBufferCreateCopy(kCFAllocatorDefault, sampleBuffer, &bufferCopy) == noErr {
// ... use bufferCopy! ...
} else {
// failed
}
Point an UnsafeMutablePointerVoid to itself
On Swift 3:
var somePointer = UnsafeMutableRawPointer(bitPattern: 1)!
somePointer = UnsafeMutableRawPointer(mutating: &somePointer)
print(somePointer)
print(somePointer.load(as: UnsafeMutableRawPointer.self))
// Output of both should be the same.
Swift 2:
Use withUnsafePointer
to obtain the pointer to a variable. Then assign that to itself.
var somePointer: UnsafeMutablePointer<Void> = nil
withUnsafePointer(&somePointer) { somePointer = UnsafeMutablePointer($0) }
Related Topics
Disable Warning Dialog If Bluetooth Is Powered Off iOS
How Is Filters Uiscrollview/Uicollectionview in Apple's Photos App Implemented That It Opens So Fast
iPhone Only App Rejected for Not Running on iPad
Facebook Sdk - iOS - Fail to Share Url (Error 102)
Avplayerviewcontroller Using Audio-Only Avplayer
Nsurlcache Does Not Clear Stored Responses in iOS8
iOS How to Use Uiapplication Launchapplicationwithidentifier Which Is in Private APIs
Insert String at Cursor Position of Uitextfield
How to Use Nsurlsession to Determine If Resource Has Changed
Ios: Production Push Notifications, Invalid Token from Apns Server
Game Center Login Dialog Not Shown Again After Cancelling It for the First Time (Ios7)
How to Load Multiple Storyboard Files Depending on iOS Version? (5 and 6)