iOS – Facebook SDK, parsing results - objective-c

In my -request:didLoad: delegate method I'm NSLoging the results but I can't figure out what's the content?
It looks like result is an NSArray but what is inside it? how do I parse the data?
A sample of the log looks like this:
result: (
{
"fql_result_set" = (
{
uid2 = 1234567;
},
{
uid2 = 12345678;
}
);
name = queryID;
},
{
"fql_result_set" = (
{
"birthday_date" = "05/12/1987";
name = "John Doe";
},
{
"birthday_date" = "03/01/1978";
name = "Jane Doe";
}
);
name = queryBirthday;
}
)

The Facebook iOS tutorial, in "Step 6: Using the Graph API", says
Note that the server response will be in JSON string format. The SDK uses an open source JSON library https://github.com/stig/json-framework/ to parse the result. If a parsing error occurs, the SDK will callback request:didFailWithError: in your delegate.
A successful request will callback request:didLoad: in your delegate. The result passed to your delegate can be an NSArray, if there are multiple results, or an NSDictionary if there is only a single result.
In your example, everything printed by NSLog inside "()" is part of an NSArray, while everything inside "{}" (which also have keys incidentally) is part of an NSDictionary and therefore accessible by key (name).
http://developers.facebook.com/docs/mobile/ios/build/

According to https://developers.facebook.com/docs/reference/api/, all 'responses' are JSON-Objects. To parse these, iOS 5 provides a class called NSJSONSerialization (NSJSONSerialization Class Reference)
You normally parse it as follows:
NSDictionary *dictionaryJSON = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&error];

Related

Retrieving values from a multidimensional JSON array

