I will improve my iOS Programm by handling errors for loading a MapView. If there is no internet connection I will display an alert. But the the method mapViewDidFailLoadingMap will get called again and again so the UIAlert.
How can I achieve that the the Alert will only showed once?
- (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error {
NSString *domain = [error domain];
NSInteger code = [error code];
NSLog(#"userInfo: %#", [error userInfo]);
NSLog(#"localizedDescription: %#", [error localizedDescription]);
NSLog(#"localizedFailureReason: %#", [error localizedFailureReason]);
NSLog(#"localizedRecoverySuggestion: %#", [error localizedRecoverySuggestion]);
NSLog(#"localizedRecoveryOptions: %#", [[error localizedRecoveryOptions] description]);
if ([domain isEqualToString:NSURLErrorDomain]) {
if (code == NSURLErrorNotConnectedToInternet) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Map Loading Error" message:[error localizedDescription] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
}
}
If your program logic allows then you can set the delegate for the MKMapView object to nil when the failure/error occurs and it will stop sending failure/error messages to the delegate thereby preventing display of multiple alerts.
You can set delegate to nil within mapViewDidFailLoadingMap:withError method.
You can use a BOOL flag to ensure that the error is shown only once for the MKMapView:
- (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error
{
if (displayErrors) {
// display the error...
displayErrors = NO;
}
}
If you reset the flag in viewWillAppear for the corresponding view controller, the error will be shown once for every time the view is accessed:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
displayErrors = YES;
}
Related
I'm trying to set up an anonymous login so my users don't have to create an account an account on the eJabberd server to use the chat room. The configuration for the server in the ejabberd.cfg is:
{host_config, "bubble", [{auth_method, anonymous},
{anonymous_protocol, login_anon}]}.
My method to connect the client to the XMPPStream:
- (BOOL)connect {
[self setupStream];
if (![self.xmppStream isDisconnected]) {
return YES;
}
if (![PFUser currentUser]) {
return NO;
}
NSString *currentUserId = [NSString stringWithFormat:#"%##bubble",[PFUser currentUser].objectId];
[self.xmppStream setMyJID:[XMPPJID jidWithString:currentUserId]];
self.xmppStream.hostName = kJABBER_HOSTNAME;
NSError *error = nil;
if (![self.xmppStream connectWithTimeout:10 error:&error]) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:[NSString stringWithFormat:#"Can't connect to server %#", [error localizedDescription]]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
return NO;
}
return YES;
}
As well as the xmppStreamDidConnect method:
- (void)xmppStreamDidConnect:(XMPPStream *)sender {
self.isOpen = YES;
NSError *error = nil;
if(![self.xmppStream authenticateAnonymously:&error]) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:[NSString stringWithFormat:#"Can't connect to server %#", [error localizedDescription]]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
}
}
When I try to login into the server, it keep on getting "The server does no support anonymous authentication".
Not sure what I'm doing wrong here, please let me know your thoughts.
From the XMPPFramework documentation:
If you wish to use anonymous authentication, you should still set myJID prior to calling connect. You can simply set it to something like "anonymous#domain", where "domain" is the proper domain. After the authentication process, you can query the myJID property to see what your assigned JID is.
Make sure that the settings on the server allow anonymous login as well.
If you don't have access to the serve configuration you can still check if the server allows anonymous login using something like:
- (void)xmppStreamDidConnect:(XMPPStream*)sender
{
self.isXmppConnected = YES;
if ([self.xmppStream supportsAnonymousAuthentication]) {
NSError* error = nil;
//the server does support anonymous auth
[self.xmppStream authenticateAnonymously:&error];
}
else {
NSLog(#"The server does not support anonymous authentication");
}
}
Be sure to place it in the didConnect delegate method, as it needs to be connected first.
I am using the default classes provided by app to do my networking tasks in my app.
At some point, some of my requests time out (regardless of the reason for the timeout)
I would like to retry some of these requests
I have subclassed the NSURLConnection class and added some parameters to it.
However, in the method "connection:didFailWithError:"
con.retries seems to always be 1, never incremented. Why ?
- (void)connection:(NSURLConnection*) connection didFailWithError:(NSError *)error
{
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
NSLog(#"%#",[NSString stringWithFormat:#"Did recieve error: %#", [error description]]);
NSLog(#"%#",[NSString stringWithFormat:#"%#", [[error userInfo]description]]);
WBURLConnection *con = (WBURLConnection *)connection;
if([con shouldRetryRequest:error]){
con.retries ++;
[con start];
}else{
[con cancel];
[con.data setLength:0];
if(!self.alert){
self.alert = [[UIAlertView alloc]initWithTitle:#"Alert" message:[error localizedDescription] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[self.alert show];
}else {
if(![self.alert isVisible]){
[self.alert show];
}
}
}
}
-(BOOL)shouldRetryRequest:(NSError *)error{
[self.retryCount appendString:[NSString stringWithFormat:#"%#:%ld",error,(long)self.retries]];
LogInfo(#"retries:%#",self.retryCount);
if([error code] == -1004){
return NO;
}
return self.retries<3;
}
I want to send a resource with Multipeer Connectivity framework, see below. But the strange thing is that the log says:
[self.mySession connectedPeers]: (
"<MCPeerID: 0x10fc9d60 DisplayName = iPad>"
)
Error: Peer not connected
So peer is connected, and in the next line says it is not connected. How, why? All the delegate methods are implemented well on client side.
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"[self.mySession connectedPeers]: %#", [self.mySession connectedPeers]);
[self.mySession sendResourceAtURL:u withName:#"apple" toPeer:[self.mySession connectedPeers] withCompletionHandler:^(NSError *error) {
if (error) {
NSLog(#"Error: %#", [error localizedDescription]);
}
else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"MCDemo"
message:#"File was successfully sent."
delegate:self
cancelButtonTitle:nil
otherButtonTitles:#"Great!", nil];
[alert performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:NO];
}
}];
});
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 use this code to share to facebook:
[appDelegate.facebook dialog:#"feed" andParams:params andDelegate:appDelegate];
How can i get the notification (like sharekit) when sharing is successful?
I want to show UIAlertView but i do not know which facebook method that i need to put the UIAlertView.
I try in this method:
- (void)dialogDidSucceed:(NSURL *)url {
if ([_delegate respondsToSelector:#selector(dialogCompleteWithUrl:)]) {
[_delegate dialogCompleteWithUrl:url];
}
UIAlertView * alert=[[UIAlertView alloc]
initWithTitle: #"Sharing to Facebook"
message: #"Success"
delegate:self
cancelButtonTitle:#"Close"
otherButtonTitles:nil, nil];
[self setAlertSuccess:alert];
[alertSuccess show];
[alert release];
NSLog(#"SUCCESS 2");
[self dismissWithSuccess:YES animated:YES];
}
It is working however, when i click cancel button, this method is also called. So where is the right one to put the success alert view?
I am new in IOS.
These are changes i made in FBDialog.m
- (void)dismissWithSuccess:(BOOL)success animated:(BOOL)animated {
if (success) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Facebook Login Sucessful!" message:#"" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
if ([_delegate respondsToSelector:#selector(dialogDidComplete:)]) {
[_delegate dialogDidComplete:self];
}
} else {
if ([_delegate respondsToSelector:#selector(dialogDidNotComplete:)]) {
[_delegate dialogDidNotComplete:self];
}
}
[self dismiss:animated];
}