I am using google contact data objective c APIs for fetching contacts. I got contacts array from google server now i want to write contact to file. i am using writeToFile:atomically: method for writing array to file but This method is not working for me since i feel that output array from gdata API not contain property list objects. Please suggest any alternate solution.
-(void)fetchData{
GDataServiceGoogleContact *service=[[GDataServiceGoogleContact alloc] init];
[service setShouldCacheResponseData:YES];
[service setServiceShouldFollowNextLinks:YES];
[service setUserCredentialsWithUsername:[mUsername stringValue] password:[mPassword stringValue]];
// GENERATING THE URL
NSURL *feedURL=[GDataServiceGoogleContact contactFeedURLForUserID:kGDataServiceDefaultUser];
GDataQuery *contQuery=[GDataQueryContact contactQueryWithFeedURL:feedURL];
[contQuery setShouldShowDeleted:YES];
[contQuery setMaxResults:2000];
GDataServiceTicket *ticket=[service fetchFeedWithQuery:contQuery delegate:self didFinishSelector:#selector(hasFetchedContacts:feed:error:)];
}
-(void) hasFetchedContacts:(GDataServiceTicket*) ticket feed:(GDataFeedContact*) contacts error:(NSError*) err
{
NSArray *contactList=[contacts entries];
NSLog(#"%d",[list writeToFile:#"/Users/subhranil/Desktop/contactList" atomically:NO]);
}
Wrap it up to NSData with:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:contactList];
Then save NSData to file with:
[data writeToFile:#"/Users/subhranil/Desktop/contactList" atomically:NO];
You can later restore the data back to NSArray using:
NSData *data = [NSData dataWithContentsOfFile: #"yourFilePath"];
NSArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:data]
Just make sure that objects inside your NSArray conform to NSCoding.
You can use byte array for this purpose and NSData for writing to file.
For saving:
NSData *data=[[NSData alloc] initWithBytes:[contacts entries] length:total];
[data writeToFile:#"path" atomically:YES];
total= The total size of the array in bytes
For retrieving:
NSData *newdata = [NSData dataWithContentsOfFile:#"path"];
NSUInteger len = [newdata length];
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [newdata bytes], len);
byteData will now contain an array of GDataEntryContact objects and you can use them accordingly.
You can encode/decode GDataObject using an xml as generator.
Encode:
[entry setNamespaces:[entry completeNamespaces]];
NSString *xml = [[entry XMLElement] XMLString];
if (nil != xml)
{
//Store your xml NSString to a file
}
Decode:
NSString *xml = //Read your XML String from file;
NSXMLElement *xmlElement = [[NSXMLElement alloc] initWithXMLString:xml error: &error];
if (!error) {
return [[GDataEntryDocBase alloc] initWithXMLElement:xmlElement parent: nil];
}
Related
In my iPhone aplication I have a list of custom objects. I need to create a json string from them. How I can implement this with SBJSON or iPhone sdk?
NSArray* eventsForUpload = [app.dataService.coreDataHelper fetchInstancesOf:#"Event" where:#"isForUpload" is:[NSNumber numberWithBool:YES]];
SBJsonWriter *writer = [[SBJsonWriter alloc] init];
NSString *actionLinksStr = [writer stringWithObject:eventsForUpload];
and i get empty result.
This process is really simple now, you don't have to use external libraries,
Do it this way, (iOS 5 & above)
NSArray *myArray;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:myArray options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
I love my categories so I do this kind of thing as follows
#implementation NSArray (Extensions)
- (NSString*)json
{
NSString* json = nil;
NSError* error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:&error];
json = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return (error ? nil : json);
}
#end
Although the highest voted answer is valid for an array of dictionaries or other serializable objects, it's not valid for custom objects.
Here is the thing, you'll need to loop through your array and get the dictionary representation of each object and add it to a new array to be serialized.
NSString *offersJSONString = #"";
if(offers)
{
NSMutableArray *offersJSONArray = [NSMutableArray array];
for (Offer *offer in offers)
{
[offersJSONArray addObject:[offer dictionaryRepresentation]];
}
NSData *offersJSONData = [NSJSONSerialization dataWithJSONObject:offersJSONArray options:NSJSONWritingPrettyPrinted error:&error];
offersJSONString = [[NSString alloc] initWithData:offersJSONData encoding:NSUTF8StringEncoding] ;
}
As for the dictionaryRepresentation method in the Offer class:
- (NSDictionary *)dictionaryRepresentation
{
NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
[mutableDict setValue:self.title forKey:#"title"];
return [NSDictionary dictionaryWithDictionary:mutableDict];
}
Try like this Swift 2.3
let consArray = [1,2,3,4,5,6]
var jsonString : String = ""
do
{
if let postData : NSData = try NSJSONSerialization.dataWithJSONObject(consArray, options: NSJSONWritingOptions.PrettyPrinted)
{
jsonString = NSString(data: postData, encoding: NSUTF8StringEncoding)! as String
}
}
catch
{
print(error)
}
Try like this,
- (NSString *)JSONRepresentation {
SBJsonWriter *jsonWriter = [SBJsonWriter new];
NSString *json = [jsonWriter stringWithObject:self];
if (!json)
[jsonWriter release];
return json;
}
then call this like,
NSString *jsonString = [array JSONRepresentation];
Hope it will helps you...
I'm a bit late to this party, but you can serialise an array of custom objects by implementing the -proxyForJson method in your custom objects. (Or in a category on your custom objects.)
For an example.
So, I'm trying to open a .mobileprovisioning profile to read what's inside... this is what I'm doing:
NSString *path = [pathURL path];
NSData *data = [[NSFileManager defaultManager] contentsAtPath:path];
Of course I get the data read but I'm not finding the way of getting of get this data into something useful... an NSDictionary, an NSString or whatever...
I've already tried:
NSString *newStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
Any idea? I'm sure this is an encoding issue, but I can't solve it after reading and googling for some time... I think the provisioning profile is saved as hexadecimal, but I don't know how to read that from objective-c. I have found this but there wasn't an useful answer.
How to convert NData populated with hex values to NSString
Thanks!
The following method should do what you want. As #rbrockerhoff says the mobile provisioning profile is an encoded CMS message. This method uses a decoder to first decode the data using the CMS functions and then creates the plist string/contents from the decoded data. This string can then be converted into a dictionary which is returned from the method. The dictionary will contain all the details from the mobile provisioning profile.
- (NSDictionary *)provisioningProfileAtPath:(NSString *)path {
CMSDecoderRef decoder = NULL;
CFDataRef dataRef = NULL;
NSString *plistString = nil;
NSDictionary *plist = nil;
#try {
CMSDecoderCreate(&decoder);
NSData *fileData = [NSData dataWithContentsOfFile:path];
CMSDecoderUpdateMessage(decoder, fileData.bytes, fileData.length);
CMSDecoderFinalizeMessage(decoder);
CMSDecoderCopyContent(decoder, &dataRef);
plistString = [[NSString alloc] initWithData:(__bridge NSData *)dataRef encoding:NSUTF8StringEncoding];
NSData *plistData = [plistString dataUsingEncoding:NSUTF8StringEncoding];
plist = [NSPropertyListSerialization propertyListWithData:plistData options:NSPropertyListImmutable format:nil error:nil]
}
#catch (NSException *exception) {
NSLog(#"Could not decode file.\n");
}
#finally {
if (decoder) CFRelease(decoder);
if (dataRef) CFRelease(dataRef);
}
return plist;
}
A .mobileprovisioning file is an encoded CMS message.
See https://developer.apple.com/library/mac/documentation/security/Reference/CryptoMessageRef/Reference/reference.html for details and an API for decoding it.
If you just want the encoded property list as text, a quick-and-dirty hack is to get the byte pointer for your NSData, scan for the beginning "<?xml" and up to the closing "</plist>". Then make a NSString from that.
You can simply force to open the mobile provisioning profile in TextEdit where you can see the
interior contents and in which you can trim/Edit the encoded CMS message or whatever you want . Then you can simply decode with NSData encodewithUTF string method.
Hope this helps.
I am allowing for application data (it's a Mac app on 10.7) to be exported as an XML file, and one field I would like to be able to export/import to/from XML is an NSData field. What would be the correct/accepted way of doing this? Should I convert to base64 and write that string to XML?
I would prefer not to roll my own solution, using a category, as the accepted answer to the linked question does (linking to Matt Gallagher's solution).
Update
I just discovered the NSPropertyListSerialization class. I got my hopes up, but it only has static serialization methods which return NSData representations.
I realized (as my updated alluded to) that I could use the NSPropertyListSerialization class, since the NSData returned by -dataWithPropertyList:format:options:error: is just a UTF-8 string. This is what I'm using to serialize:
NSData *data = value;
NSError *error = nil;
NSData *plistData = [NSPropertyListSerialization dataWithPropertyList:data
format:NSPropertyListXMLFormat_v1_0
options:0
error:&error];
if (error) {
NSLog(#"Error serializing data to plist XML: %#", error);
} else {
NSString *plistString = [[NSString alloc] initWithData:plistData encoding:NSUTF8StringEncoding];
NSXMLElement *dataElement = [NSXMLElement elementWithName:field
stringValue:plistString];
}
And deserialize:
NSData *plistData = [element.stringValue dataUsingEncoding:NSUTF8StringEncoding];
NSData *originalData = [NSPropertyListSerialization propertyListWithData:plistData
options:NSPropertyListImmutable
format:NULL
error:&error];
if (error) {
NSLog(#"Error deserializing data from plist XML: %#", error);
} else {
value = originalData;
}
What is the best way to validate whether a NSString is a propertyList or not? If I call NSString's -propertyList method it will throw an exception if it cannot parse the string.
Use +propertyListWithData:options:format:error: on NSPropertyListSerialization to attempt to parse the data, it can pass you back an NSError object with some diagnostics if it can't. For example:
NSString *plist = ...;
NSError *e = nil;
NSPropertyListFormat format;
id obj = [NSPropertyListSerialization
propertyListWithData:[plist dataUsingEncoding:NSUnicodeStringEncoding]
options:NSPropertyListImmutable
format:&format
error:&e];
I want to read some float value one by one from a custom file I defined "player.geo".
player.geo is a file I created using Xcode 4 ("Empty File" from the File > New menu)
I'm currently trying to do it like this:
- (id) initWithGeometryFile:(NSString *) nameOfFile
{
NSFileHandle *geoFile = NULL;
NSString *geoFilePath = [[NSBundle mainBundle] pathForResource:#"player" ofType:#"geo"];
geoFile = [NSFileHandle fileHandleForReadingAtPath:geoFilePath];
if(geoFile == NULL)
{
NSLog(#"Failed to open file.");
}
else
{
NSLog(#"Opening %# successful", nameOfFile);
NSMutableData *fileData = [[NSMutableData alloc] initWithData:[geoFile readDataOfLength:4]];
float firstValue;
[fileData getBytes:&firstValue length:sizeof(float)];
NSLog(#"First value in file %# is %f", nameOfFile, firstValue);
}
return self;
}
I'm not getting the expected value of -64.0, rather I'm getting 0.0.
Is this the right way to go about it?
Do I really have to read the file as a string and then parse float the string contents to get the float value?
NSData objects deal with raw bytes, not strings. If you are typing in a string into a txt file, this will not work. If you are using NSData objects, then you will need to first write the data using the data object methods such as writeToFile:atomically:.
Alternately, you can use the NSString functions stringWithContentsOfFile and componentsSeperatedByString to generate an NSArray containing each string on it's own line, like so:
NSString *tmp;
NSArray *lines;
lines = [[NSString stringWithContentsOfFile:#"testFileReadLines.txt"]
componentsSeparatedByString:#"\n"];
NSEnumerator *nse = [lines objectEnumerator];
while(tmp = [nse nextObject]) {
NSLog(#"%#", tmp);
}