Stop the nextprocess when network connection fails - iphone

I'm taking xml response from service url and I want to display error, when network connection fails. So I display the UIAlertView, but this alertView is getting displayed after the rest of process is completed. I want it to be shown immediately.
In android, if network connection fails, it will display an error alert that "Unfortunately app name has terminated". Is there anything of such for iPhone? If not I want to show alertview and stop the rest of the process.
This is the code I'm working on:
if (responseData!= NULL)
{
response = [[NSString alloc] initWithData:responseData
encoding:NSUTF8StringEncoding ];
NSLog(#"Response Code:%d",[urlResponse statusCode]);
if([urlResponse statusCode ]>=200 && [urlResponse statusCode]<300)
{
NSLog(#"Response:%#",response);
}
}
else
{
NSLog(#"Failed to send request: %#", [error localizedDescription]);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Unfornately stopped.Try Again " message:#"" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
parser =[[NSXMLParser alloc]initWithData:responseData];
[parser setDelegate:self];
[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];
currentHtmlElement=#"1";
[parser parse];
[parser release];
In my code if it fails to send request, then NSLog gets printed and alertView code is executed. At the same time I want to stop the rest of the process i.e initialising a parser and doing the rest of operation.
How can I do it?

Very simple... Move your parse code inside if block.
if (responseData!= NULL)
{
response = [[NSString alloc] initWithData:responseData
encoding:NSUTF8StringEncoding ];
NSLog(#"Response Code:%d",[urlResponse statusCode]);
if([urlResponse statusCode ]>=200 && [urlResponse statusCode]<300)
{
NSLog(#"Response:%#",response);
}
parser =[[NSXMLParser alloc]initWithData:responseData];
[parser setDelegate:self];
[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];
currentHtmlElement=#"1";
[parser parse];
[parser release];
}
else
{
NSLog(#"Failed to send request: %#", [error localizedDescription]);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Unfornately iCloudBiz has stopped.Try Again " message:#"" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
By the way... You mentioned your Android's app behavior as follows
In android if network connection fails it will display an error alert that Unfortunatly app name has terminated.
Please understand that this behavior is an abnormal behavior. This is called a CRASH and you should handle this appropriately. If network is disconnected app should display a message without terminating/crashing :)

You should use Reachability class to check for whether internet connection is available or not
this is sample code to understand how it works
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus internetStatus = [reachability currentReachabilityStatus];
if (internetStatus != NotReachable) {
//my web-dependent code
}
else {
//there-is-no-connection warning
}

Related

NSInvalidArgumentException NSDictionary count

i have write a NSDictionary Category. The Category has a method calls "initWithJSONURL".
Here the code:
- (id)initWithJSONURL:(NSURL *)url
{
self = [super init];
if (self) {
NSError *error;
NSData *data = [NSData dataWithContentsOfURL:url
options:NSUTF8StringEncoding
error:&error];
if (!data) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"connection failed"
message:[error localizedDescription]
delegate:self
cancelButtonTitle:#"cancel"
otherButtonTitles:nil];
[alert show];
} else {
self = [NSJSONSerialization JSONObjectWithData:data
options:0
error:&error];
if (error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"invalid data"
message:[error localizedDescription]
delegate:self
cancelButtonTitle:#"cancel"
otherButtonTitles:nil];
[alert show];
}
}
}
return self;
}
And here the code from my ViewController viewDidLoad
NSURL *url = [NSURL URLWithString:#"http://localhost:8888/json.php"];
NSDictionary *dict = [[NSDictionary alloc] initWithJSONURL:url];
NSLog(#"%#", dict);
If I use an correct URL everything works perfect.
But if the URL not correct, the App crash.
I don't know why, it should not crash, it should show the alert View.
The consoles show:
erminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSDictionary count]: method sent to an uninitialized immutable dictionary object'
I hope anybody can help me and sorry for my bad english.
You want to call [self init] instead of [super init]. A category is not a subclass, so [super init] means [NSObject init]. The designated initializer of NSDictionary is never called and the internal dictionary structures are staying unitiliazed.

rss read iphone/ipad app

I have an error while reading XML files for my iPhone app. I have a new feature on my iPhone app that reads my RSS feed. Everything looks good by but I have this issue:
Error while loading rss. Please check your Internet connection
Here's my code:
- (BOOL) readRSS {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
BOOL success = NO;
NSXMLParser *parser = nil;
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"http://rss.domain.com/%#.xml", self.currentPage]];
parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[parser setDelegate:self];
[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];
success = [parser parse];
[parser release];
[pool drain];
return success;
}
Then I have this code:
- (void) cleartbl:(NSInteger)type {
[[[self rssParser] rssItems] removeAllObjects];
[_tableView reloadData];
if(type == 1) {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"RSS Feed"
message:#"Error while loading rss. Please check your Internet connection."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[alert show];
[alert release];
}
Then i assign:
if([elementName isEqualToString:#"title"]){
self.currentItem.title = self.currentItemValue;
}
What is my issue, am I missing something?
The code provided looks good for me, what I would do first is to check if your RSS is valid. I think you have an RSS issue here. You can use the RSS Validation to make sure everything looks good.
I would recommend to sanitize your RSS, keep it very simple, if you only want to display news or articles use letters and numbers in your text and use SEO friendly URLs.
This will simplify the data you are loading from your app and avoid errors like special characters.
Try with a simple RSS with one entry to start and you will see if your code has errors.

Objective - C Connection Test Warnings

I have the following code:
//View guest list
-(IBAction) guestList:(id) sender{
NSString *connected = [NSString stringWithContentsOfURL:[NSURL URLWithString:#"myURL"]];
//Waits a set peroid of time
wait(20000);
//Guest list is availible
if (connected != NULL){
CHARLIEAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate displayView:6];
}
//No network connection availible
else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No Network Connection!" message:#"Cannot establish internet connection." delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[alert release];
}
}
And I get the following warnings:
//Waits a set peroid of time
wait(20000);
Gives me -
warning: passing argument 1 of 'wait' makes pointer from integer without a cast
NSString *connected = [NSString stringWithContentsOfURL:[NSURL URLWithString:#"http://photostiubhart.comoj.com/testconnection.php"]];
Gives me -
warning: 'stringWithContentsOfURL:' is deprecated (declared at /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSString.h:384)
I've done my testing and the code SEEMS to work fine, even though there are these warnings. Is there a way to remove these warnings at all? Or do they not matter?
I'm using xCode version 3.2.6
Thanks,
Jack
use
NSError* error;
NSString* connected = [NSString stringWithContentsOfURL:TheUrl encoding:NSASCIIStringEncoding error:&error];
You should use the method -
+(id)stringWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)enc error:(NSError **)error
for example -
NSString* text = [NSString stringWithContentsOfURL:TheUrl encoding:NSASCIIStringEncoding error:&error];
Hope it will help you.
Try doing it this way:
-(IBAction)guestList:(id) sender{
NSURL *requestUrl = [NSURL URLWithString:#"http://photostiubhart.comoj.com/testconnection.php"];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:requestUrl];
NSData *loadTest = [NSData dataWithContentsOfURL:requestUrl];
if (loadTest == nil) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No Network Connection!" message:#"Cannot establish internet connection." delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[alert release];
} else {
CHARLIEAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate displayView:6];
}
}

Regarding xml parsing in iphone

I am developing an application in which I am doing XML parsing. I found an error in the [xmlparse parse] method.
Error:
[NSCFString bytes]: unrecognized selector sent to instance 0x3df6310
2010-04-30 00:09:46.302 SPCiphone2[4234:1003] void SendDelegateMessage
(NSInvocation*): delegate (<CFNotificationCenter 0x3d09670 [0x87dca0]>)
failed to return after waiting 10 seconds. main run loop mode:
kCFRunLoopDefaultMode
Code snippet:
responseOfWebResultData = [[NSMutableString alloc]
initWithData:responseData
encoding:NSUTF8StringEncoding];
NSLog(#"result: %#", responseOfWebResultData);
// starting the XML parsing
if (responseOfWebResultData) {
#try {
xmlParser = [[NSXMLParser alloc] initWithData:responseOfWebResultData];
[xmlParser setDelegate:self];
[xmlParser setShouldResolveExternalEntities:YES];
[xmlParser parse];
[responseOfWebResultData release];
}
#catch (NSException *e) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Please"
message:[e reason]
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
You should not be passing in a NSString* into initWithData:. You should do this:
xmlParser = [[NSXMLParser alloc] initWithData:responseData];
The error says that you're sending the message bytes to an instance of NSCFString, which is a NSString*, even though you declared it as a NSMutableString*, because this is a dynamically typed language but the class types are not automatically converted if you try to cast it to something else.

Resolving the wait situation for a detached thread in IPhone?

I am using a private MBProgressHUD
Now I am using the indicator view on my add button in which I am calling my addrecord service .
UIWindow *window = [UIApplication sharedApplication].keyWindow;
HUD = [[MBProgressHUD alloc] initWithWindow:window];
// Add HUD to screen
[window addSubview:HUD];
// Regisete for HUD callbacks so we can remove it from the window at the right time
HUD.delegate = self;
// Show the HUD while the provided method executes in a new thread
[HUD showWhileExecuting:#selector(addingToFavorites) onTarget:self withObject:nil animated:YES];
the adding to favorites method :
NSURL *url = [NSURL URLWithString:urlstring];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0];
[request setHTTPMethod:#"GET"];
//[request setTimeoutInterval:10];
//NSURLResponse *response = nil;
// NSError *error = nil;
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
NSData *data1= [NSURLConnection sendSynchronousRequest:request
returningResponse:nil error:nil];
if(data1 == nil)
{
doneFlag = NO;
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Alert"
message:#"The network is not available.\n Please check the Internet connection."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
else
{
doneFlag = YES;
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Confirmation"
message:#"Added To favorites"
delegate:nil
cancelButtonTitle:#"OKAY"
otherButtonTitles:nil];
[alert show];
alert = nil;
[alert release];
}
[request release];
This is all running fine except the instruments gives leak of the uialertview may be it is conflicting with the mbprogreshud.
So I thought to remove the alert from the calling method and put it in the caller the method like this:
the caller method now :
UIWindow *window = [UIApplication sharedApplication].keyWindow;
HUD = [[MBProgressHUD alloc] initWithWindow:window];
// Add HUD to screen
[window addSubview:HUD];
// Regisete for HUD callbacks so we can remove it from the window at the right time
HUD.delegate = self;
// Show the HUD while the provided method executes in a new thread
[HUD showWhileExecuting:#selector(addingToFavorites) onTarget:self withObject:nil animated:YES];
//it should wait for the above line to be executing ******* then to exexute the be //below condition but how ?
if (doneFlag == NO) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Alert"
message:#"The network is not available.\n Please check the Internet connection."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
} else {
[favoritesButton setTitle:#"Remove" forState:UIControlStateNormal];
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Confirmation"
message:#"Added To favorites"
delegate:nil
cancelButtonTitle:#"OKAY"
otherButtonTitles:nil];
[alert show];
alert = nil;
[alert release];
}
the adding to favorites method :
NSURL *url = [NSURL URLWithString:urlstring];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0];
[request setHTTPMethod:#"GET"];
//[request setTimeoutInterval:10];
//NSURLResponse *response = nil;
// NSError *error = nil;
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
NSData *data1= [NSURLConnection sendSynchronousRequest:request
returningResponse:nil error:nil];
if(data1 == nil)
{
doneFlag = NO;
}
else
{
doneFlag = YES;
}
[request release];
In the launching of the progresshud thread is detaching something like this :
[NSThread detachNewThreadSelector:#selector(launchExecution) toTarget:self withObject:nil]
Now My question is that If I follow the first scenario . How can I assure the the alertview leak will not come
Or If I am following the second scenario How can I assure the if condition will be executed after completing this line executed :
[HUD showWhileExecuting:#selector(addingToFavorites) onTarget:self withObject:nil animated:YES];
Regarding the first scenario, it is in general a bad idea to do UI updates from threads other than the applications main thread. UIKit is NOT thread safe and doing threaded UI updates can cause all sorts of strange things to happen. Now, I'm not sure if this is the cause for the leak but I would avoid showing an UIAlertView in addingToFavorites. Use performSelectorOnMainThread or the second scenario described below.
Regarding the second scenario, move everything below the showWhileExecuting call to the hudWasHidden delegate method. At this point you can be sure that your code was fully executed and the doneFlag was set.
To use performSelectorOnMainThread, define a new method, put your code in it and than call performSelectorOnMainThread.
I.e.,
- (void)showAlert {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Alert" message:#"The network is not available.\n Please check the Internet connection." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
Call with,
[self performSelectorOnMainThread:#selector(showAlert) withObject:nil waitUntilDone:NO];
I would go with the second scenario though.
Other answers notwithstanding, you were creating the UIAlertView leak with this sequence:
[alert show];
alert = nil;
[alert release];
The last two lines should be swapped:
[alert show];
[alert release];
alert = nil;