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.
Related
I have this code who send a e-mail to users, Im using MFMailCompose:
.h file
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>
#interface TestViewController : UIViewController <MFMailComposeViewControllerDelegate, MFMessageComposeViewControllerDelegate>
#property(nonatomic,assign) id<MFMailComposeViewControllerDelegate> mailComposeDelegate;
.m file
#synthesize mailComposeDelegate
-(void)sendEmail:(NSString*)valor{
//Valor receive the email
NSString *corpoMensagem = #"No have body yet...";
// From within your active view controller
if([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailCont = [[MFMailComposeViewController alloc] init];
mailCont.mailComposeDelegate = self;// Required to invoke mailComposeController when send
[mailCont setSubject:#"FazerBem - Recibo de Compra"];
[mailCont setToRecipients:[NSArray arrayWithObject:valor]];
[mailCont setMessageBody:corpoMensagem isHTML:YES];
[self presentViewController:mailCont animated:YES completion:nil];
}
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
if (error){
NSString *errorTitle = #"Erro to send";
NSString *errorDescription = [error localizedDescription];
UIAlertView *errorView = [[UIAlertView alloc]initWithTitle:errorTitle message:errorDescription delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[errorView show];
}
[self becomeFirstResponder];
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result{
}
when I click the send button he can send the email to the recipient and can close the screen, now when I click the cancel button, it opens 2 more options 'delete draft' and 'save draft' when I click on one of the app crashes and returns me the following error:
[TestViewController respondsToSelector:]: message sent to deallocated instance 0x16b3b470
How I can solve this problem?
Use Switch case to for performing actions:
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
UIAlertView *alert;
switch (result)
{
case MFMailComposeResultCancelled:
break;
case MFMailComposeResultSaved:
alert = [[UIAlertView alloc] initWithTitle:#"Draft Saved" message:#"Composed Mail is saved in draft." delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
break;
case MFMailComposeResultSent:
alert = [[UIAlertView alloc] initWithTitle:#"Success" message:#"You have successfully referred your friends." delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
break;
case MFMailComposeResultFailed:
alert = [[UIAlertView alloc] initWithTitle:#"Failed" message:#"Sorry! Failed to send." delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
break;
default:
break;
}
// Close the Mail Interface
[self dismissViewControllerAnimated:YES completion:nil];
}
Remove this line:
[self becomeFirstResponder];
That should fix your problem.
If above solution didn't work for you as it was for me, here, instead of self use instance of MFMailComposeViewController:
Instead Of
[self dismissViewControllerAnimated:YES completion:nil];
Use
[mailComposer dismissViewControllerAnimated:YES completion:nil];
I have UIAlertView working as expected in simulator, and earlier in my App's development it worked well on the device, but as of now it doesn't show up. I am however certain the code is running. Help would be greatly appreciated.
MacroEditViewController.h:
#interface MacroEditViewController : UIViewController <UIAlertViewDelegate>
MacoEditViewController.m:
- (IBAction)saveDatabase:(UIButton *)sender
{
[self alertStatusWithTitle:[NSString stringWithFormat:#"Are you sure you want to override %# for %#? This cannot be undone (But you can Reset All Overrides on Macros screen).", macroMeal[1], macroMeal[0]] :#"Update Macros"];
}
- (void) alertStatus:(NSString *)msg :(NSString *)title
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
message:msg
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:#"Cancel", nil];
[alertView show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
[self saveUpdatesToDatabase];
}
}
Why did you call your function like this
[self alertStatus:[#"Are you sure you want to override?"] :#"Update Macros"];
Call it like this
[self alertStatus:#"Are you sure you want to override?" :#"Update Macros"];
without the square brackets, it may be the problem
create a CIAlert.h
void CIAlert(NSString* title, NSString* alert);
void CIError(NSString* error);
and in CIAlert.m
#import "CIAlert.h"
void CIAlert(NSString* title, NSString* alert) {
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:title message:alert delegate:nil
cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
void CIError(NSString* error) {
CIAlert(#"Error", error);
}
import the class CIAlert.h and call it just like this...
CIAlert(#"Title", #"Enter your message");
I have six methods, in which I'm calling alert function.
Is it possible to call only the alert function only once, so to optimize my code will be?
This is my code:
// #import "ViewController.h"
//.h file
.m file
#interface ViewController ()
#end
#implementation ViewController
#synthesize usernameText;
#synthesize emailText;
#synthesize passwordText;
#synthesize `repasswordTex`t;
#synthesize postalText;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
//for keyboard hide on textfield return
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
[theTextField resignFirstResponder];
return YES;
}
//function for Name validation
- (BOOL) validatename:(NSString *) candidate{
[postalText setKeyboardType:UIKeyboardTypeAlphabet];
NSString *nameRegex = #"[A-Za-z]+";
NSPredicate *codeTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#",nameRegex];
return [codeTest evaluateWithObject:candidate];
}
// email validation
- (BOOL) validateEmail: (NSString *) candidate {
NSString *emailRegex = #"[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", emailRegex];
return [emailTest evaluateWithObject:candidate];
}
// password code validation
- (BOOL)paswordvalidation:(NSString *) candidate
{
}
// postal code validation
- (BOOL) validatecode: (NSString *) candidate {
NSString *codeRegex = #"^\d{5}(?:[-\s]\d{4})?$";
NSPredicate *codeTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", codeRegex];
return [codeTest evaluateWithObject:candidate];
}
//method call on submit button
- (IBAction)submitButn:(id)sender{
//user name method call
if(![self validatename:usernameText.text])
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Please Ensure that you have insert character only"delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
return;
}
//Email Method Call
else if(![self validateEmail:emailText.text])
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Please Insert Valid Email Address"delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
return;
}
//Password validate Method Call
else if([passwordText.text length] <6)//&& [repasswordText.text length] <= 6)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Password should contain minimun 6 "delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
return;
}
else if (![passwordText.text isEqualToString:repasswordText.text])
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"confirm password should be same"delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
return;
}
//Postal Code Method Call
else if(!([self validatecode:postalText.text] ||[postalText.text length] <6))
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"postal Code should cotain 5 "delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
return;
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Write this method and call where ever you want.
-(void)showAlert :(NSString *)alertTitleString WithAlertMessage :(NSString *)alertMessage{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:alertTitleString alertMessage delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
It is possible, add this method name in AppDelegate.h
-(void)alertFuction:(NSString *)title message:(NSString *)message
Then add this function to AppDelegate.m
-(void)alertFuction:(NSString *)title message:(NSString *)message
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:title message:message delegate:self cancelButtonTitle:#"Done" otherButtonTitles:nil, nil];
[alert show];
[alert release];
alert = nil;
[delegate.window setUserInteractionEnabled:YES];
}
Then in any other view controller put this
.h file
#class AppDelegate
.m file
#import AppDelegate
in viewDidload method
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
then you can call the alert method by
[delegate alertFuction:#"title" message:#"message"];
How about a generalised helper class with class methods which cover a number of common scenarios (which you may obviously want to reconfigure / add to):
#implementation AlertHelper
+ (UIAlertView *)showAlertWithMessage:(NSString *)message
{
[AlertHelper showAlertWithTitle:nil message:message delegate:nil cancelButton:NSLocalizedString(#"OK", nil) otherButton:nil];
}
+ (UIAlertView *)showAlertWithTitle:(NSString *)title message:(NSString *)message
{
[AlertHelper showAlertWithTitle:title message:message delegate:nil cancelButton:NSLocalizedString(#"OK", nil) otherButton:nil];
}
+ (UIAlertView *)showAlertWithTitle:(NSString *)title message:(NSString *)message delegate:(id < UIAlertViewDelegate >)delegate cancelButton:(NSString *)cancel otherButton:(NSString *)other
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:delegate cancelButtonTitle:cancel otherButtonTitles:(other ? #[ other ] : nil)];
[alert show];
}
#end
Note that the alert view is returned just in case it is required (say you need to automatically remove the alert view once an operation is complete).
Surely you can, you even should! You just need to refactor it to a separate methods witch will receive a few attributes or (better option) an object with variables from which you could set a required values for the alert you want to show.
- (void)showAlertWithTitle:(NSString *)alertTitle andMessage:(NSString *)alertMessage {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertTitle message:alertMessage delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
It could be than a way better but according to your case that will do what you want. It is just extracting a method from your code.
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
}
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];
}