How can we handle multiple NSURLConnection in iPhone Xcode? - iphone

I am developing one small app in which i have multiple NSURLConnection.I have created that NSURL Connection but i don't know how to handle it.My code is like below.
-(void) loadTrafficAndEvent {
int a=10;
//Get the map view bounds for fetch the travel time markers from web service
MKCoordinateRegion region = mapView.region;
float print = region.center.latitude;
// NSLog(#"region.center=%g",print);
CGPoint firstcorner = CGPointMake(self.mapView.bounds.origin.x , mapView.bounds.origin.y);
CGPoint secondcorner = CGPointMake((self.mapView.bounds.origin.x+mapView.bounds.size.width) , mapView.bounds.origin.y);
CGPoint thirdcorner = CGPointMake(self.mapView.bounds.origin.x , (mapView.bounds.origin.y+ mapView.bounds.size.height));
CGPoint fourthcorner = CGPointMake((self.mapView.bounds.origin.x+mapView.bounds.size.width), (mapView.bounds.origin.y + mapView.bounds.size.height));;
//Then transform those point into lat,lng values
CLLocationCoordinate2D mapfirstcorner,mapsecondcorner,mapthirdcorner,mapfourthcorner,requestsender;
mapfirstcorner = [mapView convertPoint:firstcorner toCoordinateFromView:mapView];
mapsecondcorner = [mapView convertPoint:secondcorner toCoordinateFromView:mapView];
mapthirdcorner = [mapView convertPoint:thirdcorner toCoordinateFromView:mapView];
mapfourthcorner = [mapView convertPoint:fourthcorner toCoordinateFromView:mapView];
NSDateFormatter *dateFormatter;
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MM-dd-yyyy"];
NSString *date = [dateFormatter stringFromDate:[NSDate date]];
[dateFormatter release];
NSString *checksumString = [NSString stringWithFormat:#"TrafficAndEvents%#ForTravelStar", date];
NSString *md5Checksum = [self getMD5CheckSum:checksumString];
NSString *url = [NSString stringWithFormat:#"http://www.travelstar.nl/travelstarwebservice/ProviderServices.asmx/GetTrafficStatusAndEvent?northWestLatitude=%f&northWestLongitude=%f&southEastLatitude=%f&southEastLongitude=%f&zoomLevel=%d&date=%#&checksum=%#", mapfirstcorner.latitude,mapfirstcorner.longitude, self.mapView.region.center.latitude, self.mapView.region.center.longitude, a,date,md5Checksum];
NSString *url1 = [NSString stringWithFormat:#"http://www.travelstar.nl/travelstarwebservice/ProviderServices.asmx/GetTrafficStatusAndEvent?northWestLatitude=%f&northWestLongitude=%f&southEastLatitude=%f&southEastLongitude=%f&zoomLevel=%d&date=%#&checksum=%#", mapsecondcorner.latitude,mapsecondcorner.longitude, self.mapView.region.center.latitude, self.mapView.region.center.longitude, a,date,md5Checksum];
NSString *url2 = [NSString stringWithFormat:#"http://www.travelstar.nl/travelstarwebservice/ProviderServices.asmx/GetTrafficStatusAndEvent?northWestLatitude=%f&northWestLongitude=%f&southEastLatitude=%f&southEastLongitude=%f&zoomLevel=%d&date=%#&checksum=%#", mapthirdcorner.latitude,mapthirdcorner.longitude, self.mapView.region.center.latitude, self.mapView.region.center.longitude, a,date,md5Checksum];
NSString *url3 = [NSString stringWithFormat:#"http://www.travelstar.nl/travelstarwebservice/ProviderServices.asmx/GetTrafficStatusAndEvent?northWestLatitude=%f&northWestLongitude=%f&southEastLatitude=%f&southEastLongitude=%f&zoomLevel=%d&date=%#&checksum=%#", mapfourthcorner.latitude,mapfourthcorner.longitude, self.mapView.region.center.latitude, self.mapView.region.center.longitude, a,date,md5Checksum];
//Release the request if it is already created.
if(request1 ) {
[request release];
request = nil;
}
else if(request1 ) {
[request1 release];
request1 = nil;
}
else if(request2 ) {
[request2 release];
request2 = nil;
}
else if(request3 ) {
[request3 release];
request3 = nil;
}
//Release the connection if it is already created.
if(conn) {
[conn cancel];
[conn release];
conn = nil;
}
else if(conn1) {
[conn1 cancel];
[conn1 release];
conn1 = nil;
}
else if(conn2) {
[conn2 cancel];
[conn2 release];
conn2 = nil;
}
else if(conn3) {
[conn3 cancel];
[conn3 release];
conn3 = nil;
}
//If zoom level is grater then 6 then it will request for fetch the travel time markers from the web servce.
if(a > 6) {
ZOOM_LEVEL = a;
//Create the request for fetch the data from web service.
request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
request1 = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:url1]];
request2 = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:url2]];
request3 = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:url3]];
//NSLog(#"%#",url);
//NSLog(#"Request sent");
//entryDate = [NSDate date];
//[entryDate retain];
//Create the connection with the web service for fetch the data
// DownloadDelegate *dd = [[DownloadDelegate alloc] init];
conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
conn1 = [[NSURLConnection alloc] initWithRequest:request1 delegate:self];
conn2 = [[NSURLConnection alloc] initWithRequest:request2 delegate:self];
conn3 = [[NSURLConnection alloc] initWithRequest:request3 delegate:self];
}
}

