Iam new to iphone development, i want to get data from the web service using JSON parsing here is the code
-(void)loadDataSource
{
NSString *URLPath = [NSString stringWithFormat:#"https://ajax.googleapis.com/ajax/services/feed/find?v=1.0&q=Official%20Google%20Blogs"];
NSURL *URL = [NSURL URLWithString:URLPath];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSInteger responseCode = [(NSHTTPURLResponse *)response statusCode];
if (!error)// && responseCode == 200)
{
id res = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
if (res && [res isKindOfClass:[NSDictionary class]])
{
self.dict=[res objectForKey:#"responseData"];
self.items = [self.dict objectForKey:#"entries"];
[self dataSourceDidLoad];
}
else
{
[self dataSourceDidError];
}
}
else
{
[self dataSourceDidError];
}
}];
}
when i run this code it displays nothing and code for collection view at index is
- (PSCollectionViewCell *)collectionView:(PSCollectionView *)collectionView viewAtIndex:(NSInteger)index
{
NSDictionary *item = [self.items objectAtIndex:index];
PSBroView *v = (PSBroView *)[self.collectionView dequeueReusableView];
if (!v)
{
v = [[PSBroView alloc] initWithFrame:CGRectZero];
}
[v fillViewWithObject:item];
return v;
}
below the code for fillViewWithObject
- (void)fillViewWithObject:(id)object
{
[super fillViewWithObject:object];
self.captionLabel.text = [object objectForKey:#"title"];
}
You apparently didn't check your error, because when I run this I get "bad URL" as the error. I also get a compiler warning, "more % conversions than arguments". That's because of the % in your url string. You shouldn't be using stringWithFormat -- just pass the literal string, and it should work:
NSString *URLPath = #"https://ajax.googleapis.com/ajax/services/feed/find?v=1.0&q=Official%20Google%20Blogs";
I see this error (or just wasted code) a lot. You shouldn't use stringWithFormat unless you are supplying a format string and arguments.
Related
I am downloading cards from server using asynchronous request and I want the moment I finished downloading, I should be navigated to some other screen. I am downloading cards using this set of code.
NSMutableArray *array=[[NSMutableArray alloc]initWithObjects:[dictTemp objectForKey:#"image_1_url"],[dictTemp objectForKey:#"image_2_url"],[dictTemp objectForKey:#"image_3_url"], nil];
for(int i=0;i< [array count];i++)
{
NSURL* url = [NSURL URLWithString:[array objectAtIndex:i]];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
NSString *stringName=[NSString stringWithFormat:#"downloadimage%d",i+1];
UIImage *tempImage=[[UIImage alloc]initWithData:data];
[self saveLocally:tempImage andNAme:stringName];
}
[self performSelectorOnMainThread:#selector(update) withObject:nil waitUntilDone:YES];
}];
But the problem is, I am navigating to some other screen in update method, but it gets called before completion of asynchronous request.
I am downloading three images one by one using for loop as specified in the code, and I want to call update method after downloading all the three cards.
Thanks in advance
You can do the below if don't want want to change:
NSMutableArray *array=[[NSMutableArray alloc]initWithObjects:[dictTemp objectForKey:#"image_1_url"],[dictTemp objectForKey:#"image_2_url"],[dictTemp objectForKey:#"image_3_url"], nil];
NSInteger reqCounts = [array count];
for(int i=0;i< [array count];i++)
{
NSURL* url = [NSURL URLWithString:[array objectAtIndex:i]];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
NSString *stringName=[NSString stringWithFormat:#"downloadimage%d",i+1];
UIImage *tempImage=[[UIImage alloc]initWithData:data];
[self saveLocally:tempImage andNAme:stringName];
reqCounts --;
}
if (reqCounts == 0) {
[self performSelectorOnMainThread:#selector(update) withObject:nil waitUntilDone:YES];
}
}];
Better to check this awesome answer.
Instead of using the NSURLRequest class, the NSSession Object is recommended in iOS7. Try rewriting your code this way.
.......
NSURL* url = [NSURL URLWithString:[array objectAtIndex:i]];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
NSData *data = [[NSData alloc] initWithContentsOfURL:location];
NSArray *array = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
..........
}
dispatch_async(dispatch_get_main_queue(), ^{
//call your update method here
});
Hope it helps.
1.Is it necessary https://www.mysite.com/my_services/user/token
get that token and i set for login call but its get error 'csrf token issue'
before https://www.mysite.com/my_services/user/login
with post paramater username and password
i am question
whether i have to call user/token every time ..for getting token and set the x-csrf-token value in header for post requests.
(void)viewDidLoad
{
[super viewDidLoad];
NSString *notificationName = #"MTPostNotificationTut";
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(useNotificationWithString:)
name:notificationName
object:nil];
}
(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(void)viewWillAppear:(BOOL)animated {
NSString *urlString = #"https://www.mysite.com/my_services/user/token.json";
NSString *urlS = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlS]cachePolicy:NSURLCacheStorageAllowed timeoutInterval:10.0];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSString *string = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"stringFromData = %#",string);
id jsonResponseData = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:nil];
NSLog(#"jsonResponseData = %#",jsonResponseData);
NSDictionary *jsonResponseDict;
if ([jsonResponseData isKindOfClass:[NSDictionary class]]) {
jsonResponseDict = jsonResponseData;
} else {
// Error-handling code
}
jsonResponseData = [jsonResponseDict objectForKey:#"d"];
if (jsonResponseData == nil) {
id jsonExceptioTypeData = [jsonResponseDict objectForKey:#"ExceptionType"];
if (jsonExceptioTypeData != nil) {
NSLog(#"%s ERROR : Server returned an exception", __func__);
NSLog(#"%s ERROR : Server error details = %#", __func__, jsonResponseDict);
}
}
token = [jsonResponseDict objectForKey:#"token"];
NSLog(#"token = %#",token);
if (token !=NULL) {
NSString *notificationName = #"MTPostNotificationTut";
NSString *key = #"token";
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:token forKey:key];
[[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:nil userInfo:dictionary];
}
}
-(void)checkWithServer:(NSString *)urlname jsonString:(NSString *)jsonString {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlname]cachePolicy:NSURLCacheStorageAllowed timeoutInterval:10.0];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:[jsonString dataUsingEncoding:NSUTF8StringEncoding]];
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSString *string = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"stringFromData = %#",string);
id jsonResponseData = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:nil];
NSDictionary *jsonResponseDict;
if ([jsonResponseData isKindOfClass:[NSDictionary class]]) {
jsonResponseDict = jsonResponseData;
} else {
}
jsonResponseData = [jsonResponseDict objectForKey:#"d"];
if (jsonResponseData == nil) {
id jsonExceptioTypeData = [jsonResponseDict objectForKey:#"ExceptionType"];
if (jsonExceptioTypeData != nil) {
NSLog(#"%s ERROR : Server returned an exception", __func__);
NSLog(#"%s ERROR : Server error details = %#", __func__, jsonResponseDict);
}
}
NSLog(#"jsonResponseData = %#",jsonResponseDict);
token = [jsonResponseDict objectForKey:#"token"];
NSLog(#"token = %#",token);
}
-(void)useNotificationWithString:(NSNotification*)notification {
NSString *urlString = #"https://www.mysite.com/my_services/user/login.json";
NSString *urlS = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSDictionary *inputData = [[NSDictionary alloc] initWithObjectsAndKeys:
#"ranjeet.gholave", #"username",
#"ran123", #"password",
nil];
NSError *error = nil;
NSData *jsonInputData = [NSJSONSerialization dataWithJSONObject:inputData options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonInputString = [[NSString alloc] initWithData:jsonInputData encoding:NSUTF8StringEncoding];
[self getTokenFromServer:urlS jsonString:jsonInputString];
}
-(void)getTokenFromServer:(NSString *)urlname jsonString:(NSString *)jsonString {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlname]cachePolicy:NSURLCacheStorageAllowed timeoutInterval:30.0];
[request setHTTPMethod:#"POST"];
// [request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request addValue:token forHTTPHeaderField:#"X-CSRFToken"];
[request setHTTPBody:[jsonString dataUsingEncoding:NSUTF8StringEncoding]];
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSLog(#"responseDataIn Second Method = %#",responseData);
id jsonResponseData = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:nil];
NSLog(#"jsonResponseData = %#",jsonResponseData);
NSDictionary *jsonResponseDict;
if ([jsonResponseData isKindOfClass:[NSDictionary class]]) {
jsonResponseDict = jsonResponseData;
} else {
// Error-handling code
}
jsonResponseData = [jsonResponseDict objectForKey:#"d"];
if (jsonResponseData == nil) {
id jsonExceptioTypeData = [jsonResponseDict objectForKey:#"ExceptionType"];
if (jsonExceptioTypeData != nil) {
NSLog(#"%s ERROR : Server returned an exception", __func__);
NSLog(#"%s ERROR : Server error details = %#", __func__, jsonResponseDict);
}
}
}
if i cookie allowed then csrf token validation issue comes
and when i cookie not allowed then csrf token issue not comes ....how to resolved issue..thanks
Regards,
Ranjeet Gholave
I know this is a bit of an old thread. But you should check out https://github.com/kylebrowning/drupal-ios-sdk as well as AFNetworking. You're really working way harder than you have to.
But to answer your question, once you log in, the CSRF token will be returned in the user object and will be valid for then entire user session. So you can cache it and use it until the user logs out or their session expires.
With Drupal IOS SDK it is as simple as:
[DIOSUser userMakeSureUserIsLoggedInWithUsername:username
andPassword:password
success:^(AFHTTPRequestOperation *op, id response) {
DLog(#"user: %#", response);
[DIOSSession sharedSession].user = response;
//NOTE: fix for services 3.4+ CSRF Token Validation
[[DIOSSession sharedSession] setDefaultHeader:#"X-CSRF-Token" value:response[#"token"]];
[self saveLoginInfoForUserWithUsername:username andPassword:password];
[self processUserInfoWithUser:response];
success(response);
}
failure:^(AFHTTPRequestOperation *op, NSError *err) {
failure(err);
}
];
I want send to the data on the server in batches.
I have to send nsmutablestring data with 25 strings at a time then get response and if the response is success then again send the next batch.
I am using HTTPConnection class.The code that I am using is like:
HttpConnectionClass * ht= [[HttpConnectionClass alloc] init];
ht.delegate=self;
ht.isNetworkIndicator = YES;
NSString *data = #"" ;
int i = 0;
self.dataforserver = [[NSMutableString alloc]init] ;
[self.dataforserver setString:#""];
for (i=0;i<= self.dataArray.count-1; i++) {
data =[NSString stringWithFormat:#"A%d%#",[[self.recordIDArray objectAtIndex:i]intValue], [self.dataArray objectAtIndex:i]];
[self.dataforserver appendString:data];
if ((i+1)%25 == 0 && i!=0 ) {
[ht makeHttpConnection:[NSString stringWithFormat:#"http://www.url.com?action=%d&subscriberid=%d&type=%#",2,56904,#"full"] withData:self.dataforserver];
NSLog(#"in for loop dataforserver is %#",dataforserver);
[dataforserver setString:#""];
}
}
if (dataforserver != #"" ) {
NSLog(#"not in for loop dataforserver is %#",dataforserver);
[ht makeHttpConnection:[NSString stringWithFormat:#"http://www.url.com?action=%d&subscriberid=%d&type=%#",2,56904,#"full"] withData:self.dataforserver];
}
I am getting response in the following method
-(void)getHttpData:(NSObject*)data isError:(BOOL)isErr errorMsg:(NSString*)err{
NSString *response=(NSString*)data;
NSLog(#"response is %#",response);
}
I want to continue the loop only if I get the response "SUCCESS".
Can anyone suggest how to achieve it.
I am very new to iOS programming.Please help
I solved this problem by using ASIHttpRequest class which is available on github.
I am posting the code that I used if anybody gets the same issue
{
NSString *data = #"" ;
int i = 0;
int batchCount =5;
NSString *type = #"full";
self.dataforserver = [[NSMutableString alloc]init] ;
[self.dataforserver setString:#""];
for (i=0;i< self.dataArray.count; i++) {
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"http://www.myurl.com/gprsin?action=%d&//subscriberid=%d&type=%#",2,111,type]];
data =[NSString stringWithFormat:#"A%d%#",[[self.recordIDArray objectAtIndex:i]intValue], [self.dataArray objectAtIndex:i]];
[self.dataforserver appendString:data];
if ((i+1)%batchCount == 0 && i!=0 ) {
NSString *response = #"";
int j = 0;
while (response == #"" && j<3 ) {
//Using while loop is not necessary,I am using this because it was required to try three times till getting response.
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setPostBody:[[NSMutableData alloc] initWithData:[dataforserver dataUsingEncoding:NSUTF8StringEncoding]]];
[request setRequestMethod:#"POST"];
[request startSynchronous];
NSError *error = [request error];
if (!error) {
response = [request responseString];
NSLog(#"response is %#",response);
[dataforserver setString:#""];
}
else
{
// unable to connect show alert
NSLog(#"there is some error coming and the error is:%#",error);
return;
}
if ([response isEqualToString:#"SUCCESS"]) {
for (int k = i-batchCount+1; k<=i; k++) {
[self storeContactInDB:[self.dataArray objectAtIndex:k]:[[self.recordIDArray objectAtIndex:k]intValue]];//if you want to store contacts in database along only after successfully sending it to server
}
type = #"INCREMENT";
}
else if ([response isEqualToString:#"FAIL"])
{
//show alert
return;
}
j++;
}
}
if (dataforserver != #"" && i== self.dataArray.count-(self.dataArray.count%batchCount) )
{
NSString *response = #"";
int j = 0;
while (response == #"" && j<3 ) {
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setPostBody:[[NSMutableData alloc] initWithData:[dataforserver dataUsingEncoding:NSUTF8StringEncoding]]];
[request setRequestMethod:#"POST"];
[request startSynchronous];
NSError *error = [request error];
if (!error) {
response = [request responseString];
NSLog(#"response is %#",response);
}
else
{
// unable to connect show alert
NSLog(#"there is some error coming and the error is:%#",error);
return;
}
if ([response isEqualToString:#"SUCCESS"]) {
for (i = self.dataArray.count-(self.dataArray.count%batchCount); i<self.dataArray.count; i++)
{
[self storeContactInDB:[self.dataArray objectAtIndex:i]:[[self.recordIDArray objectAtIndex:i]intValue]];
}
type = #"INCREMENT";
}
else if ([response isEqualToString:#"FAIL"])
{
//show alert
return;
}
j++;
}
}
}
}
I have written code like this but I can't understand how to find if the data is present or not in the URL. Can anyone help me in solving this problem?
Note: This code terminates when the loop is entering the second condition. That is where it's terminating.
-(void)getdetails
{
NSLog(#"in get details");
NSURL *jsonurl=[NSURL URLWithString:#"http://www.myappdemo.com/checkout/services/getonlineusers.php"];
NSMutableURLRequest *request=[[[NSMutableURLRequest alloc]init ]autorelease];
[request setURL:jsonurl];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
NSError *error;
NSURLResponse *response;
NSData *serverReply = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *replyString = [[NSString alloc] initWithBytes:[serverReply bytes] length:[serverReply length] encoding: NSASCIIStringEncoding];
if([replyString isEqualToString:#"Invalid."]){ // i have not set the php code to output "invalid" so this will not work for now ...
NSLog(#"%#",replyString);
}
else {
NSMutableArray *tempArray =[replyString JSONValue];
int count=0;
self.temparray=tempArray;
for(int i=0;i<[tempArray count];i++)
{
///////Here in this loop when it is entering it is terminating /////////
NSDictionary *dict=[tempArray objectAtIndex:i];
NSLog(#"DICT is %#",dict);
NSString *string=[dict objectForKey:#"profilepic"];
NSURL *finalURL = [NSURL URLWithString:[string stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
NSLog(#"encoding string is %#",finalURL);
NSURL *url=[NSURL URLWithString:string];
NSString *source = [NSString stringWithContentsOfURL:finalURL encoding:NSUTF8StringEncoding error:nil];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:url];
NSLog(#"url is %#",url);
NSData *data=[NSData dataWithContentsOfURL:url];
if(!(data==nil))
{
NSLog(#"data is there");
UIImage *image=[[UIImage alloc]initWithData:data];
[self.array addObject:image];
[image release];
}
else {
/*
NSLog(#"if data is null condition block");
UIImage *image=[[UIImage alloc]init];
[self.array addObject:image];
[image release];
*/
}
count=count+1;
NSLog(#"count is %d",count);
}
}
[replyString release];
}
Where does the app terminate and what is the exception? Have you stepped through to see what the array object looks like during each iteration? Is it failing at NSData initWithContentsOfURL? Why don't you issue that as a separate synchronous request and test to see if you got a response?
Regarding your first (and any subsequent) synchronous request, it would probably be good to add a check to ensure you received a valid response (sorry for the formatting, the code tag isn't playing nicely at the moment)
if (response!=nil) {if([response isKindOfClass:[NSHTTPURLResponse class]]) {
// you have a valid response }}
i am fetching around 1500 image url and want to store these images in the document directory of iphone at one go??
please suggest any approach to do it...
thanks
Method to download all URLs and write into one file:
- (BOOL) downloadFilefromCDN :(NSString*)filename {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://example.com/getlinks.php"]]];
[request setHTTPMethod:#"GET"];
NSError *err = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&err];
if (err != nil) { return FALSE; } // Download error
NSArray *searchPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[searchPath objectAtIndex:0] stringByAppendingString:[NSString stringWithFormat:#"/%#",filename]];
if ([data writeToFile:path atomically:YES] != FALSE) {
return TRUE;
} else {
return FALSE; // Error
}
}
You need to write a script that returns an answer including the 1400 links so you can write it into that file.
Method to download all images given by a NSArray* to document directory.
- (id) downloadFilefromCDN :(NSString*)filename {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://example.com/%#",filename]]];
[request setHTTPMethod:#"GET"];
NSError *err = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&err];
if (err != nil) { return FALSE; }
return data;
}
- (NSArray*) downloadFilesfromCDN :(NSArray*)filenames {
NSMutableArray *mfiles = [[NSMutableArray alloc] init];
BOOL error = FALSE;
for (NSString* filename in filenames) {
NSArray *searchPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[searchPath objectAtIndex:0] stringByAppendingString:[NSString stringWithFormat:#"/%#",filename]];
id file = [self downloadFilefromCDN:filename];
if ([file isKindOfClass:[NSData class]]) {
if ([(NSData*)file writeToFile:path atomically:YES] != FALSE) {
[mfiles addObject:path];
} else {
error = TRUE; // Writing of file failed
}
} else {
error = TRUE; // Download failed
}
}
if (error) {
// Handle error
}
[filenames release];
return [NSArray arrayWithArray:mfiles];
}
Note: You need to read the pure filenames into a NSArray. If you have different origins change
[NSString stringWithFormat:#"http://example.com/%#",filename]
to
[NSString stringWithFormat:#"%#",filename]
and read the full paths (http://example.com/file1.png,http://example.com/file2.png) into a NSArray.
Done. Hope it will help.
Sorry for so much editing :S