view frame origin y

I run the following code inside of a view controller class, and the view is supposed to shift to make way for the keyboard, but it doesn't. This worked in my other project. Any suggestions?


self.view.frame.origin.y = -offset

Answered by ShinehahGnolaum in 204672022

I got things to work by putting the statement to make the text field first responder in viewDidAppear(_:). But I decided that I won't make the text field first responder when the view appears at all so that the user will see the entire view. The user can tap on the text field when he's ready to type in it. I still haven't completely made up my mind about it. Thanks for the help. I really appreciate it.

where do you do this ? Should be in keyboardWillShow


Here is an example that works in my code :


    func keyboardWillShow(sender: NSNotification) {

          // some computation to test if keyboard should move and how much
          self.view.frame.origin.y = offSet   
    }

Alternatively, create Auto Layout constraints in Interface Builder. Have an outlet for the top constraint of your view. Update this constraint constant in keyboardWillShow and call setNeedsUpdateConstraints().

Yes. I have the code in a method that runs as notified when the keyboard shows. I noticed that when I run a code to make a text field first responder in viewDidLoad that the keyboard shows and the value of self.view.frame.origin.y gets set correctly but the view does not adjust. (I check with a print to console statement.) After the text field loses first responder and the keyboard hides, and then when the text field becomes first responder again and the keyboard shows again, this time the view adjusts according to the value of self.view.frame.origin.y.

Have you defined the observer in viewDidLoad ?


Here is an extract from one of my projects.


    func keyboardWillShow(sender: NSNotification) {
            // some computation to test if keyboard should move and how much 
                    self.view.frame.origin.y = offSet   
     }  
  
    func keyboardWillHide(sender: NSNotification) {
        self.view.frame.origin.y = 0
    }
  
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);

    }

Yes, I've added the observer. The method is called when the keyboard appears. I even printed self.view.frame.origin.y from the method and it's what it's supposed to be -- a negative value to compensate for the keyboard. The code works except when the keyboard first appears after viewDidLoad makes the text field first responder, which causes the keyboard to appear. After the first time the code runs, when it runs after that, the code has the desired effect on the view.


I would like to run the code inside the keyboardWillShow method once in viewDidLoad, but I don't know how to get the keyboard height without using the sender parameter that is passed to keyboardWillShow. Do you know how I can do that? Below is the code in keyboardWillShow that defines the variable that holds the keyboard height:



let keyboardSize = (sender.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue



Here is the entire keyboardWillShow method:



func keyboardWillShow(_ sender: Notification) {

if textFieldDataFileName.isFirstResponder {

let keyboardSize = (sender.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue

var offset = keyboardSize.height - (self.view.frame.height - textFieldDataFileName.frame.origin.y - textFieldDataFileName.frame.height)

print("\toffset: \(offset)")

if offset > keyboardSize.height {

offset = keyboardSize.height

}

self.view.frame.origin.y = -offset

print("\ty: \(self.view.frame.origin.y)")

}

}

No, I always get it as you do.


May be you can "guess" a keyboard height (say 200), may be taking the max of all possible keyboards.


Why do you need it in viewDidload ? It should be needed only when user starts typing, isn't it ?

When the view first shows, I take the user to the text field he needs to fill by making the text field first responder. I want the user to see the keyboard when the view first appears.

OK.


So what about using a "guessed" keyboard size ?

Sounds like your UIKeyboardWillShow observer is added in viewDidAppear, which is too late for your purposes because the keyboard has already been triggered into showing before viewDidAppear executes. Your view adjustment should work correctly if that observer is added in viewWillAppear. (Also remove the observer in viewDidDisappear or viewWillDisappear.)

Accepted Answer

I got things to work by putting the statement to make the text field first responder in viewDidAppear(_:). But I decided that I won't make the text field first responder when the view appears at all so that the user will see the entire view. The user can tap on the text field when he's ready to type in it. I still haven't completely made up my mind about it. Thanks for the help. I really appreciate it.

I actually added the observers in viewDidLoad(). I put a print statement in the callback method to print the view's frame origin y value and it got changed like it was supposed to in order to compensate for the keyboard appearing.


I also thought that we no longer need to remove the observers because now iOS takes care of that for us.

The way I understand it is iOS >= 9.0 will automatically remove registrations for an observing object when that object is deallocated. A view controller isn't going to be deallocated if another view controller is pushed on top of it in a navigation stack, and so the lower controller will continue to receive notifications unless its registrations are removed when it disappears from view.

What happens when the view controller is in the background and the observer hasn't been removed. Will the view controller still receive notifications? Will the callback function to that notification still run?

Yes. It would only take you a couple of minutes to set up a simple experiment to test that.

view frame origin y
 
 
Q