views:

437

answers:

2

I'm trying to serve a property list of search results to my iPhone app. The server is a prototype, written in Python.

First I found Python's built-in plistlib, which is awesome. I want to give search-as-you-type a shot, so I need it to be as small as possible, and xml was too big. The binary plist format seems like a good choice. Unfortunately plistlib doesn't do binary files, so step right up PyObjC.

(Segue: I'm very open to any other thoughts on how to accomplish live search. I already pared down the data as much as possible, including only displaying enough results to fill the window with the iPhone keyboard up, which is 5.)

Unfortunately, although I know Python and am getting pretty decent with Cocoa, I still don't get PyObjC.

This is the Cocoa equivalent of what I want to do:

NSArray *plist = [NSArray arrayWithContentsOfFile:read_path];
NSError *err;
NSData *data = [NSPropertyListSerialization dataWithPropertyList:plist
                   format:NSPropertyListBinaryFormat_v1_0
                  options:0 //  docs say this must be 0, go figure
                    error:&err];
[data writeToFile:write_path atomically:YES];

I thought I should be able to do something like this, but dataWithPropertyList isn't in the NSPropertyListSerialization objects dir() listing. I should also probably convert the list to NSArray. I tried the PyObjC docs, but it's so tangential to my real work that I thought I'd try an SO SOS, too.

from Cocoa import NSArray, NSData, NSPropertyListSerialization, NSPropertyListBinaryFormat_v1_0
plist = [dict(key1='val', key2='val2'), dict(key1='val', key2='val2')]
NSPropertyListSerialization.dataWithPropertyList_format_options_error(plist,
    NSPropertyListBinaryFormat_v1_0,
    ?,
    ?)

This is how I'm reading in the plist on the iPhone side.

NSData *data = [NSData dataWithContentsOfURL:url];
NSPropertyListFormat format;
NSString *err;
id it = [NSPropertyListSerialization
         propertyListFromData:data
         mutabilityOption:0
         format:&format
         errorDescription:&err];

Happy to clarify if any of this doesn't make sense.

+4  A: 

I believe the correct function name is

NSPropertyListSerialization.dataWithPropertyList_format_options_error_

because of the ending :.

(BTW, if the object is always an array or dictionary, -writeToFile:atomically: will write the plist (as XML format) already.)

KennyTM
Can -writeToFile:atomically use the binary plist format? And I don't actually want to write it to a disk, I need to print it out for the HTTP response.
zekel
@zekel: XML format (unless the `NSWriteOldStylePropertyLists` environment variable is set).
KennyTM
@KennyTM: it doesn't look like NSWriteOldStylePropertyLists is the same thing as the binary format. It's "Specifies whether text property-list output should be in the default MacOS-X format (XML), or in the more human readable (but less powerful) original OpenStep format."
zekel
@zekel: Yes I know.
KennyTM
+2  A: 

As KennyTM said, you're missing the trailing underscore in the method name. In PyObjC you need to take the Objective-C selector name (dataWithPropertyList:format:options:error:) and replace all of the colons with underscores (don't forget the last colon, too!). That gives you dataWithPropertyList_format_options_error_ (note the trailing underscore). Also, for the error parameter, you can just use None. That makes your code look like this:

bplist = NSPropertyListSerialization.dataWithPropertyList_format_options_error_(
                                     plist,
                                     NSPropertyListBinaryFormat_v1_0, 
                                     0, 
                                     None)

# bplist is an NSData object that you can operate on directly or
# write to a file...
bplist.writeToFile_atomically_(pathToFile, True)

If you test the resulting file, you'll see that it's a Binary PList file, as desired:

Jagaroth:~/Desktop $ file test.plist 
test.plist: Apple binary property list
James Eagan