4

I've used the code from How to move content of UIViewController upwards as Keypad appears using Swift trying to prevent the keyboard from covering my view.

Somehow I can't get it to work (mainly because of my n00b programming "skills") This is the error I got: [NSObject: AnyObject] does not have a member named 'valueForKey' on this line of code: let s:NSValue = sender.userInfo.valueForKey(UIKeyboardFrameBeginUserInfoKey) as NSValue;

I guess I'll have to create a IBAction of some sort, but nothing I try works. What do I have to do to get the code to work? And why do I have to do it? What does NSObject do?

here's the code:

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self);
}

func keyboardWillShow(sender: NSNotification) {
    let s:NSValue = sender.userInfo.valueForKey(UIKeyboardFrameEndUserInfoKey) as NSValue;
    let rect :CGRect = s.CGRectValue();
    var frame = self.textField.frame;
    frame.origin.y = frame.origin.y - rect.height;
    self.textField.frame = frame;
}

func keyboardWillHide(sender: NSNotification) {
    let s:NSValue = sender.userInfo.valueForKey(UIKeyboardFrameBeginUserInfoKey) as NSValue;
    let rect :CGRect = s.CGRectValue();
    var frame = self.textField.frame;
    frame.origin.y = frame.origin.y + rect.height;
    self.textField.frame = frame;
}
Community
  • 1
  • 1
etimm
  • 121
  • 3
  • 13

1 Answers1

3

You have to cast userInfo to NSDictionary Replace above fucntions with below one

func keyboardWillShow(sender: NSNotification) {
    let dict:NSDictionary = sender.userInfo as NSDictionary
    let s:NSValue = dict.valueForKey(UIKeyboardFrameEndUserInfoKey) as NSValue;
    let rect :CGRect = s.CGRectValue();
    var frame = self.textField.frame;
    frame.origin.y = frame.origin.y - rect.height;
    self.textField.frame = frame;
}

func keyboardWillHide(sender: NSNotification) {
    let dict:NSDictionary = sender.userInfo as NSDictionary
    let s:NSValue = dict.valueForKey(UIKeyboardFrameBeginUserInfoKey) as NSValue;
    let rect :CGRect = s.CGRectValue();
    var frame = self.textField.frame;
    frame.origin.y = frame.origin.y + rect.height;
    self.textField.frame = frame;
}

Edit

//Add this above viewDidLoad
    var selecteTextFieldOriginalY:CGFloat = 0.0;

//write in viewDidLoad
    override func viewDidLoad() {
        super.viewDidLoad()
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardDidShowNotification, object: nil);
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardDidHideNotification, object: nil);
    }

//Replace these functions
    func keyboardWillShow(sender: NSNotification) {
        let dict:NSDictionary = sender.userInfo as NSDictionary
        let s:NSValue = dict.valueForKey(UIKeyboardFrameEndUserInfoKey) as NSValue;
        let rect :CGRect = s.CGRectValue();

        var frame = self.textField.frame;
        selecteTextFieldOriginalY = frame.origin.y;

//Adjust 80 according to your need actually if is for padding and quickTypeView
        var offset = (rect.height - ((self.view.frame.height - self.textField.frame.origin.y)+self.textField.frame.size.height))+80;
        print(offset)
        frame.origin.y = offset>0 ? frame.origin.y - offset : frame.origin.y ;
        UIView.animateWithDuration(0.3, animations:{
            self.textField.frame = frame;

            }
        )
    }

    func keyboardWillHide(sender: NSNotification) {
        let dict:NSDictionary = sender.userInfo as NSDictionary
        let s:NSValue = dict.valueForKey(UIKeyboardFrameBeginUserInfoKey) as NSValue;
        let rect :CGRect = s.CGRectValue();
        var frame = self.textField.frame;
        frame.origin.y = selecteTextFieldOriginalY ;

        UIView.animateWithDuration(0.3, animations:{
            self.textField.frame = frame;

            })
    }
codester
  • 36,891
  • 10
  • 74
  • 72
  • I've tried using your code and nothing is happening (But I don't get any errors, so I've got that going for me) I ctrl+dragged the UITextField item to the code screen to create an IBoutled item. But when I start the app nothing is happening, the textField is still covered by the keyboard. Is there something I'm forgetting? – etimm Jul 20 '14 at 10:11
  • @etimm what do you mean by nothing is happening ?>? – codester Jul 20 '14 at 10:26
  • To be sure it wasn't caused by other code or constraints I created a new Xcode project, placed a textfield on the bottom half of the screen, ctrl+drag the textfield in the ViewController.swift (to create the IBOutlet item/thing) and pasted the code you posted into the ViewController.swift. Now when I run the program and tap on the textfield to type something, the keyboard slides up and covers the textfield. So the code isn't preventing the textfield from being covered by the keyboard. :( – etimm Jul 20 '14 at 11:44
  • @etimm edited my answer.Replace the code with new one.It will work. – codester Jul 20 '14 at 12:00
  • I got it to work! But now everything else in the view stays where it is and only the textview moves up with the keyboard (even the labels in front of the textfield stay behind). Is there a way to get everything to move up with the label? (imageview, buttons, labels and textview?) – etimm Jul 20 '14 at 12:38