Hi i am trying to get the subject name value out of the following JSON file (dataArray), which I have already run through NSJSONSERIALISATION:
-0: {
id: "55edc05848177ec741daf79e"
firstName: "Brad"
rating: 4.2
lessons: 5
text: "Lessons, they're yours take it"
-subjects: [4]
-0: {
name: "Indonesian"
pricePerHour: "500000"
}
-1: {
name: "Diving"
pricePerHour: "700000"
}
But am not able to access if using the indexPath and dot notation I have used for other elements. I'm understanding it must because I have to access an NSDictionary element within two arrays, however haven't been able to find the correct code to do this (though have looked a lot on here, most examples are for much simpler cases).
Here is the code I have been trying, but as I mentioned I now see that this code doesn't cover the array within array of the JSON. How should I modify this to get the value:
// Load and display subjects
UILabel *subjectLabel = (UILabel *)[cell viewWithTag:103];
NSString * subject1String = [dataArray[indexPath.row] valueForKeyPath: #"subjects.0.name"];
subjectLabel.text = [NSString stringWithFormat:#"%#", subject1String];
I think this is not valid Json. Print response as you are getting from the server end. And for getting name : you need to add loop.

Parsing a config file

I have a config file whose content is something like this:
main = {
delay = 10000;
inputs = (
{
enabled = true;
ip = "127.0.0.1";
port = 10001;
file = "c:\abc.txt";
},
{
enabled = true;
ip = "127.0.0.1";
port = 10002;
file = "c:\myfile.txt";
},
);
}
Now, I want to parse this file, and for example, get the port number of the second input (i.e., 10002 in this example), etc.
Do you know what is the easiest way to do so in objective C?
Thanks!
Make sure it's a valid JSON file and then create a NSJSONSerialization object from the NSData of the file after opening it.
NSJSONSerialization *config = [[NSJSONSerialization JSONObjectWithData:DATAFROMFILE options:NSJSONReadingMutableContainers error:nil];
Then to access the second input port:
config[#"inputs"][1][#"port"]
But the best way to do this would be to create a model from each input so you could access the properties as strongly typed properties instead of by key.
ie. config.port instead of configInput[#"port"]
Looks like your config contents were output by NSLog, which results in invalid JSON hence assuming that your actual config file is a valid JSON object, following code should get you what you need:
//Don't forget to replace "configfile" with your config file name in the project
NSString *configPath = [[NSBundle mainBundle] pathForResource:#"configfile" ofType:nil];
NSData *data = [[NSFileManager defaultManager] contentsAtPath:configPath];
NSDictionary *config = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSArray *ports = [config valueForKeyPath:#"main.inputs.port"];
//ports[0] is 10001
//ports[1] is 10002
Here you can verify if your JSON is valid: http://jsonlint.com. This is how your valid JSON confi should look like:
{
"main": {
"delay": "10000",
"inputs": [
{
"enabled": true,
"ip": "127.0.0.1",
"port": 10001,
"file": "c: \\abc.txt"
},
{
"enabled": true,
"ip": "127.0.0.1",
"port": 10002,
"file": "c: \\myfile.txt"
}
]
}
}
EDIT:
I would personally use a model framework rather than just a json parser to save you from a ton of manual work that comes with built-in NSJSONSerialization class. Here are couple of pretty good ones:
1) GitHub Mantle - https://github.com/MantleFramework/Mantle
I use it where ever I can. It is very well written and thought out framework but has a little bit of learning curve involved, which probably is true to any new piece of software.
2) SBJson - https://github.com/stig/json-framework
You can use SBJson if you just wanna get the job done, it has been pretty popular, especially before Mantle and other frameworks became available.
I hope it helps.
If you are able to change or modify the configuration file format to json or plist, you could simply use built in readers an parsers.
Else, there are third party approaches like libconfig.
Also this question may help.

Passing data on subscribe using WLPush for Worklight iOS notifications

I need to pass data on subscribing to a notification, so, I've taken the example code in Module_07_04_iOSNativePush app and added the following code to the connect method (in ViewController.m):
NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys:
#"userName", #"DoronK",
#"password", #"testPwd", nil];
id pushit = [WLPushOptions new];
[pushit addSubscriptionParameter:#"test" :#"Test1"];
[pushit addSubscriptionParameters:dic];
[[WLPush sharedInstance] subscribe:readyToSubscribeListener.alias: pushit :connectListener];
This does not throw any errors, but, when I run the example PushAdapter code, and adding to the adapter using this:
var usub = 'json:'+JSON.stringify(userSubscription);
...
return { result: "Notification sent to user :: " + userId +
", wait " + waittime + " before sending another. UserSub:" + usub};
The result in the adapter is:
{
"isSuccessful": true,
"result": "Notification sent to user :: worklight, wait 0 before sending another.
UserSub:json:{\"userId\":\"worklight\",\"state\":{}}"
}
I would expect the variables that I passed in via the dictionary under "state", correct? Is there another way in the adapter to get the parameters that were passed in on the [WLPush subscribe] call?
As you can probably tell, I am VERY new to Objective C, so, don't assume the call to the subscribe is done correctly. Also, I'm using Worklight Studio 6 with Fix Pack 1.
The state will not contain the parameters passed during subscribe call. You need to first get the device subscription. The options object of the device subscription will contain the parameters passed during subscribe.
For eg.
var deviceSubscriptions=userSubscription.getDeviceSubscriptions();
var usub = 'json:'+JSON.stringify(deviceSubscriptions[0]);
Please refer to the following infocenter link
http://pic.dhe.ibm.com/infocenter/wrklight/v6r0m0/topic/com.ibm.worklight.help.doc/apiref/r_method_usersubscription_getdev.html

Phonegap Plugins

I need some Help regarding Phonegap plugins:
First , i have a JS File which invoke the native code using the phonegap.exec() containing the result handler function, error handler function , a reference to the native class's name and native function name as well as an array of parameters . My question is : if it is possible to invoke the function (native method) with given specified parameters?
That means : in my phonegap plugin file (.h & .m)
1- can i specify the arguments and their Types (NSInteger, NSString) like java
void myMethod(int a , string b){}
-(void) myMethod:(NSMutableArray )arguments withDict:(NSMutableDictionary)options;
Or is it as specified by Phonegap or Objective C ?
2- And what does it withDict means in this case ??
3- can i addicate this?
4- Why should my Code looks like this ?
-(void)myMethod: (NSMutableArray*)arguments withDict:(NSMutableDictionary*)options {
NSString *callbackID =[arguments pop];
NSString *myParam = #"";
NSArray *arrayArguments = [[arguments objectAtIndex:0] componentsSeparatedByString:#"|"];
NSString *stringArgument = ([arArguments objectAtIndex:0]);
I want to invoke my method like this :
why shall i put my arguments (as a String array element) then take it out , split it to get the right element from the String )?
Many Thanks for helping
Ok here's how you do it… The example I've added in below is a implementation of the Email plugin in Phonegap, with multiple strings. You can always substitute my string code to identify NSNumbers, or any other kind of arguments.
In JS ::
First I create the arguments with their values. . .
var attachmentData = {};
attachmentData.data = userData;
attachmentData.fileName = fileName;
var mailData = {};
mailData.toRecipients = "";
mailData.subject = "Exporting Backup for user data";
mailData.body = "User data for application. Please find the attachment containing the data from the last week.";
nativeMail(attachmentData, mailData);
Now we call a function that packages all this data for a Phonegap Plugin and sends it to the plugin class
function nativeMail(attachmentData, mailData){
e_args = {};
if(mailData.toRecipients)
e_args.toRecipients = mailData.toRecipients;
if(mailData.subject)
e_args.subject = mailData.subject; //"Hello World";
if(mailData.body)
e_args.body = mailData.body;
//call to phonegap plugin for native mail iOS
e_args.attachmentFileName = attachmentData.fileName;
e_args.datatoattach = attachmentData.data;
cordova.exec(null, fail, "EmailComposer", "showEmailComposer", [e_args]);
}
Now the EmailComposer.h file
- (void) showEmailComposer:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
And finally, how to take these arguments from the Mutablle Dictionary/Array and retrieve our string values.
- (void) showEmailComposer:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
{
NSString* toRecipientsString = [options valueForKey:#"toRecipients"];
NSString* ccRecipientsString = [options valueForKey:#"ccRecipients"];
NSString* bccRecipientsString = [options valueForKey:#"bccRecipients"];
NSString* subject = [options valueForKey:#"subject"];
NSString* body = [options valueForKey:#"body"];
NSString* isHTML = [options valueForKey:#"bIsHTML"];
. . . . . .
}
This is the only way to go about it. Its to do with the way that Phonegap itself handles data to be passed from your javascript web app to the native class. It cannot be changed. The MutableDictionary or the MutableArray will handle any kind of data you need it to. There are no limitations. However, the passing of this data can only be done using the format above. Once you have the options and arguments in the .m class, you are free to retrieve them or parse them into the data type you need.

How to parse this

I'm experimenting with googles url shortener goo.gl and at the moment it send the url to goo.gl and returns this:
{
"kind": "urlshortener#url",
"id": "http://goo.gl/kyPI",
"longUrl": "http://dsfsd.com/"
}
I think it's JSON but I'm having trouble with that because of ARC. Is there anyway else I could parse the string with key "id"?
If your app targets iOS 5 you can use NSJSONSeralization class of Apple.
(Let's assume youryour received is called theData)
NSError *error=nil;
id result=[NSJSONSerialization JSONObjectWithData:theData options:
NSJSONReadingMutableContainers error:&error];
//to retrieve the 'kind' value of the object
NSLog("Kind: %#",[result objectForKey:#"kind"]);
It's JSON, you can use a framework like SBJson to parse it. See http://stig.github.com/json-framework/