Cocoa touch how to run a UIAlertView inside a while loop - objective-c

I have an int where someone sets how many spellings there are called samount and a int called amountdone and they are both set to 0 like this NSInteger samount = 0;
NSInteger amountdone = 0;at the start. I have a button and when it is clicked it calls the method Startese. The code is
- (IBAction)Startest:(id)sender {
UIAlertView *amount = [[UIAlertView alloc] initWithTitle:#"Amount" message:#"How much spellings are there" delegate:self cancelButtonTitle:#"That amount" otherButtonTitles:nil];
[amount setAlertViewStyle:UIAlertViewStylePlainTextInput];
[[amount textFieldAtIndex:0] setKeyboardType:UIKeyboardTypeNumberPad];
[amount setTag: 0];
[amount show];
}
And I need a UIAlertView to display its self and then add its text in to an array I have got the alertView clickedButtonAtIndex void working like this
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch (alertView.tag)
{
case 0: /* amount alert */
{
samount = [[alertView textFieldAtIndex:0]text];
UIAlertView *spellings = [[UIAlertView alloc]initWithTitle:#"Enter Spelling " message:#"Pleaseenter ONE of the spellings" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[spellings setTag:1];
[spellings setAlertViewStyle:UIAlertViewStylePlainTextInput];
[spellings show];
}
break;
case 1: /* Spellings alert*/{
while (amountdone < samount) {
amountdone = amountdone + 1;
self.myarry = [[alertView textFieldAtIndex:0]text];
}
}
break;
}
}
`
It works the first time but once the while loop activates it freezes the app does anyone know how to fix this

Create method to create and launch your alertView and in clickedButtonAtIndex: method call after delay;
[self performSelector:#selector(yourMethodForLaunchingAlertView:)
withObject:objectOrNill
afterDelay:0.5];
Hope this help.

Well, the reason it is locking up is because amountdone is never set to anything other than the initialization of 0, so amountdone < samount is likely always true, and therefore your while loop continues forever.
When is amountdone suppose to be set?
Edit
I don't think you want a while loop. Based on what you've got
while (amountdone < samount) {
amountdone = amountdone + 1;
self.myarry = [[alertView textFieldAtIndex:0]text];
}
The while loop provides no value, it may as well be an if condition because you're setting the same thing over and over again (which setting NSString to NSArray doesn't make sense either).
I think it's time to take a step back and reevaluate the problem you're solving and your approach. Maybe I can help if you describe the use-case/business requirement.

Related

The Alert View shows many time not one time

I create UIAlertView in my function, the problem is it shows a lot of time when the function runs, how can I create an if statement to show only one time like if UIAlertView shows not show any more.
- (void)showAlert {
_myAlertView = nil;
_myAlertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Call_On_Hold",nil)
message:NSLocalizedString(#"Please_Wait",nil)
delegate:self
cancelButtonTitle:NSLocalizedString(#"Close_call",nil)
otherButtonTitles:nil, nil];
_myAlertView.tag = myAlertViewsTag;
[_myAlertView show];
}
Here is the function that my UIAlertView appear continuously instead of one time.
- (void) trafficTimerRun:(NSTimer*)theTimer
{
++ trafficTimerTicks;
pjmedia_rtcp_stat stat;
if (!get_stream_info([call_id intValue], &stat)) {
return;
}
LogDebug(TAG_SIP, #"Got %d bytes on stream 0 (previous: %d)", stat.rx.bytes, prev_bytes);
if (stat.rx.bytes == prev_bytes) {
if (trafficTimerTicks >= 10) {
// Steve-note: Here we need to show a pop-up message when the call in on hold when the trafficTimerTicks run.
[self showAlert];
LogError(TAG_SIP, #"No traffic received, hanging up");
// [theTimer invalidate];
// broken = YES; Steve note: The call shouldnt broke.
// [self hangup]; Steve note: The call shouldnt hangup.
}
}
}
Use a boolean:
bool alertIsShowing = false;
and in your updating method put something like this:
if (trafficTicks > 10){
if (!alertIsShowing){
alertIsShowing = true;
[self showAlert];
}
}
Then when your alert is dismissed, reset your boolean:
alertIsShowing = false;

Test Application by looping through a pattern of values in UITextField

I want to test my application by entering values from 1 to 10000 in a UITextField and pressing a "Go" UIButton.
And know conditions where a segue is getting performed.
How do I define the test criteria for automating testing with values 1 - 10000 being entered into the UITextField?
Another situation exactly matching my problem:
While testing a calculator application, I need to check all the possible operations and numbers. Can we do automation to test random clicks on calculator and check the output?
You can use a loop to try each value between 1 and 10000. For each value, type it into the text field, press the button and see what happens. I'm not sure what you're expecting to happen, so I have just written code which checks that a label appears - you should change this to whatever you think would assert that the correct outcome has happened.
XCUIApplication *app = [[XCUIApplication init] alloc];
XCUIElement *textField = [[app.textFields matchingIdentifier: "myTextField"] elementBoundByIndex: 0];
XCUIElement *goButton = [[app.buttons matchingIdentifier: "goButton"] elementBoundByIndex: 0];
for (NSNumber i = 1; i <= 10000; i++) {
NSString *n = [NSString stringWithFormat:#"%d", i];
[textField tap];
[textField typeText: n];
[goButton tap];
// Define what it is you expect to happen
BOOL expectedOutcome = [[app.staticTexts matchingIdentifier: "myLabel"] elementBoundByIndex: 0].exists;
XCTAssert(expectedOutcome, [NSString stringWithFormat:#"Unexpected result for %d", i])
}

What is a convenient way to check UITextFields for errors before allowing a form to submit?

I've been at this all day and just can't get my head around it. On a form in my app, I'm using -[UITextFieldDelegate textFieldDidEndEditing]: to register any errors and store them in an NSMutableArray instance variable formErrors.
I intend to use the formErrors when my submit button is pressed, or perhaps to disable the button disabled while there are errors on the form. The problem is the error count goes all over the place. I've just ended up confusing myself as you can see my code where I'm incrementing and decrementing in order to try and control what's going on but just confusing myself more.
Error messages get put on formErrors like this:
-(void)textFieldDidEndEditing:(UITextField *)textField {
if ( textField == [self nameField] ) {
if ( ([[textField text] isEqualToString:#""]) ) {
[formErrors addObject:#"What is your name?"];
errorCount++;
} else {
errorCount--;
if ( ([[textField text] length] < 2) || ([[textField text] length] > 20) ) {
[formErrors addObject:#"Name must contain a minimum of 2 and a maximum of 20 characters only."];
errorCount++;
} else {
errorCount--;
if ([[textField text] rangeOfCharacterFromSet:alphaSet].location != NSNotFound) {
[formErrors addObject:#"Name must contain letters and spaces only."];
errorCount++;
}
}
}
}
if (textField == [self ageField]) {
if ( ([[textField text] isEqualToString:#""]) ) {
[formErrors addObject:#"How old are you?"];
errorCount++;
} else {
errorCount--;
if ( ([[textField text] intValue]) < 1 || ([[textField text] intValue] > 120) ) {
[formErrors addObject:#"Please enter an age using a number between 1 and 120."];
errorCount++;
} else {
errorCount--;
if ([[textField text] rangeOfCharacterFromSet:numericSet].location != NSNotFound) {
[formErrors addObject:#"Age must be given in numbers."];
errorCount++;
}
}
}
}
My instance var:
{
NSMutableArray *formErrors;
}
Then initialise it in viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
formErrors = [[NSMutableArray alloc] init];
Then in prepareForSegue: I have some temporary code to check things are working:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
int errCount = [formErrors count];
// check if all textfield values are filled in if not then disallow form submit
for (NSString *error in formErrors) {
NSLog(#"Total %d errors, \n Error Message: %#", errCount, error);
}
All I want to do is, as I enter and leave fields, check if there are any errors; if there are, just store the error message in formErrors, so I can do what I need to do in the prepareForSegue:. Is this even the right approach? I've tried doing this many different ways but just keep on going in circles.
The submit button is linked to my segue and also is an outlet so I can enabled and disable it as I please.
Help would be appreciated
Kind regards
Your approach is a bit redundant. Validate your fields upon submission, cancel submission if there are any errors:
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
NSMutableArray *errors = [NSMutableArray array];
if (self.nameTextField.text.length > 21) {
[errors addObject:#"Name cannot be longer than 21 symbols"];
}
else if (!self.nameTextField.text.length) {
[errors addObject:#"Please enter your name"];
}
if (!self.passwordTextField.text.length) {
[errors addObject:#"Please enter password"];
}
else if (!self.confirmPasswordTextField.text.length) {
[errors addObject:#"Please confirm your password"];
}
else if (self.passwordTextField.text.length < 6) {
[errors addObject:#"Password is too short, use at least 6 characters."];
}
else if (![self.passwordTextField.text isEqualToString:self.confirmPasswordTextField.text]) {
[errors addObject:#"Passwords do not match"];
}
if (!self.emailTextField.text.length) {
[errors addObject:#"Please enter your e-mail"];
}
if (!self.image) {
[errors addObject:#"Please choose a photo"];
}
if (errors.count) {
[[[UIAlertView alloc] initWithTitle:#"Error"
message:[errors componentsJoinedByString:#"\n"]
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil] show];
return NO;
}
return YES;
}
You're on the right path, but here are a couple of observations.
First I would get rid of all the errorCount++ and errorCount-- lines. They don't make sense, because you can always count the items in your error array.
Every time you check your input fields, clear your error array, otherwise you will be having errors that might have been already corrected.
Inside your -(void)textFieldDidEndEditing:(UITextField *)textField method, don't only check the textfield that has been edited, because you wold need to keep track of the errors that were before, the ones that were corrected, and the new ones... too much trouble.
I think it's best to create a new method that checks all the information and returns an array of errors. Call this routine from textFieldDidEndEditing.
- (NSArray *)checkInputs
{
NSMutableArray *errors = [NSMutableArray array];
// Loop through the textfields and fill your array
return (NSArray *)errors;
}

Repopulate UITableView with New Data

I am implementing a search functionality using UIAlertView that will search a SQL Table for a match and repopulate the UITableView. So far I have this code below. "results" is array of match returned data from the search query. Then, I checked if the "elements" are empty which means it does not match any item in SQL Table. If it does then I would like to erase the data currently on UITableView and replace with the "results" data.
Here is my code so far:
NSUInteger *elements = [results count];
if(elements == 0)
{
UIAlertView *av = [[UIAlertView alloc]initWithTitle:#"Item Not Found" message:#"Sorry the item was not found" delegate:self cancelButtonTitle:#"Cancel"
otherButtonTitles:nil, nil];
[av show];
}
if(elements >= 1)
{
//Repopulate UITableView with Data
self.itemTitles = itemstitle;
self.itemPrices = itemsprice;
self.itemCategory = itemscategory;
}
Note: I tried to use [tableView reloadData] but not sure how to implement it in this case.
Thanks in advance for the help.

Creating defaults in Objective C

I'm working on my first big application and have inadvertently driven myself into a panic from a small flaw in design. I've made a timer that counts at the touch of a button, and upon a second touch, transitions into a secondary timer with a 60 second countdown.
The problem lies in the fact that once I repeat this process, the (kRest-Pause) call is remembered. I'm looking to create a default countdown of 60 without the continuation of the time. Should I kill it in memory and create a new instance for each subsequent button press? Or is there a logic game that looks at the aggregate time and corrects with each new occurance?
I don't know how to approach this, I'm done attempting -if statements with returns as I have learned that's not how that works. Any help would be appreciated
EDIT: Sorry for the lack of clarity. I'm pretty green on programming of any caliber. So far, the main timer counts down from 10-0 then up from 0-120. In that 2 minute period, if the button is pressed again, the 0-120 count is paused for 60 seconds or until the button is pressed for the third time. If this 60-0 countdown reaches 0 or is interrupted, the initial 0-120 countup resumes its count. My issue is that if I push the button a fourth time, the 60-0 countdown is resumed from the moment of interruption without retaining a default of 60. This is why I named the post "creating defaults in Objective C". It's the wrong use of the word and way to broad, but it's what I could come up with.
kRest=60
-(void)increase{
if (mode==1){
count++;
int d = 10-count;
if (d==0){ timeLabel.text = #"Begin";
[self startPlaybackForPlayer: self.startTimerSound];}
else {timeLabel.text = [NSString stringWithFormat:#"%d", abs(d)];}
if(d<0){
//workign out
active = TRUE;
if (d <= -20) {
[self stopTimer];
}
}
else{
//no user interface
active = FALSE;
}
}
else{
pause++;
countdownLabel.text = [NSString stringWithFormat:#"%d!", (kRest-pause)];
NSLog(#"Paused at time %d", pause);
UIColor *textColor = nil;
if (pause % 2==0){
textColor = [UIColor yellowColor];
}
else{
textColor = [UIColor redColor];
}
timeLabel.textColor = textColor;
if ((kRest-pause)==0){
countdownLabel.text = [NSString stringWithFormat:#"%d!",pause];
mode=1;
pause=0;
[button setTitle:#"Stop" forState:UIControlStateNormal];
repCount++;
myRepCount.text = [NSString stringWithFormat:#"Rep Count: %d", repCount];
countdownLabel.text = #"";
}
}
}
if you are using a timer to access this counter then you should be able to update the counter that the timer uses. Just make sure you synchronize the object so you dont edit while you are reading.
here is an example of what I mean.
int counter = 0;
int limit = 60;
- (BOOL) incrementUntilReached{
#synchronized(self){
if (counter == limit) return YES;
counter++;
return NO;
}
}
- (void) resetTimer{
#synchronized(self){
counter = 0;
}
}
- (int) countsLeft {
#synchronized(self){
return limit - counter;
}
}