I've been staring at this issue for the past week. Countless cups of Joe, cats stepping on my keyboard, and girlfriend wanting me to get off of the laptop later - I still can't figure this out. Hoping I'm doing something very stupid (100% chance) that I'm over looking.
I have some code which appends a decimal to the number pad. Most of the code was taken from here (http://brygruver.squarespace.com/blog/2009/10/1/creating-a-custom-number-pad.html?lastPage=true&postSubmitted=true) and I'm using his code but modified it a bit to only append the decimal and image of the decimal to the last two fields of my total five fields.
Here is my code which is showing the decimal image and appending it to the input:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
// We need to access the dot Button declared in the Delegate.
helloAppDelegate *appDelegate = (helloAppDelegate *)[[UIApplication sharedApplication] delegate];
// Only if we are editing within the Number Pad Text Field do we want the dot.
if (textField == txtUserName4) {
// Show the Dot.
appDelegate.dot.hidden = NO;
}
else if (textField == txtUserName5) {
// Show the Dot.
appDelegate.dot.hidden = NO;
}
else {
// Otherwise, Hide the Dot.
appDelegate.dot.hidden = YES;
}
}
- (void)addDecimal:(NSNotification *)notification {
// Apend the Decimal to the TextField.
if (txtUserName4.editing) {
txtUserName4.text = [txtUserName4.text stringByAppendingString:#"."];
}
else if (txtUserName5.editing) {
txtUserName5.text = [txtUserName5.text stringByAppendingString:#"."];
}
here is a video of what's happening (http://screencast.com/t/OTNhODRiYjAt). The decimal isn't showing unless I bring up the alert error, and then it shows correctly for both the fields.
SO, I turned off the field validation and - shocking - the decimal shows on the last two fields (http://screencast.com/t/ZmQyOTc1MT). So it must not be the code showing the decimals but the validation I have.
here is the validation I have. I'm thinking I'm dropping the ball with the text field being nil or being first responder?
- (void)textFieldDidEndEditing:(UITextField *)textField
{
if (textField == txtUserName)
{
NSString *userNameOne = txtUserName.text;
double numOne = [userNameOne doubleValue];
if(numOne < 30 || numOne > 80)
{
//show alert
//release alert
//if there is alert then clear out the field and make that the FR
[txtUserName becomeFirstResponder];
txtUserName.text = nil;
}
else
{
[txtUserName2 becomeFirstResponder];
}
}
else if (textField == txtUserName2)
{
NSString *userNameThree = txtUserName2.text;
float numTwo = [userNameThree doubleValue];
if (numTwo < 20 || numTwo > 32)
{
//show alert
//release alert
//if there is alert then clear out the field and make that the FR
[txtUserName2 becomeFirstResponder];
txtUserName2.text = nil;
}
else
{
[txtUserName3 becomeFirstResponder];
}
}
else if (textField == txtUserName3)
{
NSString *userNameThree = txtUserName3.text;
float numThree = [userNameThree doubleValue];
if (numThree < 475 || numThree > 650)
{
//show alert
//release alert
//if there is alert then clear out the field and make that the FR
[txtUserName3 becomeFirstResponder];
txtUserName3.text = nil;
}
else
{
[txtUserName4 becomeFirstResponder];
}
}
else if (textField == txtUserName4)
{
NSString *userNameFour = txtUserName4.text;
double numFour = [userNameFour doubleValue];
if (numFour < 0.5 || numFour > 3.00)
{
//show alert
//release alert
//if there is alert then clear out the field and make that the FR
[txtUserName4 becomeFirstResponder];
txtUserName4.text = nil;
}
else
{
[txtUserName5 becomeFirstResponder];
}
}
else if (textField == txtUserName5)
{
NSString *userNameFive = txtUserName5.text;
double numFive = [userNameFive doubleValue];
if (numFive > 0.80)
{
//show alert
//release alert
//if there is alert then clear out the field and make that the FR
[txtUserName5 becomeFirstResponder];
txtUserName5.text = nil;
}
else
{
[txtUserName5 resignFirstResponder];
}
}
}
I'm really stumped but at least figured out it's something with my validation mixing things up...
EDIT:
I found out if I comment out the else that makes the next field the first responder, then everything works as it should.
With that said, does removing the else really hurt anything in my validation? This entire validation was made with the idea of using the 'done' and 'next' buttons back when I was using the basic keyboard. Now, I'm seeing that my entire validation code is lacking a bit :)
Most likely when you call -becomeFirstResponder, the keyboard is getting redrawn, which likely is pushing the keyboard view above your magical "dot" view that is supposed to be floating on top. You probably need to call -bringSubviewToFront: with your "dot" view whenever you switch first responder.
Related
I am adding this Method to my code to format the textfield. I am using the code below to try and add the method, but it not working, what am I doing wrong?
.h file
NSString* phone_;
UITextField* phoneFieldTextField;
#property (nonatomic,copy) NSString* phone;
.m file
#synthesize phone = phone_;
ViewDidLoad{
self.phone = #"";
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
// Make cell unselectable and set font.
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.font = [UIFont fontWithName:#"ArialMT" size:13];
if (indexPath.section == 0) {
UITextField* tf = nil;
switch ( indexPath.row ) {
case 3: {
cell.textLabel.text = #"Phone" ;
tf = phoneFieldTextField = [self makeTextField:self.phone placeholder:#"xxx-xxx-xxxx"];
phoneFieldTextField.keyboardType = UIKeyboardTypePhonePad;
[self formatPhoneNumber:phoneFieldTextField.text deleteLastChar:YES];
[cell addSubview:phoneFieldTextField];
break ;
}
// Textfield dimensions
tf.frame = CGRectMake(120, 12, 170, 30);
// Workaround to dismiss keyboard when Done/Return is tapped
[tf addTarget:self action:#selector(textFieldFinished:) forControlEvents:UIControlEventEditingDidEndOnExit];
}
}
// Textfield value changed, store the new value.
- (void)textFieldDidEndEditing:(UITextField *)textField {
//Section 1.
if ( textField == nameFieldTextField ) {
self.name = textField.text ;
} else if ( textField == addressFieldTextField ) {
self.address = textField.text ;
} else if ( textField == emailFieldTextField ) {
self.email = textField.text ;
} else if ( textField == phoneFieldTextField ) {
self.phone = textField.text ;
}else if ( textField == dateOfBirthTextField ) {
self.dateOfBirth = textField.text ;
}
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString* totalString = [NSString stringWithFormat:#"%#%#",textField.text,string];
// if it's the phone number textfield format it.
if(textField.tag == 10 ) {
if (range.length == 1) {
// Delete button was hit.. so tell the method to delete the last char.
textField.text = [self formatPhoneNumber:totalString deleteLastChar:YES];
} else {
textField.text = [self formatPhoneNumber:totalString deleteLastChar:NO ];
}
return false;
}
return YES;
NSLog(#"Testing should change character in range");
}
-(NSString*) formatPhoneNumber:(NSString*) simpleNumber deleteLastChar:(BOOL)deleteLastChar {
if(simpleNumber.length == 0) return #"";
// use regex to remove non-digits(including spaces) so we are left with just the numbers
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[\\s-\\(\\)]" options:NSRegularExpressionCaseInsensitive error:&error];
simpleNumber = [regex stringByReplacingMatchesInString:simpleNumber options:0 range:NSMakeRange(0, [simpleNumber length]) withTemplate:#""];
// check if the number is to long
if(simpleNumber.length>10) {
// remove last extra chars.
simpleNumber = [simpleNumber substringToIndex:10];
}
if(deleteLastChar) {
// should we delete the last digit?
simpleNumber = [simpleNumber substringToIndex:[simpleNumber length] - 1];
}
// 123 456 7890
// format the number.. if it's less then 7 digits.. then use this regex.
if(simpleNumber.length<7)
simpleNumber = [simpleNumber stringByReplacingOccurrencesOfString:#"(\\d{3})(\\d+)"
withString:#"($1) $2"
options:NSRegularExpressionSearch
range:NSMakeRange(0, [simpleNumber length])];
else // else do this one..
simpleNumber = [simpleNumber stringByReplacingOccurrencesOfString:#"(\\d{3})(\\d{3})(\\d+)"
withString:#"($1) $2-$3"
options:NSRegularExpressionSearch
range:NSMakeRange(0, [simpleNumber length])];
if (simpleNumber.length == 10 && deleteLastChar == NO) { [self resignFirstResponder];}
return simpleNumber;
NSLog(#"Testing format phone number");
}
#pragma mark - TextField
-(UITextField*) makeTextField: (NSString*)text
placeholder: (NSString*)placeholder {
UITextField *tf = [[UITextField alloc] init];
tf.placeholder = placeholder;
tf.text = text ;
tf.autocorrectionType = UITextAutocorrectionTypeNo ;
tf.autocapitalizationType = UITextAutocapitalizationTypeNone;
tf.adjustsFontSizeToFitWidth = YES;
tf.returnKeyType = UIReturnKeyDone;
tf.textColor = [UIColor colorWithRed:56.0f/255.0f green:84.0f/255.0f blue:135.0f/255.0f alpha:1.0f];
return tf ;
}
The method you are using:
-(NSString*) formatPhoneNumber:(NSString*) simpleNumber deleteLastChar:(BOOL)deleteLastChar
Returns an NSString Object. In your case you are calling the method correctly but you are not setting the Returned NSString object to anything. It is simply hanging there. You need to set the phoneFieldTextField to the formatted text like so:
phoneFieldTextField.text = [self formatPhoneNumber:phoneFieldTextField.text deleteLastChar:YES];
NOTE - If you want to learn more about return methods then read the following:
If you noticed some most methods are of the void type. You know this when you see a method like this:
- (void)someMethod {
int x = 10;
}
What void means is that the someMethod does not return anything to you. It simply executes the code within the method. Now methods than return an object or some other data type look like this:
- (int)returnSomething {
int x = 10;
return x;
}
First thing you will notice is the return type is no longer void, it is an int. This means the method will return an integer type. In this case the code executes and you are returned the value of x.
This is just the start of the topic of return methods but hopefully it makes things a bit clearer for you.
First off you need to tell us What is not working we don't have your app and all your code. You need to explain what is working and what is not working exactly. It took longer then necessary to figure out that your question is why is textField:shouldChangeCharactersInRange: not working. Did you set a breakpoint in the function to see what it was doing. Was it not being called?
That said your bug is that textField:shouldChangeCharactersInRange: is using tags to identify text fields but the rest of the code is using pointers
// if it's the phone number textfield format it.
- if(textField.tag == 10 ) {
+ if(textField.tag == phoneFieldTextField ) {
Also you didn't include the code for makeTextField:placeholder: There could be issues in it too. Compare your code to the makeTextField:placeholder: in my sample.
I created a sample project on GitHub. To fix this. I also demos a better approach to creating input forms using table views.
https://github.com/GayleDDS/TestTableViewTextField.git
Look at both diffs to see what I did to YourTableViewController.m to make things work.
https://github.com/GayleDDS/TestTableViewTextField/commit/d65a288cb4da7e1e5b05790ea23d72d472564793
https://github.com/GayleDDS/TestTableViewTextField/commit/31ecaec8c9c01204643d72d6c3ca5a4c58982099
There is a bunch of other Issues here:
You need to call [super viewDidLoad]; in your viewDidLoad method
You need to correctly indent your code (could be a cut and paste issue)
You should be using the storyboard to create your views. See the better solution tab and BetterTableViewController implementation.
Must Watch - iOS Development Videos
WWDC 2011 - Session 309 - Introducing Interface Builder Storyboarding
https://developer.apple.com/videos/wwdc/2011/?id=309
Stanford iPhone Programing Class (Winter 2013)
Coding Together: Developing Apps for iPhone and iPad
https://itunes.apple.com/us/course/coding-together-developing/id593208016
Lecture 9. Scroll View and Table View
Lecture 16. Segues and Text Fields
Looks like you are not setting the delegate <UITextFieldDelegate> in the .h file, and not assigning your textfield's delegate property to self tf.delegate = self; in order to call - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
Try that and let me know how it goes
-Good Luck!
#koray was right: you need to setup the delegate for the class. Your class should be declared as implementing the protocol UITextFieldDelegate (in addition to UITableViewDataSource, I assume)
then in your makeTextField: (NSString*)text placeholder: (NSString*)placeholder method, you need to have something like:
-(UITextField*) makeTextField: (NSString*)text
placeholder: (NSString*)placeholder {
UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(40, 0, 150, 40)];
tf.placeholder = placeholder;
// (...)
tf.delegate = self;
return tf ;
}
Then you need to setup the delegate methods correctly. In the following example, I have a nav bar, since the numbers pad doesn't have a return or a done button. I setup a button that will act as the done button (you may have another way of making the keyboard go, and switching between text fields will trigger the end of edition anyway):
- (void) textFieldDidBeginEditing:(UITextField *)textField {
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doneEditing:)];
self.navBar.topItem.rightBarButtonItem = doneBtn;
}
- (void) doneEditing:(id) sender {
if(phoneFieldTextField.isFirstResponder) {
[phoneFieldTextField resignFirstResponder];
}
// (...)
self.navBar.topItem.rightBarButtonItem = nil;
}
Then, the magic happens in the textDidEndEditing delegate method:
- (void)textFieldDidEndEditing:(UITextField *)textField {
if ( textField == phoneFieldTextField ) {
self.phone = [self formatPhoneNumber:textField.text deleteLastChar:YES] ; // convert
[phoneFieldTextField setText:self.phone]; // display
}
// (...)
}
I have a sign up page for my app. Users are prompted to enter a cell number and a four digit PIN for use in the app. There are three cell fields to help with standardization of the cell format--the first field is three digits and holds the area code, the second field is also three digits, and the last field is four. The PIN field comes next. I want the next field to become active when the user enters the correct number of digits in a given box. For example, when someone types in three digits of the area code, the cursor should progress to the next box.
I've gotten it to work so that if one continues typing the cursor will move. However, it only moves after the next digit is typed (for example, you type three digits of the area code, then type another digit, and that digit will appear in the next box along with the cursor; the cursor does not move after typing only three digits). Additionally, the method I am using appears to have a glitch that makes it impossible to edit the fields if they already have the desired number of characters.
This is the code I am using currently:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSUInteger newLength = newString.length;
if (textField.tag == 3) {
if (newLength == 4) {
[cellField2 becomeFirstResponder];
}
}
if (textField.tag == 4) {
if (newLength == 4) {
[cellField3 becomeFirstResponder];
}
}
if (textField.tag == 5) {
if (newLength == 5) {
[pinField becomeFirstResponder];
}
}
if (textField.tag == 6) {
if (newLength == 5) {
[pinField resignFirstResponder];
}
}
return YES;
}
I appreciate any help, thanks.
ETA: edited to include danh's code, which I know is more correct than what I was doing. However, my cursor problem remains.
Note that you don't need to use tag's since you have them all in outlets so you could just use: if (textField == cellField1) {, or even better: if (textField == self.cellField1) {. This also makes it easier to follow your code and identify which textField that you are operating on.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSUInteger newLength = newString.length;
if (textField == self.cellField1) {
if (newLength == 3) {
[cellField1 setText:newString];
[cellField2 becomeFirstResponder];
return NO; // NO because we already updated the text.
}
}
if (textField == self.cellField2) {
if (newLength == 3) {
[cellField2 setText:newString];
[cellField3 becomeFirstResponder];
return NO;
}
}
if (textField == self.cellField3) {
if (newLength == 4) {
[cellField3 setText:newString];
[pinField becomeFirstResponder];
return NO;
}
}
if (textField == pinField) {
if (newLength == 5) {
[pinField resignFirstResponder];
return YES;
}
}
return YES;
}
A few things:
newLength needs first to have the the new string, this should solve the counting problem:
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSUInteger newLength = newString.length;
Next, you can just send becomeFirstResponder. No need to send resign since it's implicit in the become.
And this method should answer YES at the end.
lnafziger's answer works great! Those who are finding a swift solution, here is my swift 2.2 code.
func textField(textField: UITextField, shouldChangeCharactersInRangerange: NSRange, replacementString string: String)-> Bool
{
let newString = ((textField.text)! as NSString).stringByReplacingCharactersInRange(range, withString: string)// Convert text into NSString in order to use 'stringByReplacingCharactersInRange' function
let newLength = newString.characters.count // Count the length of 'String' type variable
if (textField == cellField1) {
if (newLength == 3) {
cellField1.text = newString
cellField2.becomeFirstResponder()
return false
}
}
if (textField == cellField2) {
if (newLength == 3) {
cellField2.text = newString
cellField3.becomeFirstResponder()
return false
}
}
if (textField == cellField3) {
if (newLength == 4) {
cellField3.text = newString
pinField.becomeFirstResponder()
return false
}
}
if (textField == pinField) {
if (newLength == 5) {
pinField.resignFirstResponder()
return true
}
}
return true
}
I have an IBAction that is called when someone is done entering text in a field. I then validate the input. If I have determined there is an error, I display a message and want the user to enter into that same field again. Rather than make them select the text field to bring the keyboard up (which works fine) I want to just leave the keyboard displayed.
I am doing [SymbolEntered becomeFirstResponder]; as the last statement in my IBAction, but the keyboard still goes away. Am I putting that in the wrong place? Any help would be appreciated. Thanks.
- (IBAction)textFieldDoneEditing:(id)sender {
DebugMsg.text = nil;
DebugMsg2.text = nil;
DebugMsg3.text = nil;
NSLog (#"done editing");
NSLog (#"%#", SymbolEntered.text);
if ([SymbolEntered.text isEqualToString:nil])
{
Result.textColor = [UIColor redColor];
Result.text = #"You must enter a symbol!";
[SymbolEntered becomeFirstResponder];
}
else
{
if ([SymbolEntered.text isEqualToString:
[NSString stringWithCString:elements_table2[el_tbl_idx-1].element_symbol]])
{
correct_count++;
Result.textColor = [UIColor greenColor];
Result.text = #"Correct!";
Score.hidden = FALSE;
Score.text = [NSString stringWithFormat:#"Score: %d out of %d - %d Percent", correct_count, el_count+1,
(correct_count*100)/(el_count+1)];
GetNextElementButton.hidden = FALSE;
SymbolEntered.enabled = FALSE;
el_count++;
attempts = max_tries + 1;
}
else
{
Score.hidden = TRUE;
Result.textColor = [UIColor redColor];
if (attempts < max_tries)
{
if (attempts+1 == max_tries)
{
Result.text = #"Sorry, one more try -";
}
else
{
Result.text = #"Sorry, try again - ";
}
GetNextElementButton.hidden = TRUE;
attempts++;
}
else
{
Result.text = [[NSString alloc] initWithFormat: #"Sorry. The correct answer is %#",
[NSString stringWithCString:elements_table2[el_tbl_idx-1].element_symbol]];
Score.hidden = FALSE;
Score.text = [NSString stringWithFormat:#"Score: %d out of %d - %d Percent", correct_count, el_count+1, (correct_count*100)/(el_count+1)];
GetNextElementButton.hidden = FALSE;
SymbolEntered.enabled = FALSE;
el_count++;
}
}
}
[SymbolEntered becomeFirstResponder];
NSLog (#"end of textfieldoneediting");
}
You can do your validation in the UITextField textFieldShouldEndEditing: delegate method instead. If you return NO from that callback, the text field will remain first responder and the keyboard won't go away. (You'll have to make your controller object the text field's delegate if it isn't already, of course.)
Try calling the [textField becomeFirstResponder] sometime later? Also make sure the UITextField pointer is not nil or something. For more help please show some of your code, it's very hard to tell where the problem is like this.
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
Try This it will resign the keyboard.
I have 10 textfields, each of which could hold at most one character. When I enter a character in the first textfield, the focus should automatically move to the next textfield and so on. That is, as soon as the first character is entered in a textfield, the focus should shift to the next. That is, the next textfield should become the first responder. I have written the below code, used the textfield delegate method.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *myCharSet = [NSCharacterSet characterSetWithCharactersInString:#"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"];
for (int i = 0; i < [string length]; i++) {
unichar c = [string characterAtIndex:i];
if([myCharSet characterIsMember:c])
{
int previousTag = textField.tag;
if([textField.text length] > 0)
{
if((previousTag == 9) && ([textField10.text length] >0))
{
return NO;
}
UITextField *tempField=(UITextField *)[self.view viewWithTag:previousTag+1];
if([tempField.text length] > 0){
[tempField resignFirstResponder];
return NO;
}
[tempField becomeFirstResponder];
return YES;
}
}
else{
return NO;
}
}
return YES;
}
But I am not getting the desired results. When I type a character its entered in the first textfield, but the focus is not shifting to the next, though when I type the 2nd character, it is entered in the next textfield.
Similarly, I need to write a delete function such that when I delete a textfield, the focus automatically shifts to the previous textfield.
Any answers will be appreciated. Thanks.
You can always return NO and change the textField text manually. I guess what you need is something like this.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *myCharSet = [NSCharacterSet characterSetWithCharactersInString:#"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"];
int previousTag = textField.tag;
if ([string isEqualToString:#""]) {//backspace button
if (previousTag==0) {//added to prevent crashing in first tf
return YES;
}
UITextField *tempField2=(UITextField *)[self.view viewWithTag:previousTag-1];
textField.text=string;
[tempField2 becomeFirstResponder];
return NO;
}
for (int i = 0; i < [string length]; i++) {
unichar c = [string characterAtIndex:i];
if([myCharSet characterIsMember:c])
{
if((previousTag == 9) && ([textField10.text length] >0))
{
return NO;
}
UITextField *tempField=(UITextField *)[self.view viewWithTag:previousTag+1];
if([tempField.text length] > 0)
{
textField.text=string;
[tempField resignFirstResponder];
return NO;
}
textField.text=string;
[tempField becomeFirstResponder];
return NO;
}
else{
return NO;
}
}
return YES;
}
-shouldChangeCharactersInRange gets called before text field actually changes its text. So you will be getting the old value in the string. Add the line at the beginning of your method. It should fix your problem.
string = [textField.text stringByReplacingCharactersInRange:range withString:string];
-(IBAction) change {
self.imageView.animationImages = myImages;
self.imageView.animationDuration = 2;
if(self.imageView.isAnimating == NO){
[self.imageView startAnimating];
NSLog(#"if bool = %d", self.imageView.isAnimating);
}
else {
self.imageView stopAnimating];
NSLog(#"else bool = %d", self.imageView.isAnimating);
}
}
hello, i'm studying iOS programming.
but i have a question.
i have a button and when i click the button, then this method will be called.
first i click the button, then this code will start the if statement. that's what i want.
i click the button again, i think that will execute the else statement.
but it always execute the if statement only.
why is that?
i really don't know why is that. please help me
I think setting the properties like animationImages or animationDuration will stop the animation, so that by clicking, you every time stop and then just after (re)start it in the if part. Try setting these two properties outside the action method you wrote, and just let the if/else sequence.
-(IBAction) change {
// set these two anywhere else
//self.imageView.animationImages = myImages;
//self.imageView.animationDuration = 2;
if(self.imageView.isAnimating == NO){
[self.imageView startAnimating];
NSLog(#"if bool = %d", self.imageView.isAnimating);
}
else {
self.imageView stopAnimating];
NSLog(#"else bool = %d", self.imageView.isAnimating);
}
}