NSString Propertylist issue - objective-c

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];

Related

how to convert an array into string? [duplicate]

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.

JSON to NSDictionary - How to check the boolean type

I get JSON from site using this code:
+(NSDictionary *)parseJSONFromURLString:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
NSString *jsonAsString = [NSString stringWithContentsOfURL:url
encoding:NSUTF8StringEncoding
error:nil];
NSData *json = [jsonAsString dataUsingEncoding:NSUTF8StringEncoding];
return [NSJSONSerialization JSONObjectWithData:json options:0 error:nil];
}
When I am calling this method and debugging:
NSDictionary *response = [APIUtils parseJSONFromURLString:[queryBuilder questionsFromTime:time WithPageSize:100 WithPage:1]];
I can look at jsonAsString variable in the parseJSONFromURLString (NSString) method I can see the element "has_more" with value true:
..., "has_more":true, ....
But If I look at responseVariable (NSDictionary) I see next picture:
The value have __NSCFBoolean type and 0X7fff79d377f0 value.
How can I convert this type to BOOL and check it as true or false ?
Using this if statement should detect if the value for that key is true or false.
if([[response objectForKey:#"has_more"] isEqual:[NSNumber numberWithBool:true]]){
//hits here if this value is true
}else{
//and here if it's not.
}
I hope this is what you're looking for.
NSNumber class has the method:
- (BOOL)boolValue
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/Reference/Reference.html#//apple_ref/doc/uid/20000178-boolValue
It's actually a NSNumber, you can get its boolValue.

EXC_BAD_ACCESS memory error under ARC

In the method below I'm receiving "EXC_BAD_ACCESS" on the line containing the "urlString" variable. My research suggests that this error occurs when the program sends a message to a variable that has already been released. However since I'm using ARC I'm not manually releasing memory. How can I prevent ARC from releasing this variable too soon?
-(NSMutableArray *)fetchImages:(NSInteger *)count {
//prepare URL request
NSString *urlString = [NSString stringWithFormat:#"http://foo.example.com/image?quantity=%#", count];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
//Perform request and get JSON as a NSData object
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
//Parse the retrieved JSON to an NSArray
NSError *jsonParsingError = nil;
NSArray *imageFileData = [NSJSONSerialization JSONObjectWithData:response options:0 error:&jsonParsingError];
//Create an Array to store image names
NSMutableArray *imageFileNameArray;
//Iterate through the data
for(int i=0; i<[imageFileData count];i++)
{
[imageFileNameArray addObject:[imageFileData objectAtIndex:i]];
}
return imageFileNameArray;
}
Your problem has nothing to do with ARC. NSInteger isn't a class, so you don't want to be using the %# format. %# is going to send a description method to what the system thinks is an object, but when it turns out not to be one - CRASH. To solve your problem, you have two options:
You might want:
NSString *urlString =
[NSString stringWithFormat:#"http://foo.example.com/image?quantity=%d",
*count];
Make sure the count pointer is valid first!
You might need to change your method signature to be:
-(NSMutableArray *)fetchImages:(NSInteger)count;
and then change the urlString line as follows:
NSString *urlString =
[NSString stringWithFormat:#"http://foo.example.com/image?quantity=%d",
count];
You'll also need to fix all of the callers to match the new signature.
The second option seems more "normal" to me, but without more of your program it's impossible to be more specific.
you also may want to alloc and init the
NSMutableArray *imageFileNameArray;
before adding objects to it, otherwise you'll keep crashing. So you'd have
//Create an Array to store image names
NSMutableArray *imageFileNameArray = [[NSMutableArray alloc] init];

Best way to write arbitrary NSData into an NSXMLElement

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;
}

Unable to write NSArray to file

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];
}