Imported TPKeyboardAvoidingScrollView.h and .m files in my xcode projects and used that TPkeyboard for my UIScrollview in all classes of my project like this
TPKeyboardAvoidingScrollView *scrollView = [[TPKeyboardAvoidingScrollView alloc] init];
The app is terminating and showing the error as
-[TPKeyboardAvoidingScrollView keyboardWillHide:]: message sent to deallocated
instance.
Can anyone please provide me some information.
Thanks in advance.
KeyboardWillHide function in TPKeyboardAvoidingScrollView.m:
- (void)keyboardWillHide:(NSNotification*)notification {
_keyboardRect = CGRectZero;
_keyboardVisible = NO;
// Restore dimensions to prior size
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]];
self.contentInset = _priorInset;
self.contentOffset = CGPointMake(self.contentOffset.x, 0);
[self setScrollIndicatorInsets:self.contentInset];
_priorInsetSaved = NO;
[UIView commitAnimations];
}
Related
The app I am building has a messaging/chat view controller that has a view with a textView and a button at the base of the view (tab bar is set to hidden). When the view loads, the view with those objects (the textView and the button) in it is at the base of the screen (like how it looks in the iMessage app when you go into a conversation)
Now when the textview is tapped on, obviously the keyboard moves up, and along with that I have managed to get the view to move up and sit right up on top of the keyboard (like when you go to type in a new text message).
Now what I am trying to do is get the view move up and down with the keyboard. As of right now it starts at the bottom. When keyboard goes up, that view is stuck at the bottom for a second or two and then just appears above the keyboard. Same goes for when the keyboard is dismissed.
I wish I could provide pictures but I guess my reputation is not quite cutting it
Is there a way I can match the transitions or animations of the two so they move together as if they are attached?
The view is initialized
//Create the keyboard UIView
self.keyboardView = [[UIView alloc] initWithFrame:CGRectMake(0, self.view.frame.origin.y + self.view.frame.size.height - (self.navigationController.tabBarController.tabBar.frame.size.height), self.view.frame.size.width, 50)];
Selector used to move the view
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardFrameDidChange:) name:UIKeyboardDidChangeFrameNotification object:nil];
Selector implemented
- (void)keyboardFrameDidChange:(NSNotification*)notification{
NSDictionary* info = [notification userInfo];
CGRect kKeyBoardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
[self.keyboardView setFrame:CGRectMake(0, kKeyBoardFrame.origin.y - self.keyboardView.frame.size.height, 320, self.keyboardView.frame.size.height)];
self.myScrollView.contentSize = CGSizeMake(self.view.frame.size.width, self.myTableView.frame.size.height);
}
You can do this here is the keyboard notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
keyboardWasShown
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
double duration = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
int curve = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
[UIView beginAnimations:#"foo" context:nil];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
CGRect rect=self.viewChatWindow.frame;
rect.size.height=self.viewChatWindow.frame.size.height-kbSize.height;
self.viewChatWindow.frame=rect;
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(scrollToLast)];
[UIView commitAnimations];
}
keyboardWillBeHidden
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
double duration = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
int curve = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
[UIView beginAnimations:#"foo" context:nil];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
CGRect rect=self.viewChatWindow.frame;
rect.size.height=self.view.frame.size.height-rect.origin.y;
self.viewChatWindow.frame=rect;
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(scrollToLast)];
[UIView commitAnimations];
}
Just wrap your [keyboardView setFrame:...] in an animation block. You can get the keyboard's animation duration and curve from the notification object:
NSTimeInterval duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
[UIView animateWithDuration:duration delay:0 options:curve animations:^{
self.keyboardView.frame = ...;
} completion:nil];
Using UITextFieldDelegate
This will be your flag that the keyboard is gonna show up
-(void)textFieldDidBeginEditing:(UITextField *)textField{
//Animate like slide up.
[UIView animateWithDuration:0.3
animations:^{
//Use offset rather than contentSize
scrollView.contentOffset = CGPointMake(x,y);
}];
}
When your keyboard is dismissed (resignFirstResponder)
-(void)dismissKeyboard{
[self.view endEditing:YES];
[UIView animateWithDuration:0.3
animations:^{
scrollView.contentOffset = CGPointMake(0,0);
}];
}
I'm new to iOS, i want to update the text in ViewDidLoad() function.
This is my button function, When button is clicked animation take place and also adds the value "1" to "resultText.text"
- (IBAction)oneButton1:(id)sender {
oneBtn2.userInteractionEnabled = YES;
CGRect frame = oneBtn1.frame;
CGRect frame1 = reffButton.frame;
frame.origin.x = frame1.origin.x;
frame.origin.y = frame1.origin.y;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration: 3.0];
[UIView animateWithDuration:3.0 animations:^{
[oneBtn1 setTransform:CGAffineTransformMakeScale(.4, .4)];
} completion:^(BOOL finished) {
oneBtn1.hidden = YES;
price = [resultText.text intValue];
[resultText setText:[NSString stringWithFormat:#"%i", price+1]];
}];
oneBtn1.frame = frame;
[UIView commitAnimations];
}
Problem: The above text value is 1 but in ViewDidLoad is 0 ,
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%#", resultText.text); // output is 0 instead of 1;
}
Please anyone tell me how to update the text value in ViewDidLoad function ...
ViewDidLoad calling only once when the object is creating .So you can't update the thing in ViewDidLoad.ViewDidLoad use for initialising the parameters and set the initial settings when an object creating.
This is because every time your view will load it create new object of your textField, thats why you are unable to fetch previous (because its new textField not old one).So you have to save your text some where, for example you can use NSUserDefaults
SetText
NSString *result=[NSString stringWithFormat:#"%i", price+1];
[resultText setText:];
//Also set it to NSUserDefaluts
[[NSUserDefaults standardUserDefaults] setValue:result forKey:#"key"];
[[NSUserDefaults standardUserDefaults] synchronize];
Get Text
- (void)viewDidLoad
{
[resultText setText:[[NSUserDefaults standardUserDefaults] valueForKey:#"key"]];
NSLog(#"%#", resultText.text);
}
EDIT
You can make animation afterButton click, so call this method in button click event
-(void)animateImage
{
if ([resultText.text isEqualToString:#"3"]) {
//make your animation
}
}
You can use a method to do that
- (void)updateLabel {
oneBtn2.userInteractionEnabled = YES;
CGRect frame = oneBtn1.frame;
CGRect frame1 = reffButton.frame;
frame.origin.x = frame1.origin.x;
frame.origin.y = frame1.origin.y;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration: 3.0];
[UIView animateWithDuration:3.0 animations:^{
[oneBtn1 setTransform:CGAffineTransformMakeScale(.4, .4)];
} completion:^(BOOL finished) {
oneBtn1.hidden = YES;
price = [resultText.text intValue];
[resultText setText:[NSString stringWithFormat:#"%i", price+1]];
}];
oneBtn1.frame = frame;
[UIView commitAnimations];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self updateLabel];
NSLog(#"%#", resultText.text); // output is 0 instead of 1;
}
im trying to do an animation on UIPicker where when my app runs its hidden and when the button is pressed it will appear sliding from the buttom and when i tap the button again it will slide away. well, my code does that but only just once.
it does:
first click -> show the picker, isPickerHidden = NO
second click -> hides picker, isPickerHidden = YES
third click -> does not do anything, but it returns isPickerHidden = NO
where in viewDidLoad declaration are;
and same as the fourth click it doesnt do anything but return the correct BOOL value.
isPickerHidden = YES;
[self.picker setHidden:isPickerHidden];
if(isPickerHidden == NO){
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.6];
CGRect frame = self.picker.frame;
[self.picker setFrame:CGRectOffset(frame, self.picker.frame.origin.x, self.picker.frame.origin.y)];
[UIView commitAnimations];
isPickerHidden = YES;
NSLog(#"hidden yes");
}else if(isPickerHidden == YES) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.6];
CGAffineTransform transfrom = CGAffineTransformMakeTranslation(0, -200);
self.picker.transform = transfrom;
[self.picker setHidden:NO];
[UIView commitAnimations];
NSLog(#"hidden no ");
isPickerHidden = NO;
}
i would like to know on whats the problem i am facing, and what am i missing. thanx
add some logging for the frame and picker to see what is happening...
NSLog(#"picker: %.0f, %.0f, %.0f, %.0f", self.picker.frame.origin.x, self.picker.frame.origin.y, self.picker.frame.size.width, self.picker.frame.size.height);
thanx NS bro for the reply but i did a different approach now instead of offsetting the points from the original one i used CGRectMake, i did this
if(isPickerHidden == NO) {
CGRect frame = self.picker.frame;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.6];
[self.picker setFrame:CGRectMake(frame.origin.x, frame.origin.y + 216, frame.size.width, frame.size.height)];
[UIView commitAnimations];
isPickerHidden = YES;
} else if (isPickerHidden == YES) {
CGRect frame = self.picker.frame;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.6];
[self.picker setFrame:CGRectMake(frame.origin.x, frame.origin.y - 216, frame.size.width, frame.size.height)];
[UIView commitAnimations];
isPickerHidden = NO;
}
both the sliding down and sliding up are doing well animated in the same manner. but now the problem is i wanted to make the UIPicker disappear on app load so in the viewDidLoad i did try to use the [self.picker setHidden:YES]; but the frames i made using CGRect dont appear when i press the button and i also tried alpha still nop.
i did also put in the body of the if-else statement the setHidden to yes and to know with respect to their values.
would like to know what im missing now.
I got the following code:
- (void) hide_waiting_activity
{
[UIView beginAnimations:nil context:NULL]; {
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:.5];
self.waiting_view.alpha = 0;
self.waiting_label.alpha = 0;
self.activity_indicator.alpha = 0;
} [UIView commitAnimations];
}
The problem: It crashes sometimes and sometimes not. If it crashes the console output looks something like this:
2013-02-07 18:16:21.658 driver[5912:907]
-[NSISRestrictedToNonNegativeVariable count]: unrecognized selector sent to instance 0x1dd3aea0 2013-02-07 18:16:21.679 driver[5912:907]
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:
'-[NSISRestrictedToNonNegativeVariable count]: unrecognized selector
sent to instance 0x1dd3aea0'
* First throw call stack: (0x342e03e7 0x3bfd1963 0x342e3f31 0x342e264d 0x3423a208 0x34c90d5b 0x34c9a6c3 0x34c9a56f 0x34c9a781
0x34c9acf1 0x34c99d6b 0x34c9ac31 0x34c92393 0x34c94f01 0x34c95ed7
0x34c9ecab 0x36527519 0x36527689 0x365277ab 0x3652791f 0x36527acf
0x34c95997 0x36527a41 0x3652aad1 0x3652d0d9 0x3652cfe3 0x34226acd
0x3652cf97 0x34226acd 0x3652cf97 0x34226acd 0x3652cf97 0x34226acd
0x3652cf97 0x34226acd 0x3652cf97 0x34226acd 0x3652cf97 0x34226acd
0x3652cf97 0x34226acd 0x3652cf97 0x34c95997 0x36526f3d 0x361623dd
0x35e9e513 0x35e9e0b5 0x35e9efd9 0x35e9e9c3 0x35e9e7d5 0x35e9e639
0x342b5941 0x342b3c39 0x342b3f93 0x3422723d 0x342270c9 0x37e0533b
0x361432b9 0xd3871 0xc29d8) libc++abi.dylib: terminate called throwing
an exception
the corresponding stacktrace looks like this:
or something like this:
driver(5930,0x3df85b78) malloc: * error for object 0x1e565990:
pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug (lldb)
Then the stacktrace looks like
I'm completely clueless. Has anybody got an idea? I'm using ios 6.1.
Update:
Commenting the inner nested brackets does not change anything:
[UIView beginAnimations:nil context:NULL]; {
//[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
//[UIView setAnimationDuration:.5];
self.waiting_view.alpha = 0;
self.waiting_label.alpha = 0;
self.activity_indicator.alpha = 0;
} [UIView commitAnimations];
Update 2:
After removing the curly brackets the app still crashes as decribed.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:.5];
self.waiting_view.alpha = 0;
self.waiting_label.alpha = 0;
self.activity_indicator.alpha = 0;
[UIView commitAnimations];
Update 3:
This is the complete code that contain any of the affected ui elements in the hide_waiting_activity:
MainNavigationController.h
//Waiting overlay
#property (nonatomic,strong) UIActivityIndicatorView* activity_indicator;
#property (nonatomic,strong) UIImageView* waiting_view;
#property (nonatomic,strong) UILabel* waiting_label;
MainNavigationController.m
#implementation MainNavigationController
#synthesize activity_indicator;
#synthesize waiting_view;
#synthesize waiting_label;
...
- (void)viewDidLoad
{
[super viewDidLoad];
//Create a transparent waiting indicator view that is shown to the user while the app is working in background
waiting_view = [[UIImageView alloc] initWithFrame:CGRectMake( 0, 64.f /* top navigation bar is 64.f */, 320, 480 )];
[waiting_view setImage:[UIImage imageNamed:#"Main_Menu_Background.png"]];
waiting_view.backgroundColor = [UIColor clearColor];
self.activity_indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[self.activity_indicator setColor:[UIColor blackColor]];
[self.activity_indicator startAnimating];
self.activity_indicator.center = CGPointMake( 160.f, (240.f-64.f) );
[waiting_view addSubview:activity_indicator];
waiting_label = [[UILabel alloc] initWithFrame:CGRectMake( 110.f, (240.f-64.f)+30.f, 100.f, 16.f)];
waiting_label.font = [UIFont boldSystemFontOfSize:13.f];
waiting_label.textColor = [UIColor blackColor];
waiting_label.backgroundColor = [UIColor clearColor];
waiting_label.textAlignment = UITextAlignmentCenter;
waiting_label.text = NSLocalizedString(#"Please_Wait_Text", #"");
[waiting_view addSubview:waiting_label];
[self.view addSubview:waiting_view];
[self.view bringSubviewToFront:self.activity_indicator];
self.waiting_view.hidden = YES;
self.activity_indicator.hidden = YES;
...
}
- (void) show_waiting_activity
{
if( self.waiting_view.alpha == 1 && self.waiting_view.hidden == NO )
return;
self.waiting_view.hidden = NO;
self.activity_indicator.hidden = NO;
[UIView beginAnimations:nil context:NULL]; {
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:.2];
self.waiting_view.alpha = 1;
self.waiting_label.alpha = 1;
self.activity_indicator.alpha = 1;
} [UIView commitAnimations];
}
- (void) hide_waiting_activity
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:.5];
self.waiting_view.alpha = 0;
self.waiting_label.alpha = 0;
self.activity_indicator.alpha = 0;
[UIView commitAnimations];
}
I'm asking myself where in this code the ui elements could be destroyed in these .5 seconds?
The problem isn't in the code you pasted - the problem is what's happening to the views it's referencing after the animation starts (somewhere else in your code). If the animation is running for 0.5 seconds, all those views must be alive still for the next 0.5 seconds.
So, your choices for views that are not living long enough: self, self.waiting_view, self.waiting_label, self.activity_indicator.
I am making a chat that functions similar to the one below:
When a user clicks the message bubble, I need it to raise both the UITextField AND the UITableView (with the table view above the text-box of course). And similarly, when they send or retract the message, it should go back down to what it was.
I tried the solution posted here
Two notifications:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHideOrShow:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHideOrShow:) name:UIKeyboardWillShowNotification object:nil];
And the actual function:
- (void)keyboardWillHideOrShow:(NSNotification *)note
{
NSDictionary *userInfo = note.userInfo;
NSTimeInterval duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
CGRect keyboardFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect keyboardFrameForTextField = [self.myTextField.superview convertRect:keyboardFrame fromView:nil];
CGRect newTextFieldFrame = self.myTextField.frame;
newTextFieldFrame.origin.y = keyboardFrameForTextField.origin.y - newTextFieldFrame.size.height;
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
self.myTextField.frame = newTextFieldFrame;
} completion:nil];
}
But it has two problems:
I'm not sure how to raise the tableview on top of the keyboard
When the keyboard goes back down, the input box disappears entirely.
This might help....Cant take credit for it but for the life of me I cant remember where it came from...helped me with a project at one point though so this is how I used it.
This will move the view up and down when the keyboard is called/dismissed based on a BOOL value YES or NO. This way also allows you to have a bit more control over other aspects of it.
- (void) animateTextField: (UITextField*) textField up: (BOOL)up
{
const int movementDistance = 100;
const float movementDuration = 0.3f;
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
And then to implement it:
-(IBAction)goingup:(id)sender
{
//Bounces the text field up for editing
[self animateTextField: yourtextfield up: YES];}
}
-(IBAction)backdown:(id)sender
{
//Bounces it back when keyboard is dismissed
[self animateTextField: yourtextfield up: NO];
}
Connect the actions to your text fields Editing did begin and Editing did end outlets and you're set.
Hope that helps.