This web view failed error showing the alert popup even when it is loading the website. I believe I need to delay this method in order for it to work.What will be the best method for doing this?
- (void)webView:(UIWebView *)webViewfail didFailLoadWithError:(NSError *)error
{
if([webViewfail isEqual:webview]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Connection Failed" message:#"Check your Internet connection before refreshing."
delegate:webview
cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
}
Here is how I am loading the website
- (void)viewDidLoad
{
[webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.blabla.com"]]];
}
The problem is most likely an error -999 which generally happens when something from the webpage does not load correctly or a user tries to navigate back while the page is still loading. After some research here's what I found and used to keep the NetworkAlert from poping up every time but still popping up when there is no network.
-(void)webView:(UIWebView *)webBlog didFailLoadWithError:(NSError *)error{
if ([error code] != -999) {
NSLog(#"Could not load the dumb webPage");
//show error alert, etc.
[self showNoNetworkAlert];
}else{
NSLog(#"Could not load the dumb web page...just might blame user!");
}
}
- (void) showNoNetworkAlert{
UIAlertView *baseAlert = [[UIAlertView alloc]
initWithTitle:#"No Network" message:#"A network connection is required. Please verify your network settings and try again."
delegate:nil cancelButtonTitle:nil
otherButtonTitles:#"Dismiss", nil];
[baseAlert show];
}
Hope this helps someone...
Related
I'd would like to handle the case in which in-app purchase products are requested without an internet connection.
When testing this case both in the simulator and a device (by turning off the wi-fi), instead of receiving a call to request:didFailWithError:, I receive a call productsRequest:didReceiveResponse: with an empty products array and then to requestDidFinish:.
Is this the expected behavior? If so, how can I know if the request failed due to a connection issue? If not, what might be wrong?
In case it helps, this is how I request the products:
- (void) requestProducts:(NSSet*)identifiers
{
_productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:identifiers];
_productsRequest.delegate = self;
[_productsRequest start];
}
I'm using iOS 6.
I don't know if its expected behavior because the docs are a little sparse on the subject. But I always do the checks myself so I can provide nice error messages to the user because it seems half the time the StoreKit Errors are very nondescript. Here is a bit of code I used in a recent project.
I have my own storeManager delegate to simplify calls and inheritance but it should be pretty clear whats happening.
#pragma mark - Purchase Methods
- (void)purchaseProduct:(SKProduct *)product
{
// Check Internet
if ([self checkInternetConnectionAndAlertUser:YES]) {
// Check Restrictions
if ([self checkRestrictionsAndAlertUser:YES]) {
// Check Products
if ([_products containsObject:product]) {
// Purchase the product
[[SKPaymentQueue defaultQueue] addPayment:[SKPayment paymentWithProduct:product]];
} else {
[[[UIAlertView alloc] initWithTitle:#"Error" message:#"Sorry, we couldn't find that product." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
[self.delegate purchaseDidFailWithError:[NSError errorWithDomain:#"SDInAppPurchaseManager" code:404 userInfo:#{ NSLocalizedDescriptionKey : #"Product not found." }]];
}
} else {
// Not allowed to make purchase
[self.delegate requestdidFailWithError:[NSError errorWithDomain:#"SDInAppPurchaseManager" code:500 userInfo:#{ NSLocalizedDescriptionKey : #"Not authorized to make purchases." }]];
}
} else {
// No Internet
[self.delegate requestdidFailWithError:[NSError errorWithDomain:#"SDInAppPurchaseManager" code:300 userInfo:#{ NSLocalizedDescriptionKey : #"No internet connection." }]];
}
}
#pragma mark - Checks
- (BOOL)checkInternetConnectionAndAlertUser:(BOOL)alert
{
if ([[SDDataManager dataManager] internetConnection]) {
return YES;
} else {
// Alert the user if necessary.
if (alert) {
[[[UIAlertView alloc] initWithTitle:#"No Connection" message:#"You don't appear to be connected to the internet. Please check your connection and try again." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
return NO;
}
}
- (BOOL)checkRestrictionsAndAlertUser:(BOOL)alert
{
if ([SKPaymentQueue canMakePayments]) {
return YES;
} else {
// Alert the user if necessary.
if (alert) {
[[[UIAlertView alloc] initWithTitle:#"Purchases Disabled" message:#"In App Purchasing is disabled for your device or account. Please check your settings and try again." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
return NO;
}
}
Looking for some help again...
I've currently got 2 sections of my app that need internet connection, 1 is a photo gallery through Flickr and the other a Twitter Feed, I was wondering if this is the correct code for the UIAlertView... I can get it working from a button but thats all!
{
-(void)didTap_roundedRectButton1:(id)sender forEvent:(UIEvent *)event {
UIAlertView *alertView = [[UIAlertView alloc] init];
alertView.title = #"You are not connected to the Internet!";
alertView.message = #"Please check your connection and try again...";
[alertView addButtonWithTitle:#"Ok"];
[alertView show];
[alertView release];
}
i think you need to use this example as i have used it to check is there any network is available and device is connected to any one of the network it is alos available on the apple's developer example site
example link is this
You should try this:
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"You are not connected to the Internet!"
message:#"Please check your connection and try again..."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[alertView show];
[alertView release];
and can you post the code how do you create the UIButton?
I am showing alertViews when Location manager unable to find current location. I did it like this
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
[manager stopUpdatingLocation];
switch([error code])
{
case kCLErrorNetwork: // general, network-related error
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Please check your network connection or that you are not in airplane mode" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
break;
case kCLErrorDenied:{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"User has denied to use current Location " delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
break;
default:
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Unknown network error" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
break;
}
}
My problem is locationManager didFailWithError method get called repeatedly. So my alertviews repeatedly display.
How can I solve this issue?
Apple documentation states:
If the location service is unable to retrieve a location right away,
it reports a kCLErrorLocationUnknown error and keeps trying. In such a
situation, you can simply ignore the error and wait for a new event.
If the user denies your application’s use of the location service,
this method reports a kCLErrorDenied error. Upon receiving such an
error, you should stop the location service.
So you might skip some cases where you stop updating and show the alert, especially the default case.
A good start for error messages that can be triggered by an ongoing background process - like the location manager - is to store the reference to the UIAlertView. When the delegate receives alertView:clickedButtonAtIndex:, reset this reference to nil. Before displaying new errors, check if one is already visible.
Even better, don't display modal error messages from background processes. Just walking around, you'll occasionally lose reception, and it's tedious to have to dismiss an error when that happens. If your app has a configuration or help screen, include a space there for the most recent error message from the Location Manager (or Game Center, or iCloud, or anything else that loses connectivity occasionally.)
When you first try to access a user's ALAssetsLibrary, the OS will present them with a dialog asking for permission. If they do not allow this, a failureBlock will be called and will always be called in the future. Is there a way to force a prompt of this authorization request again?
I notice in the Maps app, that they inform the user to go to the Settings app to turn on location services with a button. However, there is no way that I know of to programmatically open the Settings app. Should I just display directions as to how to turn on the location services?
You can't open up the settings app in an Apple approved manner.
The best you can hope for is to trap the error and then display a UIAlertView or other view with instructions on how to do this. Take a look at the latest v. of the Dropbox app for an idea on how they instruct the user.
When you try to access the Library from your code, you can use the error handler to catch the error and display an alert specifying to the user what to do.
Example
failureBlock:^(NSError *error) {
// error handling
if (error.code == ALAssetsLibraryAccessGloballyDeniedError) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error!"
message:#"Error loading image... \nEnable Location Services in 'Settings -> Location Services'."
delegate:self cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
[alert show];
} else if (error.code == ALAssetsLibraryAccessUserDeniedError) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error!"
message:[NSString stringWithFormat:#"Error loading image... \nEnable Location Services in 'Settings -> Location Services' for %#.", [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleDisplayName"]]
delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error!" message:#"Error loading image..." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
}
I am getting odd behavior from an NSAlert in two different parts of my program. The behavior is:
Alert appears and then spontaneously disappears.
Alert reappears and then remains until dismissed by user i.e. normal behavior.
Alert reappears again.
This behavior only occurs the first time the method that displays the alert is called. After that first time, it behaves normally.
Here is the code for the one of the parts in which the behavior occurs:
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"You are in the right place." message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
[locationAlert release];
Or if you prefer, with a bit more context:
- (IBAction)locateMe {
NSLog(#"About to check location");
locMan = [[CLLocationManager alloc] init];
locMan.delegate = self;
locMan.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
locMan.distanceFilter = 1609; //1 mile
[locMan startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation * )oldLocation {
if (newLocation.horizontalAccuracy >= 0) {
CLLocation *airportLocation = [[[CLLocation alloc] initWithLatitude:51.500148 longitude:-0.204669] autorelease];
CLLocationDistance delta = [airportLocation getDistanceFrom: newLocation];
long miles = (delta * 0.000621371) + 0.5; //metres to rounded mile
if (miles < 3) {
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"You are in the right place." message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
[locationAlert release];
[locMan stopUpdatingLocation];
} else {
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"You are not in the right place." message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
[locationAlert release];
[locMan stopUpdatingLocation];
}
}
}
- (void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"Error." message:error.code delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
[locMan release];
locMan = nil;
}
Any ideas? Thanks.
Edit---------
The other place this happens is:
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
NSString * errorString = [NSString stringWithFormat:#"Unable to download feed from web site (Error code %i )", [parseError code]];
NSLog(#"error parsing XML: %#", errorString);
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:#"Error loading content" message:errorString delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
For context the first case is in the AppDelegate and the second in the view controller for the 1st tab view. The second problem occurs every time the xml is reloaded when there is no internet connection. The first one only occurs the first time the function is called.
Edit-----
If I move the alert it works. Unfortunatly this is not where I want it!
- (IBAction)locateMe {
UIAlertView * locationAlert = [[UIAlertView alloc] initWithTitle:#"You are in the right place." message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[locationAlert show];
/*
NSLog(#"About to check location");
locMan = [[CLLocationManager alloc] init];
locMan.delegate = self;
locMan.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
locMan.distanceFilter = 1609; //1 mile
[locMan startUpdatingLocation];*/
}
Update:
I set some NSLog entries and discovered that despite the addition of [locMan stopUpdatingLocation] the didUpdateToLocation function was running multiple times.
I guess the spontaneous disappearance happens because the alert view is called again and the programme clears the first instance to make way for the second automatically.
Any ideas as to why [locMan stopUpdatingLocation] doesn't work would be appreciated but in the mean time I just moved the declaration of the locationAlert out of the function (so it is global), set it in the initial locate me function and use the following the first time it is called:
[locationAlert show];
locationAlert = nil;
That way it works perfectly.
You're not turning off your location manager when you first show the alert. As the location is refined by the device (ie, the accuracy is increased), your callback will be (potentially) called multiple times. You should use [locMan stopUpdatingLocation] after your alert display.
I set some NSLog entries and discovered that despite the addition of [locMan stopUpdatingLocation] the didUpdateToLocation function was running multiple times.
I guess the spontaneous disappearance happens because the alert view is called again and the programme clears the first instance to make way for the second automatically.
Any ideas as to why [locMan stopUpdatingLocation] doesn't work would be appreciated but in the mean time I just moved the declaration of the locationAlert out of the function (so it is global), set it in the initial locate me function and use the following the first time it is called:
[locationAlert show];
locationAlert = nil;
That way it works perfectly.
I think the NSAlert disappearing on its own is the key to solving this.
It's simple to explain why an alert displays unexpectedly i.e. it's just been called unexpectedly. However, it's not so common to programmatically dismiss an alert. Whatever is causing it to disappear is most likely triggering the display again.
To debug I suggest:
(1) Looking in your code for the NSAlert – dismissWithClickedButtonIndex:animated: method and see if somehow you're actually dismissing the alert programmatically.
(2) I believe (someone double-check me on this) that an alert view is added as a subview to whichever base view is currently on screen. It might be that the base view is disappearing for some reason and taking the alert view with it. If the view disappears and then reappears rapidly enough, it might not be obvious when the alert is frontmost. (Edit: see Ed Marty's comment below.)
(3) Since this happens in two separate pieces of the app, compare both to find a common element or structure. That common element might be the cause.
An odd problem.
Edit01: Updated for additional info
If locMan isan instance variable, it should be defined as a property and you should access it every time withself.locMan By accessing it directly, you lose your automatic retention management.
I encountered the same exact issue with the alert dialog appearing momentarily, reappearing, and finally appearing again after being dismissed. I was making a string comparison before deciding to show the alert view:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if([string isEqualToString:#"OK"]) {
NSLog(#"(Settings)Registration Successful");
statusField.text = #"Registration successful!";
[settingsActivity stopAnimating];
}
else {
NSLog(#"(Settings)Registration Failure");
[settingsActivity stopAnimating];
UIAlertView * regFail = [[[UIAlertView alloc] initWithTitle:#"Registration Error!" message:#"Please check your email address and try again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil] autorelease];
[regFail show];
}}
To correct this behavior I simply verified the returned string rather than just showing the alert:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if([string isEqualToString:#"OK"]) {
NSLog(#"(Settings)Registration Successful");
statusField.text = #"Registration successful!";
[settingsActivity stopAnimating];
}
else if([string isEqualToString:#"Error"]) {
NSLog(#"(Settings)Registration Failure");
[settingsActivity stopAnimating];
UIAlertView * regFail = [[[UIAlertView alloc] initWithTitle:#"Registration Error!" message:#"Please check your email address and try again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil] autorelease];
[regFail show];
}
I also got the Same problem while working on Location Manager. Here i checked with Nslog but it is executing multiple times, finally i fount that i am creating multiple objects and using Sharedinstance for same ViewController that contains Location Manger but i am not releasing the object, so at perticular location how many objects if we create that many times the location detects.So while working on LocationManger check handling objects thoroughly to reduce these type of problems.