How to know which UITextField is responding? - ios

In the UIViewController I add itself as observer:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
......
}
- (void)keyboardWillShow:(NSNotification *)notification {
NSDictionary *userInfo = [notification userInfo];
NSValue* aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [aValue CGRectValue];
if (textField1.isFirstResponder) {
NSLog(#"I am here1");
}
if (textField2.isFirstResponder) {
NSLog(#"I am here2");
}
........
}
I also create five UITextField in the controller. My problem is how to know which textField is called. I try the method to find out whose "isFirstResponder" have change , but it is not working.

erm... why don't you use -textFieldDidBeginEditing: of UITextFieldDelegate
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
NSLog(#"%#",textField);
}

Use the tag property!! When you create your Textfield set their tags (to some textfield-specific number), and when you get the notification, simply check which tag they have!

Try UIKeyboardDidShowNotification instead of UIKeyboardWillShowNotification.

Related

keyboard notification not called in ios 11.3

I have keyboard notification in my App and its working fine in ios 10 but my notification method not called in ios11.3
Below is my code:
- (void)attach {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
- (void)keyboardWasShown:(NSNotification*)aNotification {
UIView* responder = [self findFirstResponder];
if (responder) {
_tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(didTapAnywhere:)];
[baseView addGestureRecognizer:_tapRecognizer];
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
CGRect screenRect = [RGLayout layout].fullScreen;
CGRect frame = responder.frame ;
}
}
I have tried to find the solution and i got that the only changes in iOS11 is UIKeyboardFrameEndUserInfoKey for keyborad height.
But my problem is that my keyboardWasShown not called in ios11.3 same code is working ios 10.2
FYI: when user click on next the next textField will becomeFirstResponder.
Don't know why but the behaviour is strange the notification is calling in one screen and not in another screen.
I have solve the issue by following code:
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
if (self.nextField) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.nextField becomeFirstResponder];
[[NSNotificationCenter defaultCenter] postNotificationName: UIKeyboardDidShowNotification object:self];
});
}
else{
dispatch_async(dispatch_get_main_queue(), ^{
[textField resignFirstResponder] ;
});
}
return NO ;
}

Get Keyboard size in textFieldShouldBeginEditing delegate