Declare conn,conn1,conn2,conn3 in .h file.
Then do the following.
in loadTrafficAndEvent:
conn1 = [[NSURLConnection alloc] initWithRequest:request1 delegate:self];
in connectionDidFinishDownloading: method,
- (void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *)destinationURL{
if(connection==conn){
conn1 = [[NSURLConnection alloc] initWithRequest:request1 delegate:self];
}
else if(connection==conn1){
conn2 = [[NSURLConnection alloc] initWithRequest:request2 delegate:self];
}
else if(connection==conn2){
conn3 = [[NSURLConnection alloc] initWithRequest:request3 delegate:self];
}
}
Do the operations inside each if else condition, and no need to allocate and initialize all NSURLConnection in loadTrafficAndEvent: The download will occur one after other.

you might want to take a look at AFNetworking for an easier and tidier way of doing network requests.

Implement NSURLConnection delegate methods and rest will be handle by itself

Related

iPhone - NSURLConnection asynchronous download using URLs in NSArray

I have seen almost all the posts about NSURL on this site, and I am still stuck. I am using Xcode 4.5.
I am trying to download images and display them in a UIScrollView.
I want to download asynchronously download images using URLs, that get stored in an array populated using JSON. I get the URLs from a JSON grab off of my database. That works quite well and I can see the URL's being placed into the urlArray, but making the URLConnection to get the image, seems to fail.
I can't get any of the images to download, or at least they don't show up in my imageArray.
Here is my code and thank you for any help!! Let me know what else is needed
- (void)viewDidLoad
{
[super viewDidLoad];
//show network activity to user.... very useful
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
//call getJSON. getJSON does not parse, but it connects and gets the data.
[self getJSON];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)getJSON
{
NSURL *url = [NSURL URLWithString:#"http://"My server goes here/json.php"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//just initialize the connection, do not
[[NSURLConnection alloc] initWithRequest:request delegate:self]; //"Ecression result unused" warning here
}
- (void)getNextImage
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
for (int y = 0; y < urlArray.count; y++)
{
NSString *urlString = [urlArray objectAtIndex:y];
NSLog(#"Array String is: %# ", urlString);
NSURL *arrayURL = [NSURL URLWithString:urlString];
NSURLRequest *imageRequest = [NSURLRequest requestWithURL:arrayURL];
NSData *imgData = [[NSURLConnection alloc] initWithRequest:imageRequest delegate:self]; //"Incompatible pointer types initializing ..." warning here
imageData = [UIImage imageWithData:imgData];
[imageArray addObject:imageData];
}
NSLog(#"LEAVING getNextImage");
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
theJsonData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[theJsonData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
urlArray = [[NSMutableArray alloc] init];
//This is where all the JSON Parsing is being done.
//Turn off the data indicator, because the download is complete.
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
jsonArray = [NSJSONSerialization JSONObjectWithData:theJsonData options:nil error:nil]; //"Incompatible pointer types initializing ..." warning here
//get the URL strings out of the jsonArray
for (int x = 0; x < jsonArray.count; x++)
{
NSString *urlString = [[jsonArray objectAtIndex:x] objectForKey:#"image_URL"];
NSLog(#"String is %# ", urlString);
[urlArray addObject:urlString];
}
[self getNextImage];
//display the images..... Not sure why this is in connectionDidFinishLoading.
for (int x = 0; x < imageArray.count; x++)
{
CGRect frame;
frame.origin.x = self.mainScroll.frame.size.width * x;
frame.origin.y = 0;
frame.size = self.mainScroll.frame.size;
UIImageView *nextIV = [[UIImageView alloc] initWithFrame:frame];
[nextIV setImage:imageData];
[self.mainScroll addSubview:nextIV];
//NSLog(#"Pass %d", x);
}
self.mainScroll.contentSize = CGSizeMake(self.mainScroll.frame.size.width * imageArray.count,1.0);
NSLog(#"!!!!!!leaving connection did finnish loading!!!!!");
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
//show error message to user if there is a connection error.
UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:#"Error" message:#"The Download could not complete - please make sure you're connected to the internet." delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[errorView show];
//turn off the network activity indicatior
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
you never download imageData. you assign it the request object . thats why you get the warning too. a NSURLConnection object is not a NSData object: NSData *imgData = [[NSURLConnection alloc] initWithRequest:imageRequest delegate:self]; //"Incompatible pointer types initializing ..." warning here
I would today rewrite it using the startAsyncConnection method. sec
-- there you go, untested and written in text edit but it should get you started (I reused most of your code but cut it down a lot too)
#import "RootViewController.h"
#interface RootViewController ()
#property(assign) IBOutlet UIScrollView *mainScroll;
#end
#implementation RootViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[self getJSONAndImageData];
}
- (void)getJSONAndImageData
{
NSURL *url = [NSURL URLWithString:#"http://My server goes here/json.php"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse*r, NSData*d, NSError*e) {
[self parseJSONAndGetImages:d];
}];
}
- (void)parseJSONAndGetImages:(NSData*)data
{
NSMutableArray *urlArray = [[NSMutableArray alloc] init];
//This is where all the JSON Parsing is being done.
//Turn off the data indicator, because the download is complete.
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSArray *jsonArray = (NSArray*)[NSJSONSerialization JSONObjectWithData:data options:nil error:nil]; //"Incompatible pointer types initializing ..." warning here => likely not an array then
assert([jsonArray isKindOfClass:[NSArray class]]);
//could be made in one liner with KVC
//get the URL strings out of the jsonArray
for (int x = 0; x < jsonArray.count; x++)
{
NSString *urlString = [[jsonArray objectAtIndex:x] objectForKey:#"image_URL"];
NSLog(#"String is %# ", urlString);
[urlArray addObject:urlString];
}
[self loadImageArray:urlArray handler:^(NSArray* imageArray) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
for (int x = 0; x < imageArray.count; x++)
{
CGRect frame;
frame.origin.x = self.mainScroll.frame.size.width * x;
frame.origin.y = 0;
frame.size = self.mainScroll.frame.size;
UIImageView *nextIV = [[UIImageView alloc] initWithFrame:frame];
[nextIV setImage:imageArray[x]];
[self.mainScroll addSubview:nextIV];
//NSLog(#"Pass %d", x);
}
self.mainScroll.contentSize = CGSizeMake(self.mainScroll.frame.size.width * imageArray.count,1.0);
}];
}
//for SIMPLICITY I do synchronous networking here!
- (void)loadImageArray:(NSArray *)urlArray handler:(void(^)())handler {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSMutableArray *imageArray = [NSMutableArray array];
for (int y = 0; y < urlArray.count; y++)
{
NSString *urlString = [urlArray objectAtIndex:y];
NSLog(#"Array String is: %# ", urlString);
NSURL *arrayURL = [NSURL URLWithString:urlString];
NSURLRequest *imageRequest = [NSURLRequest requestWithURL:arrayURL];
NSData *imgData = [NSURLConnection sendSynchronousRequest:imageRequest returningResponse:nil error:nil];
UIImage *image = [UIImage imageWithData:imgData];
[imageArray addObject:image];
}
dispatch_async(dispatch_get_main_queue(),^ {
handler(imageArray);
});
});
}
#end

How to get cookies and use them for other requests like POST ( iOS )?

My previous question was about the problem that I have to login each time for doing web services like posting a link or uploading a picture. Philipe answered that I have to use cookies instead of login process for each request. I found this method for getting cookies:
- (void)getCookies {
NSHTTPURLResponse * response;
NSError * error;
NSMutableURLRequest *request;
request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://MyWebsite.com/login.php"]
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:120];
NSData * data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"%#", [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]);
NSArray * all = [NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:[NSURL URLWithString:#"http://MyWebsite.com/login.php"]];
NSLog(#"%d", all.count);
for (NSHTTPCookie *cookie in all) {
NSLog(#"Name: %# : Value: %#", cookie.name, cookie.value);
NSLog(#"Comment: %# : CommentURL: %#", cookie.comment, cookie.commentURL);
NSLog(#"Domain: %# : ExpiresDate: %#", cookie.domain, cookie.expiresDate);
NSLog(#"isHTTPOnly: %c : isSecure: %c", cookie.isHTTPOnly, cookie.isSecure);
NSLog(#"isSessionOnly: %c : path: %#", cookie.isSessionOnly, cookie.path);
NSLog(#"portList: %# : properties: %#", cookie.portList, cookie.properties);
NSLog(#"version: %u", cookie.version);
}
}
I also found this code to use these cookies, but I'm not sure how to use it:
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookies];
Here is my method for POSTing, I am using RestKit API:
- (IBAction)addLinkPressed:(UIButton *)sender {
[RKClient clientWithBaseURLString:#"http://MyWebsite.com"];
NSDictionary* params = [NSDictionary dictionaryWithObjectsAndKeys:
self.linkField.text, #"url",
self.linkTitleField.text, #"title",
self.linkSummaryField.text, #"summary",
nil];
RKRequest *request = [[RKClient sharedClient] post:#"/send_link.php" params:params delegate:self];
[request setUserData:#"sendLink"];
}
Question: Which property of cookies should I store to use it for login information and where should I put it in my code?
I solved this issue by some inefficient way. Here is my methodology:
First I try to post to the web service and after posting I parse the returning HTML to see if the posting was successful or not. If posting was successful I give an appropriate message to the user that you post successfully but if it was not successful it could have two reasons: First: there were some error during the post execution Second: the user was not logged in. The way that I recognize the differentiation between fist and second error is just parsing the response HTML.
Here is the code that I used for this methodology (this is for the time that the user wants to change the password)
- (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error {
NSRange range = [[error localizedDescription] rangeOfString:#"-1012"];
if (range.length > 0){
//First error occurs here
}
RKLogError(#"Hit error: %#", error);
}
- (IBAction)requestToChangePasswordPressed {
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText = #"Loading";
[RKClient clientWithBaseURLString:#"http://WebServiceDomain.com"];
NSDictionary* params = [NSDictionary dictionaryWithObjectsAndKeys:
self.oldPasswordField.text, #"oldPassword",
self.passwordNew.text, #"newPassword",
self.confirmPasswordField.text, #"confirmPassword",
nil];
RKRequest *request = [[RKClient sharedClient] post:#"/change_password.php" params:params delegate:self];
[request setUserData:#"changePassword"];
[self.view endEditing:YES];
[MBProgressHUD hideHUDForView:self.view animated:YES];
}
- (void)autoLogin {
[RKClient clientWithBaseURLString:#"http://WebServiceDomain.com"];
[RKObjectManager sharedManager].client=[RKClient sharedClient];
RKParams *parameters = [RKParams params];
[parameters setValue:[[NSUserDefaults standardUserDefaults] objectForKey:#"defaultUsername"] forParam:#"username"];
[parameters setValue:[[NSUserDefaults standardUserDefaults] objectForKey:#"defaultPassword"] forParam:#"password"];
[[RKClient sharedClient] setAuthenticationType:RKRequestAuthenticationTypeHTTP];
// because we have two POSTs and we want to use the same method for both of the for didLoadResponse: we set the UserDate like bellow
RKRequest *request = [[RKClient sharedClient] post:#"/login.php" params:parameters delegate:self];
[request setUserData:#"login"];
}
- (void)request:(RKRequest*)request didLoadResponse:(RKResponse*)response
{
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText = #"Loading";
id userData = [request userData];
if ([userData isEqual:#"login"]) {
if ([request isGET]) {
// Handling GET /foo.xml
if ([response isOK]) {
// Success! Let's take a look at the data
NSLog(#"Retrieved XML: %#", [response bodyAsString]);
}
} else if ([request isPOST]) {
// Handling POST /other.json
if ([response isJSON]) {
NSLog(#"Got a JSON response back from our POST!");
}
} else if ([request isDELETE]) {
// Handling DELETE /missing_resource.txt
if ([response isNotFound]) {
NSLog(#"The resource path '%#' was not found.", [request resourcePath]);
}
}
}
else if ([userData isEqual:#"sendLink"]) {
NSData *addLinksHtmlData = response.body;
// 2
TFHpple *addlinksParser = [TFHpple hppleWithHTMLData:addLinksHtmlData];
// 3
NSString *errorLinksXpathQueryString = #"//div[#class='errorBox']/ul/li";
NSArray *errorLinksNodes = [addlinksParser searchWithXPathQuery:errorLinksXpathQueryString];
// 4
NSMutableArray *newErrorLinks = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in errorLinksNodes) {
// 5
AllModels *errorTitle = [[AllModels alloc] init];
[newErrorLinks addObject:errorTitle];
// 6
errorTitle.errorTitle = [[element firstChild] content];
}
// 8
self.linkErrorObjects = newErrorLinks;
NSString *successLinksXpathQueryString = #"//div[#class='successBox']";
NSArray *successLinksNodes = [addlinksParser searchWithXPathQuery:successLinksXpathQueryString];
// 4
NSMutableArray *newSuccessLinks = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in successLinksNodes) {
// 5
AllModels *successTitle = [[AllModels alloc] init];
[newSuccessLinks addObject:successTitle];
// 6
successTitle.successTitle = [[element firstChild] content];
}
// 8
self.linkSuccessObjects = newSuccessLinks;
}
else {
NSLog(#"HTTP status code: %d", response.statusCode);
NSLog(#"HTTP status message: %#", [response localizedStatusCodeString]);
NSLog(#"Header fields: %#", response.allHeaderFields);
NSLog(#"Body: %#", response.bodyAsString);
NSData *HtmlData = response.body;
// 2
TFHpple *addParser = [TFHpple hppleWithHTMLData:HtmlData];
// 3
NSString *errorXpathQueryString = #"//div[#class='errorBox']/ul/li";
NSArray *errorNodes = [addParser searchWithXPathQuery:errorXpathQueryString];
// 4
NSMutableArray *newError = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in errorNodes) {
// 5
AllModels *errorTitle = [[AllModels alloc] init];
[newError addObject:errorTitle];
// 6
errorTitle.errorTitle = [[element firstChild] content];
}
// 8
self.ErrorObjects = newError;
NSString *successXpathQueryString = #"//div[#class='successBox']";
NSArray *successNodes = [addParser searchWithXPathQuery:successXpathQueryString];
// 4
NSMutableArray *newSuccess = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in successNodes) {
// 5
AllModels *successTitle = [[AllModels alloc] init];
[newSuccess addObject:successTitle];
// 6
successTitle.successTitle = [[element firstChild] content];
}
// 8
self.successObjects = newSuccess;
[self errorCheck];
}
[MBProgressHUD hideHUDForView:self.view animated:YES];
[MBProgressHUD hideHUDForView:self.view animated:YES];
}
- (void)errorCheck {
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText = #"Loading";
if(self.errorObjects.count > 0) {
AllModels *errorlink = [self.errorObjects objectAtIndex:0];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"There is a problem" message:errorlink.errorTitle delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil , nil];
[alert show];
}
else {
if(self.linkErrorObjects.count > 0) {
[self autoLogin];
[self requestToChangePasswordPressed];
}
else {
AllModels *successlink = [self.successObjects objectAtIndex:0];
self.successLabel.hidden = NO;
self.successLabel.text = successlink.successTitle;
NSLog(#"Success Title: %#",successlink.successTitle);
[UIView animateWithDuration:3.0
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{ self.successLabel.alpha = 0.0; }
completion:^(BOOL fin) { if (fin) [self.successLabel removeFromSuperview]; }];
[self performSelector:#selector(dismissModalViewController) withObject:nil afterDelay:1.0];
}
}
[MBProgressHUD hideHUDForView:self.view animated:YES];
[MBProgressHUD hideHUDForView:self.view animated:YES];
}

Recalling viewDidLoad after failed connection not working

this is my viewDidLoad function working well :
- (void)viewDidLoad
{
[super viewDidLoad];
//iAds code
adview = [[ADBannerView alloc] initWithFrame:CGRectZero];
adview.frame = CGRectOffset(adview.frame, 0, 0);
adview.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifierPortrait];
adview.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
[self.view addSubview:adview];
adview.delegate = self;
self.adbanerinvesiable = NO;
//php data code
NSError *er;
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://localhost:8888/newjson.php?number=1"]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
if (response.length != 0){
NSString *json_string = [[NSString alloc]initWithData:response encoding:NSUTF8StringEncoding];
listt = [parser objectWithString:json_string error:&er];
}
else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"No Internet conniction" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:#"Refresh", nil];
[alert show];
//for ID contet post
SBJsonParser *parser2 = [[SBJsonParser alloc] init];
NSURLRequest *request2 = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://localhost:8888/newjson.php?number=2"]];
NSData *response2 = [NSURLConnection sendSynchronousRequest:request2 returningResponse:nil error:nil];
NSString *json_string2 = [[NSString alloc]initWithData:response2 encoding:NSUTF8StringEncoding];
IDNum = [parser2 objectWithString:json_string2 error:&er];
}
}
As you can see if the connection failed it will show UIAlertView and two Buttons {ok , Refresh}.
I used this Method in case the refresh button been clicked to call viewDidLoad But not Working and giving me blank white view:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 1){
[self viewDidLoad];
}
}
Any idea please ?
You should put your PHP Data Code in a method in it's own, so when you need to call that specifically you can, because you can't (or should I say shouldn't) call viewDidLoad manually. That should only be called automatically by UIViewController.
Example
- (void)viewDidLoad
{
[super viewDidLoad];
//iAds code
adview = [[ADBannerView alloc] initWithFrame:CGRectZero];
adview.frame = CGRectOffset(adview.frame, 0, 0);
adview.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifierPortrait];
adview.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
[self.view addSubview:adview];
adview.delegate = self;
self.adbanerinvesiable = NO;
}
-(void)viewWillAppear:(BOOL)animated /* or: -(void)viewDidAppear: */
{
[super viewWillAppear:animtaed];
[self refreshPHData];
}
-(void)refreshPHPData
{
//php data code
NSError *er;
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://localhost:8888/newjson.php?number=1"]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
if (response.length != 0){
NSString *json_string = [[NSString alloc]initWithData:response encoding:NSUTF8StringEncoding];
listt = [parser objectWithString:json_string error:&er];
}
else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"No Internet conniction" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:#"Refresh", nil];
[alert show];
//for ID contet post
SBJsonParser *parser2 = [[SBJsonParser alloc] init];
NSURLRequest *request2 = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://localhost:8888/newjson.php?number=2"]];
NSData *response2 = [NSURLConnection sendSynchronousRequest:request2 returningResponse:nil error:nil];
NSString *json_string2 = [[NSString alloc]initWithData:response2 encoding:NSUTF8StringEncoding];
IDNum = [parser2 objectWithString:json_string2 error:&er];
}
}
Also, when you call viewDidLoad from your UIAlertView, you are creating a second (and third and so forth) adview because you aren't removing the previous instance. Depending on how many times the alert is shown and viewDidLoad is called, you are going to see adview stacking on top of itself. So try instead:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 1){
[self refreshPHPData];
}
}

NSOperation and EXC_BAD_ACCESS

I have a few apps which are largely data driven, so most screens are basically composed of:
Open the screen
Download the data via an NSOperation
Display data in a UITableView
Make a selection from the UITableView
Go to new screen, and start over from step 1
I am finding that everything works in normal usage, but if the user goes away from the app for a while and then comes back, I'm getting an EXC_BAD_ACCESS error when the next NSOperation runs. This doesn't seem to matter if the user sends the app into the background or not, and it only seems to occur if there's been at least a few mins since the previous data connection was made.
I realise this must be some form of over-releasing, but I'm pretty good with my memory management and I can't see anything wrong. My data calls generally look like this:
-(void)viewDidLoad {
[super viewDidLoad];
NSOperationQueue* tmpQueue = [[NSOperationQueue alloc] init];
self.queue = tmpQueue;
[tmpQueue release];
}
-(void)loadHistory {
GetHistoryOperation* operation = [[GetHistoryOperation alloc] init];
[operation addObserver:self forKeyPath:#"isFinished" options:0 context:NULL];
[self.queue addOperation:operation];
[operation release];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqual:#"isFinished"] && [object isKindOfClass:[GetHistoryOperation class]]) {
GetHistoryOperation* operation = (GetHistoryOperation*)object;
if(operation.success) {
[self performSelectorOnMainThread:#selector(loadHistorySuceeded:) withObject:operation waitUntilDone:YES];
} else {
[self performSelectorOnMainThread:#selector(loadHistoryFailed:) withObject:operation waitUntilDone:YES];
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
-(void)loadHistorySuceeded:(GetHistoryOperation*)operation {
if([operation.historyItems count] > 0) {
//display data here
} else {
//display no data alert
}
}
-(void)loadHistoryFailed:(GetHistoryOperation*)operation {
//show failure alert
}
And my operations generally looks something like this:
-(void)main {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSError* error = nil;
NSString* postData = [self postData];
NSDictionary *dictionary = [RequestHelper performPostRequest:kGetUserWalkHistoryUrl:postData:&error];
if(dictionary) {
NSNumber* isValid = [dictionary objectForKey:#"IsValid"];
if([isValid boolValue]) {
NSMutableArray* tmpDays = [[NSMutableArray alloc] init];
NSMutableDictionary* tmpWalksDictionary = [[NSMutableDictionary alloc] init];
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyyMMdd"];
NSArray* walksArray = [dictionary objectForKey:#"WalkHistories"];
for(NSDictionary* walkDictionary in walksArray) {
Walk* walk = [[Walk alloc] init];
walk.name = [walkDictionary objectForKey:#"WalkName"];
NSNumber* seconds = [walkDictionary objectForKey:#"TimeTaken"];
walk.seconds = [seconds longLongValue];
NSString* dateStart = [walkDictionary objectForKey:#"DateStart"];
NSString* dateEnd = [walkDictionary objectForKey:#"DateEnd"];
walk.startDate = [JSONHelper convertJSONDate:dateStart];
walk.endDate = [JSONHelper convertJSONDate:dateEnd];
NSString* dayKey = [dateFormatter stringFromDate:walk.startDate];
NSMutableArray* dayWalks = [tmpWalksDictionary objectForKey:dayKey];
if(!dayWalks) {
[tmpDays addObject:dayKey];
NSMutableArray* dayArray = [[NSMutableArray alloc] init];
[tmpWalksDictionary setObject:dayArray forKey:dayKey];
[dayArray release];
dayWalks = [tmpWalksDictionary objectForKey:dayKey];
}
[dayWalks addObject:walk];
[walk release];
}
for(NSString* dayKey in tmpDays) {
NSMutableArray* dayArray = [tmpWalksDictionary objectForKey:dayKey];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"startDate" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray* sortedDayArray = [dayArray sortedArrayUsingDescriptors:sortDescriptors];
[sortDescriptor release];
[tmpWalksDictionary setObject:sortedDayArray forKey:dayKey];
}
NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:NO selector:#selector(localizedCompare:)];
self.days = [tmpDays sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
self.walks = [NSDictionary dictionaryWithDictionary:tmpWalksDictionary];
[tmpDays release];
[tmpWalksDictionary release];
[dateFormatter release];
self.success = YES;
} else {
self.success = NO;
self.errorString = [dictionary objectForKey:#"Error"];
}
if([dictionary objectForKey:#"Key"]) {
self.key = [dictionary objectForKey:#"Key"];
}
} else {
self.errorString = [error localizedDescription];
if(!self.errorString) {
self.errorString = #"Unknown Error";
}
self.success = NO;
}
[pool release];
}
-(NSString*)postData {
NSMutableString* postData = [[[NSMutableString alloc] init] autorelease];
[postData appendFormat:#"%#=%#", #"LoginKey", self.key];
return [NSString stringWithString:postData];
}
----
#implementation RequestHelper
+(NSDictionary*)performPostRequest:(NSString*)urlString:(NSString*)postData:(NSError**)error {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:#"%#/%#", kHostName, urlString]];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];
[urlRequest setHTTPMethod:#"POST"];
if(postData && ![postData isEqualToString:#""]) {
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
[urlRequest setHTTPBody:[postData dataUsingEncoding:NSASCIIStringEncoding]];
[urlRequest setValue:postLength forHTTPHeaderField:#"Content-Length"];
[urlRequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
}
NSURLResponse *response = nil;
error = nil;
NSData *jsonData = [NSURLConnection sendSynchronousRequest:(NSURLRequest *)urlRequest returningResponse:(NSURLResponse **)&response error:(NSError **)&error];
NSString *jsonString = [[NSString alloc] initWithBytes: [jsonData bytes] length:[jsonData length] encoding:NSUTF8StringEncoding];
NSLog(#"JSON: %#",jsonString);
//parse JSON
NSDictionary *dictionary = nil;
if([jsonData length] > 0) {
dictionary = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:error];
}
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
return dictionary;
}
If I have the autorelease pool in place, the crash occurs on [pool release]. If I don't, then the crash just looks to appear in the main.m method, and I don't seem to get any useful information. It's difficult to track down when I have to wait 10 mins in between every test!
If anyone can offer any clues or directions to go, that'd be much appreciated.
It's almost certain you're overreleasing something in your code, seeing that the crash is occurring during a [pool release] (There's a autorelease pool in the main method as well).
You can find it using Xcode - use build and analyze to have the static analyser pinpoint potential problems. Run it and post the results.
try this:
http://cocoadev.com/index.pl?NSZombieEnabled
also, you should avoid:
1) calling UIKit methods from secondary threads
2) making (synchronous) url requests from the main thread.
you must be doing one in any case in RequestHelper's performPostRequest method.
My guess is this section
GetHistoryOperation* operation = (GetHistoryOperation*)object;
if(operation.success) {
[self performSelectorOnMainThread:#selector(loadHistorySuceeded:) withObject:operation waitUntilDone:YES];
} else {
[self performSelectorOnMainThread:#selector(loadHistoryFailed:) withObject:operation waitUntilDone:YES];
}
If the sleep happens at a bad point here, you have an object being passed to another thread. I'd find a way around having to pass the operation as the object.
This is a really old question, so sorry for the dredge, but there is no accepted answer.
I was also getting a EXC_BAD_ACCESS on NSOperationQueue -addOperation for seemingly no reason, and after a few days of hunting down memory leaks, and turning on all the debugger options i could find (malloc guard, zombies) and getting nothing, I found an NSLog warning that said: "[NSoperation subclass] set to IsFinished before being started by the queue."
When I modified my base operation subclass, so that its -cancel function only set (IsRunning = NO) and (IsFinished = YES) IF AND ONLY IF (IsRunning == YES), NSOperationQueue stopped crashing.
So if you're ever calling NSOperationQueue -cancelAllOperations, or you're doing that manually (i.e. for (NSOperation *op in queue.allOperations) ) double check to make sure that you don't set IsFinished on those operations in your subclass implementation.

Bing Maps in iPhone Application

How to integrate Bing Maps into iPhone Application?
I am doing using VirtualEarthKit framework [website appears to host malware].
My code is as below :
I am getting error while getting token.
{
VECommonService *commonService = [[VECommonService alloc] init];
NSString *token;
printf("2\n");
NSError *error=[commonService getToken:&token forUserID:#"abc" password:#"def" ipAddress:#"123"];
NSString *errMsg= [error description];
printf("\n%s\n",[errMsg UTF8String]);
printf("3\n");
VEGeocodeService *geocodeService = [[VEGeocodeService alloc] init];
VEGeocodeRequest *geocodeRequest = [[VEGeocodeRequest alloc] init];
printf("4\n");
geocodeRequest.query = #"Portland State University";
geocodeRequest.token = token;
printf("5\n");
VEServiceResponse *geocodeResponse = [geocodeService geocode:geocodeRequest];
VEGeocodeResult *geocodeResult = [geocodeResponse.results objectAtIndex:0];
//NSLog([geocodeResult.location description]);
//NSLog([geocodeResult.address description]);
VEImageryService *imageryService = [[VEImageryService alloc] init];
VEGetMapURIRequest *mapRequest = [[VEGetMapURIRequest alloc] init];
mapRequest.center = geocodeResult.location;
mapRequest.token = token;
VEGetMapURIResponse *mapResponse = [imageryService getMapURI:mapRequest];
NSURL *url = mapResponse.mapURL;
//printf("\n\n URL==> %s",[url relativeString]);
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[webView loadRequest:requestObj];
[self.view addSubview:webView];
}
is there any way to use bing maps in an iPhone app?