I define a UIAlertView, its tag = 101, to determine save or not, show another UIAlertView called alertView2 when clicked save button, and then delete the subviews of rootView. But when I call clear Code [self clearAllSubviewsInRootView];here, it clear subViews before call alertView2. How do I fix it?
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView.tag == 101)
{
if (buttonIndex == 0)
{
}
else
{
if (buttonIndex == 1)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"input fileName" message:nil delegate:self cancelButtonTitle:#"cancel" otherButtonTitles:#"OK", nil];
alertView.tag = 102;
alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
[alertView show];
}
[self clearAllSubviewsInRootView];
}
}
if (alertView.tag == 102)
{
if (buttonIndex == 0)
{
}
else
{
NSArray *viewArray = [self.canvasView subviews];
NSUserDefaults *UD = [NSUserDefaults standardUserDefaults];
NSString *scaleStr = [UD objectForKey:#"scale"];
NSArray *dataArray = [NSArray arrayWithObjects:scaleStr, _labelArrivalTime.text, _textAccidentLocation.text,
_textDeclare.text, _textWeather.text, _textRoadSurface.text, [NSNumber numberWithFloat:canvasSize], nil];
NSMutableArray *array = [NSMutableArray arrayWithObjects:viewArray, dataArray, nil];
NSData * encodedata=[NSKeyedArchiver archivedDataWithRootObject:array];
NSString *fileName = [alertView textFieldAtIndex:0].text;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *floerName = #"file";
NSString *saveDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:floerName];
NSString *filePath = [saveDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.rta", fileName]];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:filePath])
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"file existed" message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
alertView.tag = 103;
[alertView show];
}
else
{
[encodedata writeToFile:filePath atomically:YES];
[self saveImage:_prospector.image :filePath :#"勘查员"];
[self saveImage:_draftman.image :filePath :#"绘图员"];
[self saveImage:_person.image :filePath :#"当事人"];
}
}
}
}
UIAlertViews are modal views, but that does not mean they are synchronous.
In fact, UIAlertViews are asynchronous modal views.
In plain english, that means that they will be presented on screen, but some other code may be executed simultaneously (= asynchronous). So, code execution does not stop after calling [myAlert show]. The user however, is not able to select something else, he or she must deal with this one and only element on screen (= modal).
Having said that: I do not know the exact implementation of UIAlertViews, but it would not surprise me if the current runloop is being run to the end until the alert is actually presented on screen. That means, all code after [alertView show] will be executed to the end, and only then the alert will show (with the next runLoop).
So, you are asking "why it clears subviews before showing the second alert", but this is exactly what you tell it to do:
if (buttonIndex == 1)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"input fileName" message:nil delegate:self cancelButtonTitle:#"cancel" otherButtonTitles:#"OK", nil];
alertView.tag = 102;
alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
[alertView show]; // <-- you show the alert
}
[self clearAllSubviewsInRootView]; // <—- and clear all views
You are creating and showing the second view and then immediately call [self clearAllSubviewsInRootView] after [alertView show].
If you want to clearAllSubviews only after the user has selected something in the second alert view, you must move this call [self clearAllSubviewsInRootView]to a later point in your if (alertView.tag == 102) routine
The main problem here js you override name of the alertView inside method:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
You have here property named alertView. Later you declare:
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"input fileName" message:nil delegate:self cancelButtonTitle:#"cancel" otherButtonTitles:#"OK", nil];
This is a bit confusing and i'm not sure what are you trying to achieve here.
But GCD seems to fitting your problem so Apple provide here a useful snippet (you can call it by start writing dispatch_after):
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//put code here, whatever you want to fire later (after two seconds in this case)
});
In your case you probably want (i'm not sure) to keep second alert view after code is completed. In this case you should
This works for me,.. And it so simple you can use this for an infinite alertview.
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if ([alertView.title isEqualToString:#"First Alertview Title"]) {
if (buttonIndex == [alertView cancelButtonIndex]) {
// do your stuff in cancel button --->First Alert
} else if (buttonIndex == 1) {
// do your stuff in other button ----> First Alert
}
} else if ([alertView.title isEqualToString:#"Second Alertview Title"]) {
if (buttonIndex == [alertView cancelButtonIndex]) {
// do your stuff in cancel button ----> Second Alert
} else if (buttonIndex == 1) {
// do your stuff in other button -----> Second Alert
}
}
}
Related
The photo in the link below illustrates the app I am currently working on, the name is a UITextfield that the user edits him/herself and the balance is label in which the user clicks the add button to add their desired funds. Then the two textfields below that allow for the input of money spent and how it was spent, this is then saved as a UITableviewCell in the UITable view. The problem I am currently having right now is when I restart my iPhone device the previously inputted data is rested meaning the user will have to rewrite everything which wouldn't help as this is an app to monitor one's savings. I did some googling to see if there was a fix for this I came across NSUserDefaults and tried the following code in my viewDidLoad.
Could someone provide the steps for a different approach to keep the inputted information where it is even after the user turns off his or her iPhone/iPad etc. Heres the photo link
http://imgur.com/DceJ7gs
[[NSUserDefaults standardUserDefaults] synchronize];
This is the code I am using to add funds which in turn changes the balance displayed by the uilabel Balance in the above photo
- (IBAction)addFunds:(id)sender {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Add Funds" message:#"Please add your funds" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Done", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[_inputStatement resignFirstResponder];
[_spent resignFirstResponder];
[myTableView resignFirstResponder];
[_custName2 resignFirstResponder];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
//alertview input text was blank so we are doing a check
if([[alertView textFieldAtIndex:0].text isEqual:#""] && buttonIndex == 1){
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Input Required" message:#"Please fill in the textfield" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
} else {
if(buttonIndex == 1){
NSString *tempText = [alertView textFieldAtIndex:0].text;
float toAdd = [tempText floatValue];
float add = [_currentBalance.text floatValue];
if(toAdd < 0) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"You can't add a negative number, try again" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
} else {
add = add + toAdd;
if(add >= 99999999.50){
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Well you broke it" message:#"You are not allowed to input this much. In the event you do have these funds, I apologize for putting in this restriction. Personally contact me at thejobemuhammed#gmail.com for further inquiries." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
} else {
_currentBalance.text = [NSString stringWithFormat:#"%.2f", add];
if(!array){
array = [[NSMutableArray alloc]init];
}
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
date1 = [NSDate dateWithTimeIntervalSinceNow:5];
NSString *resultString = [dateFormatter stringFromDate:date1];
[array insertObject:[NSString stringWithFormat:#"%#%#%#",#"$",tempText, #" deposited"] atIndex:0];
[date insertObject:resultString atIndex:0];
[details insertObject:#"This is a deposit" atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.myTableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
}
[_inputStatement resignFirstResponder];
[_spent resignFirstResponder];
[myTableView resignFirstResponder];
}
add this code where you want to save . i am not getting where are you saving .
save it using this code
NSString *valueToSave = #"hereis yourvalue";
[[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:#"preferencekyename"];
[[NSUserDefaults standardUserDefaults] synchronize];
to get it back later using this code
NSString *savedValue = [[NSUserDefaults standardUserDefaults]
stringForKey:#"preferencekyename"];
I have a tabbed application with 2 tab views. I want to change the view from the second tab to the first when the user presses "OK" on an alert view.
The following code snippet works when I use it on an -IBAction button pressed, but it doesn't do anything when I use it inside the alert code:
self.tabBarController.selectedViewController = [self.tabBarController.viewControllers objectAtIndex:0];
Why does it not work when used as below, in my SeondViewController.m in my
- (void)viewDidLoad {
[super viewDidLoad];?
UIAlertView *alert =[[UIAlertView alloc]
initWithTitle:#"Camera and Target coincident"
message:msg
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
self.tabBarController.selectedViewController = [self.tabBarController.viewControllers objectAtIndex:0];
I'm just learning this, so anything you can offer would be helpful.
When I use the following code:
if ([ theProjection Trans_Initialise] == 1) {
NSString * msg = nil;
UIAlertView *alertView =[[UIAlertView alloc] initWithTitle:#"Camera and Target coincident" message:msg delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if ([[alertView buttonTitleAtIndex:buttonIndex] isEqualToString:#"OK"]) {
self.tabBarController.selectedIndex = 0;
}
}
I get the error message on -(void) alertView "Invalid argument type void to unary expression" Am I doing something grammatical, or is it (quite possibly) something I just didn't understand?
First of all, you need a delegate call back from the alert view informing you about the button that was clicked.
Your alert view should be created like this :
UIAlertView *alert =[[UIAlertView alloc] initWithTitle:#"Camera and Target coincident" message:msg delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
Then in your m file implement the function :
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if ([[alertView buttonTitleAtIndex:buttonIndex] isEqualToString:#"OK"]) {
self.tabBarController.selectedIndex = 0;
}
}
I have two buttons that will pop up an alertview with textfield to input data. However, only certain characters are allowed in each of the two textfields. Somehow, if I press the second button, the character set from the first button is used. What's going on here?
Also, what would be a more elegant form of inputting data without having to use an alertview? Could I use a modal view? If so, how?
- (IBAction)editRate
{
if(!self.powerOn) return;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Edit Jail Fee Rate"
message:#"Enter New Daily Rate"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[[alert textFieldAtIndex:0] setKeyboardType:UIKeyboardTypeNumberPad];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != alertView.cancelButtonIndex)
{
UITextField *field = [alertView textFieldAtIndex:0];
field.placeholder = #"Enter New Rate";
NSCharacterSet * set = [[NSCharacterSet characterSetWithCharactersInString:#"0123456789."] invertedSet];
if ([field.text rangeOfCharacterFromSet:set].location != NSNotFound)
{
UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Only numbers are allowed in this field."delegate:self cancelButtonTitle:#"OK"otherButtonTitles:nil];
[errorAlert show];
FeeRate.text=#"0.00";
}
else
{
FeeRate.text = field.text;
[[NSUserDefaults standardUserDefaults] setObject:field.text forKey:RATE_KEY];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
else
{
}
}
- (IBAction)editDate
{
if(!self.powerOn) return;
UIAlertView *alertDate = [[UIAlertView alloc] initWithTitle:#"Edit Jail Fee Date"
message:#"Enter New Date"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
alertDate.alertViewStyle = UIAlertViewStylePlainTextInput;
[[alertDate textFieldAtIndex:0] setKeyboardType:UIKeyboardTypeNumberPad];
[alertDate show];
}
- (void)alertDate:(UIAlertView *)alertDate clickedButtonAtIndex:(NSInteger)buttonIndex2
{
if (buttonIndex2 != alertDate.cancelButtonIndex)
{
UITextField *fieldDate = [alertDate textFieldAtIndex:0];
fieldDate.placeholder = #"Enter New Date";
NSCharacterSet * setnew = [[NSCharacterSet characterSetWithCharactersInString:#"0123456789/"] invertedSet];
if ([fieldDate.text rangeOfCharacterFromSet:setnew].location != NSNotFound)
{
UIAlertView *errorAlert1 = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Only numbers and slashes are allowed in this field."delegate:self cancelButtonTitle:#"OK"otherButtonTitles:nil];
[errorAlert1 show];
FeeDate.text=#"00/00/0000";
}
else
{
FeeDate.text = fieldDate.text;
[[NSUserDefaults standardUserDefaults] setObject:fieldDate.text forKey:DATE_KEY];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
else
{
}
}
When a UIAlertView is dismissed then a function called
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
is called.
So, both your alert views call this function.
One way to tell which alertView is calling it, you could create an ivar or better two properties like this:
#property (nonatomic, strong) UIAlertView *rateAlert;
#property (nonatomic, strong) UIAlertView *dateAlert;
and you should initialize like this:
[self setRateAlert:[[UIAlertView alloc] initWithTitle...
[self.rateAlert show];
and
[self setDateAlert:[[UIAlertView alloc] initWithTitle...
[self.dateAlert show];
and then:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView==self.rateAlert) {
//do whatever for rateAlert
} else {
//do whatever with dateAlert
}
}
I want an alert when the following text fields receive the conditions in second section of code
self.circuit.rcdAtIan = [ICUtils nonNilString:self.rcdAtIan.text];
self.circuit.rcdAt5an = [ICUtils nonNilString:self.rcdAt5an.text];
The above code works fine so now I need to fire it. Using the below method was my first thought but that fires the alert on every keyboard resignation. I only want the alert to display once.
- (void)textFieldDidEndEditing:(UITextField *)textField {
if ([_rcdAtIan.text intValue]> 200) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning" message:#"my message" delegate:nil cancelButtonTitle: #"Ok" otherButtonTitles: nil];
[alert show];
}
if ([_rcdAt5an.text intValue]> 40) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning" message:#"my message" delegate:nil cancelButtonTitle: #"Ok" otherButtonTitles: nil];
[alert show];
}
}
Im thinking maybe I need a bool with NSUserDefaults perhaps? but not sure how to implement that to check if the alert has been shown. Normally if I wanted an alert shown once I would do
if (![#"1" isEqualToString:[[NSUserDefaults standardUserDefaults] objectForKey:#"alert"]]){
[[NSUserDefaults standardUserDefaults] setValue:#"1" forKey:#"alert"];
[[NSUserDefaults standardUserDefaults] synchronize];
[alert show];
}
However in this instance, when the page is reloaded I want the alerts to be shown again and in any case im not sure if thats an efficient way to solve this
Don't use NSUserDefaults, that would be inappropriate
in your #interface...
#property (assign) BOOL freshAlert1;
#property (assign) BOOL freshAlert2;
then something like this... (assuming 'page is reloaded' equates to your viewController coming back onscreen)
- (void)viewDidAppear
{
self.freshAlert1 = YES;
self.freshAlert2 = YES;
}
if (([_rcdAtIan.text intValue]> 200) && self.freshAlert1) {
self.freshAlert1 = NO;
...
}
if (([_rcdAt5an.text intValue]> 40) && self.freshAlert2) {
self.freshAlert2 = NO;
...
}
What exactly do you mean by "once"? Once per app run, once per editing step?
Or maybe simply add two BOOL flags that you can reset whenever you want and simply to
- (void)textFieldDidEndEditing:(UITextField *)textField {
if ([_rcdAtIan.text intValue]> 200 && !alert1shown) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning" message:#"my message" delegate:nil cancelButtonTitle: #"Ok" otherButtonTitles: nil];
alert1shown = YES;
[alert show];
}
if ([_rcdAt5an.text intValue]> 40 && !alert2shown) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning" message:#"my message" delegate:nil cancelButtonTitle: #"Ok" otherButtonTitles: nil];
alert2shown = YES;
[alert show];
}
}
I have a button which I want to implement with password before triggering a segue if the password is correct. it all looks fine up to the moment when you type in wrong password and I have implemented another alertView to tell the user the password is wrong. When the alert view pops out and dismisses after some delay, it keeps re-appearing and disappearing and nothing else can be done on the screen!
How to stop the re appearing?
Below is my part of the code that deals with this:
- (IBAction)editLeagues:(id)sender {
[self presentAlertViewForPassword];
}
-(void)presentAlertViewForPassword
{
_passwordAlert = [[UIAlertView alloc]initWithTitle:#"Password"
message:#"Enter Password to edit Leagues"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
[_passwordAlert setAlertViewStyle:UIAlertViewStyleSecureTextInput];
_passwordField = [_passwordAlert textFieldAtIndex:0];
_passwordField.delegate = self;
_passwordField.autocapitalizationType = UITextAutocapitalizationTypeWords;
_passwordField.tag = textFieldPassword;
[_passwordAlert show];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSString *password = [NSString stringWithFormat:#"55555"];
if ( ![_passwordField.text isEqual:password]) {
_wrongPassword = [[UIAlertView alloc] initWithTitle:#"Wrong Password"
message:#"You are not authorised to use this feature!"
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
[_wrongPassword show];
[self performSelector:#selector(allertViewDelayedDissmiss:) withObject:nil afterDelay:2];
}
else
{
[self performSegueWithIdentifier:#"addLeague" sender:[alertView buttonTitleAtIndex:0]];
}
}
-(void) allertViewDelayedDissmiss:(UIAlertView *)alertView
{
[_wrongPassword dismissWithClickedButtonIndex:-1 animated:YES];
}
- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
{
NSString *inputText = [[alertView textFieldAtIndex:0] text];
if( [inputText length] >= 4 )
{
return YES;
}
else
{
return NO;
}
}
[_wrongPassword dismissWithClickedButtonIndex:-1 animated:YES]; will call the delegate method alertView:didDismissWithButtonIndex:
You have two options:
don't set a delegate on the wrong password alert
check for the correct alert in alertView:didDismissWithButtonIndex: e.g.
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (alert == _passwordAlert) {
NSString *password = [NSString stringWithFormat:#"55555"];
// and so on
}
}
Issue is causing because when you dismiss the wrong password alert it'll also call the didDismissWithButtonIndex delegate method.
Solution 1
Set the delegate of wrong password alert to nil.
wrongPassword = [[UIAlertView alloc] initWithTitle:#"Wrong Password"
message:#"You are not authorised to use this feature!"
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:nil];
Solution 2
Add a tag to your alertView. And change your methods like:
-(void)presentAlertViewForPassword
{
_passwordAlert = [[UIAlertView alloc]initWithTitle:#"Password"
message:#"Enter Password to edit Leagues"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
[_passwordAlert setAlertViewStyle:UIAlertViewStyleSecureTextInput];
passwordAlert.tag = 7;
_passwordField = [_passwordAlert textFieldAtIndex:0];
_passwordField.delegate = self;
_passwordField.autocapitalizationType = UITextAutocapitalizationTypeWords;
_passwordField.tag = textFieldPassword;
[_passwordAlert show];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if(alertView.tag == 7)
{
NSString *password = [NSString stringWithFormat:#"55555"];
if ( ![_passwordField.text isEqual:password])
{
_wrongPassword = [[UIAlertView alloc] initWithTitle:#"Wrong Password"
message:#"You are not authorised to use this feature!"
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
[_wrongPassword show];
[self performSelector:#selector(allertViewDelayedDissmiss:) withObject:nil afterDelay:2];
}
else
{
[self performSegueWithIdentifier:#"addLeague" sender:[alertView buttonTitleAtIndex:0]];
}
}
}