Need Help Converting (Cfpropertylistref *)Nsdictionary to Swift

Need help converting (CFPropertyListRef *)nsdictionary to swift

This is the signature for MIDIObjectGetProperties in Swift:

func MIDIObjectGetProperties(obj: MIDIObjectRef, outProperties: UnsafeMutablePointer<Unmanaged<CFPropertyList>?>, deep: Boolean) -> OSStatus

So you need to pass in an UnsafeMutablePointer to a Unmanaged<CFPropertyList>?:

var midiDevice = MIDIGetDevice(0)
var unmanagedProperties: Unmanaged<CFPropertyList>?

MIDIObjectGetProperties(midiDevice, &unmanagedProperties, 1)

Now you have your properties, but they're in an unmanaged variable -- you can use the takeUnretainedValue() method to get them out, and then cast the resulting CFPropertyList to an NSDictionary:

if let midiProperties: CFPropertyList = unmanagedProperties?.takeUnretainedValue() {
let midiDictionary = midiProperties as NSDictionary
println("Midi properties: \(index) \n \(midiDictionary)");
} else {
println("Couldn't load properties for \(index)")
}

Results:

Midi properties: 0 
{
"apple.midirtp.errors" = <>;
driver = "com.apple.AppleMIDIRTPDriver";
entities = (
);
image = "/Library/Audio/MIDI Drivers/AppleMIDIRTPDriver.plugin/Contents/Resources/RTPDriverIcon.tiff";
manufacturer = "";
model = "";
name = Network;
offline = 0;
scheduleAheadMuSec = 50000;
uniqueID = 442847711;
}

Using a reference to CFPropertyListRef in Swift

If your usage in Objective-C is really right, the function header of your MyFunction needs to be something like this:

extern void MyFunction(CFPropertyListRef *list, CFPropertyListFormat *fmt);

(CFPropertyListRef actually is just a typealias of void * in Objective-C/C. So, the compiler rarely outputs warnings for many possible type mis-uses.)

And Swift 2 imports such function as:

public func MyFunction(list: UnsafeMutablePointer<Unmanaged<CFPropertyList>?>, _ fmt: UnsafeMutablePointer<CFPropertyListFormat>)

So, assuming you have changed the function header as above,
you need to use it as follows:

var fmt: CFPropertyListFormat = .XMLFormat_v1_0
var umPlist: Unmanaged<CFPropertyList>? = nil
MyFunction(&umPlist, &fmt)
var plist = umPlist?.takeRetainedValue() //or this may be `umPlist?.takeUnretainedValue()`

Casting a CFDictionaryRef to NSDictionary?

ARC changed the way bridging works.

NSDictionary *original = [NSDictionary dictionaryWithObject:@"World" forKey:@"Hello"];
CFDictionaryRef dict = (__bridge CFDictionaryRef)original;
NSDictionary *andBack = (__bridge NSDictionary*)dict;
NSLog(@"%@", andBack);

how to do true deep copy for NSArray and NSDictionary with have nested arrays/dictionary?

A couple of years ago, I wrote a few category methods for exactly the same reason, transforming a whole tree of user defaults to mutable. Here they are - use them at your own risk! :-)

//
// SPDeepCopy.h
//
// Created by Sherm Pendley on 3/15/09.
//

#import <Cocoa/Cocoa.h>

// Deep -copy and -mutableCopy methods for NSArray and NSDictionary

@interface NSArray (SPDeepCopy)

- (NSArray*) deepCopy;
- (NSMutableArray*) mutableDeepCopy;

@end

@interface NSDictionary (SPDeepCopy)

- (NSDictionary*) deepCopy;
- (NSMutableDictionary*) mutableDeepCopy;

@end

//
// SPDeepCopy.m
//
// Created by Sherm Pendley on 3/15/09.
//

#import "SPDeepCopy.h"

@implementation NSArray (SPDeepCopy)