I am having trouble while i am creating a messaging app, When keyboard is opened i am not sure about total size and frame for Keyboard (dictionary area is opened or not).
I want to get total size and frame in
textFieldShouldBeginEditing
delegate.
You should use the UIKeyboardWillChangeFrameNotification . Also make sure to convert the CGRect into the proper view, for landscape use.
Set NSNotificationCenter in your textFieldShouldBeginEditing
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
and write this method.
- (void)keyboardWillChange:(NSNotification *)notification {
CGRect keyboardRect = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil]; //this is it!
}
In Swift 4
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(_noti:) ), name: NSNotification.Name.UIKeyboardWillChangeFrame , object: nil)
KeyboardWillChange Method
#objc func keyboardWillChange(_noti:NSNotification)
{
let keyBoard = _noti.userInfo
let keyBoardValue = keyBoard![UIKeyboardFrameEndUserInfoKey]
let fram = keyBoardValue as? CGRect // this is frame
}
Register for UIKeyboardWillShowNotification.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
and in the selector get the keyboard frame:
- (void)keyboardWillShow:(NSNotification *)iNotification {
NSDictionary *userInfo = [iNotification userInfo];
NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [aValue CGRectValue];
}
I have faced this problem and solved by using notification observer on keyboard.
//set observer in textFieldShouldBeginEditing like
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myNotificationMethod:) name:UIKeyboardWillChangeFrameNotification object:nil];
return YES;
}
// method implementation
- (void)myNotificationMethod:(NSNotification*)notification
{
NSDictionary* keyboardInfo = [notification userInfo];
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
NSLog(#"%#",keyboardFrameBegin);
NSLog(#"%f",keyboardFrameBeginRect.size.height);
}
//remove observer
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{
[[NSNotificationCenter defaultCenter ]removeObserver:self];
return YES;
}

iOS Keyboard show event handling

I am working on a chat app wherein I have a textview (not textfield) and when I click on it, the keyboard should show and everything should move up.
Till now, I have managed to shift the frame of the table view and textview up and show the keyboard using the below code.
- (void)keyboardWasShown:(NSNotification *)notification {
NSDictionary* info = [notification userInfo];
keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGPoint contentViewOrigin = self.contentView.frame.origin;
CGFloat contentViewHeight = self.contentView.frame.size.height;
CGRect visibleRect = self.view.frame;
visibleRect.size.height -= keyboardSize.height;
BOOL up = CGRectContainsPoint(visibleRect, contentViewOrigin);
if (!up){
self.tableView.frame = CGRectMake(self.tableView.frame.origin.x,self.tableView.frame.origin.y,self.tableView.frame.size.width,280.0f);
self.contentView.frame = CGRectOffset(self.contentView.frame, 0, 0 - keyboardSize.height);
if([self.tableView numberOfRowsInSection:0]!=0)
{
NSIndexPath* ip = [NSIndexPath indexPathForRow:[self.tableView numberOfRowsInSection:0]-1 inSection:0];
[self.tableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionBottom animated:UITableViewRowAnimationLeft];
}
}
}
- (void)keyboardWillBeHidden:(NSNotification *)notification {
self.contentView.frame = originalContentView;
self.tableView.frame = originalTable;
}
- (void)registerForKeyboardNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)deregisterFromKeyboardNotifications {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardDidHideNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
}
But when I saw how whatsapp does it, mine looked like a hack. Whatsapp's keyboard moves up together with all the elements while mine works like this: First the keyboard is shown, a notification is sent to the app, notification is received, the code calculates the height of keyboard and moves up the elements according to the height.
I have searched and found the solution that I have implemented.
Can someone help??
I use this trick a lot in my apps. You want to listen to UIKeyboardWillShowNotification and UIKeyboardWillHideNotification.
The best way to handle animation in my opinion is using autolayout. When you call [self.view layoutIfNeeded]; your views will move along with the keyboard animation. No animation block needed.
I've set up a simple project for anyone to try and see how it works!
- (void)addKeyboardNotificationsObserver {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleKeyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)handleKeyboardWillShow:(NSNotification *)paramNotification
{
NSDictionary* info = [paramNotification userInfo];
//when switching languages keyboard might change its height (emoji keyboard is higher than most keyboards).
//You can get both sizes of the previous keyboard and the new one from info dictionary.
// size of the keyb that is about to disappear
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
// size of the keyb that is about to appear
CGSize kbSizeNew = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
//make adjustments to constraints here...
//and here where's magick happen!
[self.view layoutIfNeeded];
}
- (void)handleKeyboardWillHide:(NSNotification *)paramNotification
{
//adjust constraints
[self.view layoutIfNeeded];
}
You can use UIKeyboardWillShowNotification and UIKeyboardWillHideNotification
Try TPKeyboardAvoidingScrollView from here: https://github.com/michaeltyson/TPKeyboardAvoiding (my choice)

How to pass objects between classes using NSNotificationCenter - Fail to pass objects

My code:
NSDictionary *dict = #{#"1": #"_infoView3",
#"2": [NSNumber numberWithFloat:_showSelectionView.frame.size.height]
};
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:#"UIKeyboardWillShowNotification"
object:dict];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardDidHide:)
name:#"UIKeyboardDidHideNotification"
object:dict];
and :
- (void) keyboardWillShow:(NSNotification *)note {
NSDictionary *userInfo = [note userInfo];
CGSize kbSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
// move the view up by 30 pts
CGRect frame = self.view.frame;
frame.origin.y = -kbSize.height;
[UIView animateWithDuration:0.3 animations:^{
self.view.frame = frame;
}];
}
- (void) keyboardDidHide:(NSNotification *)note {
// move the view back to the origin
CGRect frame = self.view.frame;
frame.origin.y = 0;
[UIView animateWithDuration:0.3 animations:^{
self.view.frame = frame;
}];
}
But those two methods is not working when the keyboard is showing up or hiding.
And those two methods is working if I pass object nil, instead dict.
I don't know where is the problem, please help me , Thank you.
As I can see you are trying to post object at observer side. It is quite opposite, see the example below.
Receiver class
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveNotification:)
name:#"myNotification"
object:nil];
}
- (void)receiveNotification:(NSNotification *)notification
{
if ([[notification name] isEqualToString:#"myNotification"]) {
NSDictionary *myDictionary = (NSDictionary *)notification.object;
//doSomething here.
}
}
Sender Class
- (void)sendNotification {
[[NSNotificationCenter defaultCenter] postNotificationName:#"myNotification" object:YOUR_DICTIONARY];
}
That's because the object parameter is designed to specify the particular object to observe, not for passing arbitrary data to the called selector.
From the reference:
notificationSender
The object whose notifications the observer wants
to receive; that is, only notifications sent by this sender are
delivered to the observer.
If you pass nil, the notification center doesn’t use a notification’s
sender to decide whether to deliver it to the observer.

Present ViewController modally shows weird animation

I'm trying to create a simple modal view controller that lets you edit text using a text view. However, when I present the view controller modally, it slides in from the bottom left direction instead of just sliding in from the bottom.
Here's a video of the weird effect: http://youtu.be/9M_MHA5mt1M
My controller simply watches for the keyboard to show and then resizes the text view using auto layout appropriately. Here's the code:
#import "TextPicker.h"
#interface TextPicker ()
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *keyboardHeight;
#end
#implementation TextPicker
- (id)initWithText:(NSString *)text
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
self = [storyboard instantiateViewControllerWithIdentifier:#"textPicker"];
if (self) {
self.text = text;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self observeKeyboard];
//self.textView.text = self.text;
[self.textView becomeFirstResponder];
}
- (void) viewWillDisappear:(BOOL)animated {
[self.textView resignFirstResponder];
}
- (IBAction)savePressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)cancelPressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void) dealloc {
[self stopObervingKeyboard];
}
- (void)observeKeyboard {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillChangeFrameNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)stopObervingKeyboard {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillChangeFrameNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification {
NSDictionary *info = [notification userInfo];
NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardFrame = [kbFrame CGRectValue];
self.keyboardHeight.constant = -keyboardFrame.size.height;
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
[UIView animateWithDuration:animationDuration animations:^{
[self.view layoutIfNeeded];
}];
}
- (void)keyboardWillHide:(NSNotification *)notification {
NSDictionary *info = [notification userInfo];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
self.keyboardHeight.constant = 0;
[UIView animateWithDuration:animationDuration animations:^{
[self.view layoutIfNeeded];
}];
}
- (IBAction)dismissKeyboard:(id)sender {
[self.textView resignFirstResponder];
}
#end
Your view is animating as you have asked it to by wrapping the [self.view layoutIfNeeded] call inside an animation block.
In viewDidLoad you begin observing keyboard changes, and when you detect them you animate the adjustments, this is normally correct. But then, before the view does its first layout, you show the keyboard; this results in an animation for all the views from CGRectZero to their proper sizes. And this is the effect you are seeing.
So basically you need to give the view a chance to layout before your animated layoutIfNeeded call. Probably the easiest way to do this is simply to move [self.textView becomeFirstResponder]; to either viewWillAppear: or viewDidAppear:.
*As a side note, remember to call super in appearance calls. I noticed you did not call [super viewWillDisappear];.

Resources