I am creating a rather simple tab-based app with a few UIWebViews. To pass App Store Approval, I need to implement an error if there is no network connection. I'm a beginner, but I tried this and nothing happened.
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Can't connect. Please check your internet Connection"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
I've tried Reachability, but its complicated, and I'm not sure exactly how to implement it into a UIAlertView. Could this code work with tweaking or is it trash?
I suggest you to use delegate methods of webView and implement it in ViewController.
There are mainly three delegate methods of webView.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
- (void)webViewDidFinishLoad:(UIWebView *)webView
In didFailLoadWithError method you can identify error code using [error code]. You can use any of these as per your requirement.
// Error codes for CFURLConnection and CFURLProtocol
kCFURLErrorUnknown = -998,
kCFURLErrorCancelled = -999,
kCFURLErrorBadURL = -1000,
kCFURLErrorTimedOut = -1001,
kCFURLErrorUnsupportedURL = -1002,
kCFURLErrorCannotFindHost = -1003,
kCFURLErrorCannotConnectToHost = -1004,
kCFURLErrorNetworkConnectionLost = -1005,
kCFURLErrorDNSLookupFailed = -1006,
kCFURLErrorHTTPTooManyRedirects = -1007,
kCFURLErrorResourceUnavailable = -1008,
kCFURLErrorNotConnectedToInternet = -1009,
These error codes are available in CFNetworkError.h. In my application i have used in this way.
if ([error code] == kCFURLErrorNotConnectedToInternet) {
// if we can identify the error, we can present a more precise message to the user.
UIAlertView *alertView=[[[UIAlertView alloc] initWithTitle:APP_NAME message:#"Sorry, there doesn’t seem to be an internet connection." delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil]autorelease];
[alertView show];
}
This is working fine for me.
The viewcontroller which you have assigned delegate for the UIWebView; (in the code of viewcontroller where you have set the webview.delegate=self), you need to commit in the header (.h) file to the UIWebViewDelegate protocol. Only then your method :
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
will be triggered. I guess you are missing this otherwise your process is correct.
So, add the UIWebViewDelegate in your .h file.
Hope this will help.
You can check Network Connection using Reachability Code at ViewDidLoad or ViewWillAppear ..Download them using below link
https://github.com/tonymillion/Reachability
Reachability *reach = [Reachability reachabilityForInternetConnection];
NetworkStatus netStatus = [reach currentReachabilityStatus];
if (netStatus != NotReachable)
{
NSLog(#"Async.....Network is Available");
}
else
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Network Error" message:#"No Network Available" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil , nil];
[alertView show];
}
Or You can Put alert on below delegate method of UIWebView
(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
Hope it helps you...!
Related
I'm wondering why I don't get alert when I disconnect my internet connection. When I'm connected everything is going great, but when there is no connection, simply nothing appears, I'm pretty new in objective-c but I think this code looks correct.
Thanks for help anyway.
- (void)viewDidLoad
{
webView.hidden = YES;
NSURL *url = [NSURL URLWithString:#"https://url"];
webView.scrollView.scrollEnabled = NO;
NSURLRequest *requestURL = [NSURLRequest requestWithURL:url];
[webView loadRequest:requestURL];
if ([[webView stringByEvaluatingJavaScriptFromString:#"document.readyState"] isEqualToString:#"complete"]) {
webView.hidden = NO;
}
self.canDisplayBannerAds = YES;
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No Internet Connection!"
message:#"Can't connect. Please check your internet Connection"
delegate:self
cancelButtonTitle:#"Close"
otherButtonTitles:nil];
[alert show]; }
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
exit(0);
}
If you want to check the connectivity with internet then you have to check it in your code. For this you can go through Apple's Reachbility code.
The method webView:didFailLoadWithError: will called if page could not be loaded due to some reason. This means it's not connectivity issue, this may be due to some internal errors at server.
An async request has been sent to the server and here is my connection delegate.
in RKYLoginDelegate.m file, i made an alert to tell user that the member is verifying when receiving data.
didReceivedData
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[_receivedData appendData:data];
loginAlertView = [[UIAlertView alloc] initWithTitle:#"message"
message:#"verifying member..."
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
[loginAlertView performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:YES];
NSLog(#"Received data: %#", [[NSString alloc] initWithData:_receivedData encoding:NSUTF8StringEncoding]);
}
and in finish loading data, if nothing return, then shows the error message.
didFinishLoading
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
in the code, it will verify return state and parse value, if not respond then alert a dialog to notify user error message
if ([jsonDataDictionary count] > 0) {
// add member into data
RKYMemberManager *rkyMemberManager = [RKYMemberManager new];
[rkyMemberManager addMember:jsonDataDictionary];
// navigate to main
UIStoryboard *rkyMainStoryboard = [UIStoryboard storyboardWithName:#"RKYMainStoryboard" bundle:nil];
RKYMainViewController *rkyMainViewController =
[rkyMainStoryboard instantiateViewControllerWithIdentifier:#"RKYMain"];
[[[UIApplication sharedApplication] delegate].window.rootViewController.navigationController presentViewController:rkyMainViewController animated:YES completion:nil];
}
else {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:#"message"
message:#"Cannot login!"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:YES];
[alertView show];
NSLog(#"cannot login");
}
Those alert dialogs did show its message, but will cause an error:
Thread 1:EXC_BAD_ACCESS(code=2, address=0xc)
as title, am I doing correctly?
if yes, how to solve the problem that caused?
I can do authentication with NSURL and user can assign username and password. However, I got another problem. If I open this, http://html5test.com/ , it also pop up and ask username and password. I got authentication even if it is not supposed to get. I would like to know how to do.
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if(!_auth)
{
connection_for_auto = [[NSURLConnection alloc] initWithRequest:request delegate:self];
firsttimeonly=TRUE;
[connection_for_auto start];
NSLog(#"Request >> %# and !firsttimeonly",request);
return NO;
}
self.lbl_error.hidden = YES; //hide error message label
return YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
checkTochangeUIalert=TRUE;
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Login"
message:nil
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK",#"Auto", nil];
alertView.transform=CGAffineTransformMakeScale(1.0, 0.75);
alertView.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
[alertView show];
}
I think I have found a way to do. I need to check what kind of authentication method I use.
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic] || [challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodNTLM])
{
.............
}
I have a class called MatchmakingServer has a method as following:
- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state
{
switch (state)
{
case GKPeerStateAvailable:
break;
case GKPeerStateUnavailable:
break;
// A new client has connected to the server.
case GKPeerStateConnected:
if (_serverState == ServerStateAcceptingConnections)
{
if (![_connectedClients containsObject:peerID])
{
NSString *peerID2 =[self displayNameForPeerID:peerID];
self.PeerId=peerID;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Oops:("
message:[NSString stringWithFormat:#"%#:%# %#",#"device",peerID2,#"want to join your session"]
delegate:self
cancelButtonTitle:#"NO"
otherButtonTitles:nil];
[_connectedClients addObject:peerID];
NSLog(#"the orginal peerID %#",peerID);
[self.delegate matchmakingServer:self clientDidConnect:peerID];
}
}
also
#interface MatchmakingServer : NSObject <GKSessionDelegate,UIAlertViewDelegate>
Any Ideas why alertView dosn't call the clickedButtonAtIndex
You're not showing the alert view on the screen, you're only initializing it. Insert
[alert show];
after the initialization code and you should be fine.
You need to call [alert show]; method and adopt UIAlertViewDelegate in your UIViewController.h file.
This question already has answers here:
UIAlertView fails to show and results in “EXC_BAD_ACCESS” error
(6 answers)
Closed 8 years ago.
I add a function to dismiss the UIAlertView after several seconds.The whole code is like:
- (void)netWorkAlert
{
UIAlertView *netWork = [[UIAlertView alloc] initWithTitle:#"error" message:#"network has problems" delegate:self cancelButtonTitle:nil otherButtonTitles: nil];
[netWork show];
[self performSelector:#selector(dismissAlert:) withObject:netWork afterDelay:2];
}
- (void)dismissAlert:(UIAlertView *)alert
{
if(alert)
{
[alert dismissWithClickedButtonIndex:0 animated:YES];
[alert release];
}
}
the netWorkAlert is invoked when the network is unavailable.
Now the problem I met is when the netWorkAlert is invoked at the second time, the app is broken and the Xcode shows error in
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([ZJAppDelegate class]));
//Thread 1 :EXC_BAD_ACCESS(code=1,address=xc0000004)
}
}
I didn;t use ARC and I don't know why it crashes. Even I comment the [alert release];, it still has the same problem at the second time.
Could anyone help me to check it?
thanks!
The EXC_BAD_ACCESS is caused by accessing a released object. To avoid this make your call to UIAlertView kind of modal:
Function body:
-(void)checkSaving
{
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Do you want to add these results to your database?"
message:#"\n\n"
delegate:self
cancelButtonTitle:#"No"
otherButtonTitles:#"Save", nil];
alert.alertViewStyle = UIAlertViewStyleDefault;
[alert show];
//this prevent the ARC to clean up :
NSRunLoop *rl = [NSRunLoop currentRunLoop];
NSDate *d;
d= (NSDate*)[d init];
while ([alert isVisible]) {
[rl runUntilDate:d];
}
}
Your choice result:
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
// the user clicked one of the OK/Cancel buttons
if (buttonIndex == 1)//Save
{
//do something
}
if (buttonIndex == 0)//NO
{
//do something
}
}
Register the functions in the interface declaration:
#interface yourViewController ()
-(void)checkSaving
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
//...
#end
To call:
[self checkSaving];
I wish this will help you.
The UIAlertView could be out of scope by the time the dismissAlert method is called (your checking for alert being nil will prevent this code crashing. There is, however, a better way of implementing this where alert will never be out of scope.
Your class that defines the networkAlert method should implement the <UIAlertViewDelegate> protocol. The code below allows you to intercept the user clicking the 'cancel' button and perform a custom action. The default action of pressing cancel is to close the UIAlertView.
#interface YourClassName : UIViewController <UIAlertViewDelegate> {}
#implementation YourClassName
-(void) networkAlert
{
UIAlertView *netWork = [[UIAlertView alloc] initWithTitle:#"error"
message:#"network has problems"
delegate:self
cancelButtonTitle:#"cancel"
otherButtonTitles:nil];
[netWork show];
}
- (void) alertViewCancel:(UIAlertView*)alertView
{
what ever it is you want to do when the cancel button is pressed here
}