- (NSArray*) deepCopy {
unsigned int count = [self count];
id cArray[count];

for (unsigned int i = 0; i < count; ++i) {
id obj = [self objectAtIndex:i];
if ([obj respondsToSelector:@selector(deepCopy)])
cArray[i] = [obj deepCopy];
else
cArray[i] = [obj copy];
}

NSArray *ret = [[NSArray arrayWithObjects:cArray count:count] retain];

// The newly-created array retained these, so now we need to balance the above copies
for (unsigned int i = 0; i < count; ++i)
[cArray[i] release];

return ret;
}
- (NSMutableArray*) mutableDeepCopy {
unsigned int count = [self count];
id cArray[count];

for (unsigned int i = 0; i < count; ++i) {
id obj = [self objectAtIndex:i];

// Try to do a deep mutable copy, if this object supports it
if ([obj respondsToSelector:@selector(mutableDeepCopy)])
cArray[i] = [obj mutableDeepCopy];

// Then try a shallow mutable copy, if the object supports that
else if ([obj respondsToSelector:@selector(mutableCopyWithZone:)])
cArray[i] = [obj mutableCopy];

// Next try to do a deep copy
else if ([obj respondsToSelector:@selector(deepCopy)])
cArray[i] = [obj deepCopy];

// If all else fails, fall back to an ordinary copy
else
cArray[i] = [obj copy];
}

NSMutableArray *ret = [[NSMutableArray arrayWithObjects:cArray count:count] retain];

// The newly-created array retained these, so now we need to balance the above copies
for (unsigned int i = 0; i < count; ++i)
[cArray[i] release];

return ret;
}

@end

@implementation NSDictionary (SPDeepCopy)

- (NSDictionary*) deepCopy {
unsigned int count = [self count];
id cObjects[count];
id cKeys[count];

NSEnumerator *e = [self keyEnumerator];
unsigned int i = 0;
id thisKey;
while ((thisKey = [e nextObject]) != nil) {
id obj = [self objectForKey:thisKey];

if ([obj respondsToSelector:@selector(deepCopy)])
cObjects[i] = [obj deepCopy];
else
cObjects[i] = [obj copy];

if ([thisKey respondsToSelector:@selector(deepCopy)])
cKeys[i] = [thisKey deepCopy];
else
cKeys[i] = [thisKey copy];

++i;
}

NSDictionary *ret = [[NSDictionary dictionaryWithObjects:cObjects forKeys:cKeys count:count] retain];

// The newly-created dictionary retained these, so now we need to balance the above copies
for (unsigned int i = 0; i < count; ++i) {
[cObjects[i] release];
[cKeys[i] release];
}

return ret;
}
- (NSMutableDictionary*) mutableDeepCopy {
unsigned int count = [self count];
id cObjects[count];
id cKeys[count];

NSEnumerator *e = [self keyEnumerator];
unsigned int i = 0;
id thisKey;
while ((thisKey = [e nextObject]) != nil) {
id obj = [self objectForKey:thisKey];

// Try to do a deep mutable copy, if this object supports it
if ([obj respondsToSelector:@selector(mutableDeepCopy)])
cObjects[i] = [obj mutableDeepCopy];

// Then try a shallow mutable copy, if the object supports that
else if ([obj respondsToSelector:@selector(mutableCopyWithZone:)])
cObjects[i] = [obj mutableCopy];

// Next try to do a deep copy
else if ([obj respondsToSelector:@selector(deepCopy)])
cObjects[i] = [obj deepCopy];

// If all else fails, fall back to an ordinary copy
else
cObjects[i] = [obj copy];

// I don't think mutable keys make much sense, so just do an ordinary copy
if ([thisKey respondsToSelector:@selector(deepCopy)])
cKeys[i] = [thisKey deepCopy];
else
cKeys[i] = [thisKey copy];

++i;
}

NSMutableDictionary *ret = [[NSMutableDictionary dictionaryWithObjects:cObjects forKeys:cKeys count:count] retain];

// The newly-created dictionary retained these, so now we need to balance the above copies
for (unsigned int i = 0; i < count; ++i) {
[cObjects[i] release];
[cKeys[i] release];
}

return ret;
}

@end

How to solve it ( EXC_BAD_ADDRESS in Objective-C )?

Some ideas:

Turn on zombies (How to enable NSZombie in Xcode). You'll get more information about the object causing the crash when you do that.

If you can make the error happen at will, set a breakpoint at the top of saveAsync and step through it.

Change the stringWithFormat calls somehow so they don't reference anything that might be deallocated and see if the problem goes away. If it does, you'll know what was causing it.

I find it sometimes helps to override retain and release in objects I'm suspicious of and either print something out or set a breakpoint so I can see who might be over-releasing an object.



Related Topics



Leave a reply



Submit