I have added observers so that I can move textFields above keyboard.
Its working fine on all devices but keyboardWillAppear function is not called when running in simulator iPhone 4S (iOS 9).
This is happening when I "Connect Hardware Keyboard"
keyboardWillHide is being called instead of keyboardWillShow
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector:"keyboardWillAppear:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector:"keyboardWillDisappear:", name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWillAppear(notification: NSNotification){
// This is not called on simulator iPhone 4S(iOS 9.0)
}
func keyboardWillDisappear(notification: NSNotification){
// This is called
}
I really can't understand this behaviour. Can someone please explain the internal functionality which leads to this.
Related
I am trying to detect the orientation change in a certain ViewController. I use the notification and a custom function. With iPhone 7 (running iOS 10.2) every time the notification changes the rotated function is being called. But while using iPhone 6 (running 9.3) or iPhone 6s (running 10.0) the function is being called only once, when the screen loads, but not when I turn around the phone.
Code:
func rotated() {
if UIDevice.current.orientation.isLandscape {
print("Landscape")
} else {
print("Portrait")
}
}
override func viewDidLoad() {
super.viewDidLoad()
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
Set up the notification in the viewWillAppear function and it should work just fine. Works fine for me on devices available on the simulator. Actually the view DidLoad function is called only once when the view controller appears for the first time. Whereas the view will appear will be called everytime the view controller is about to be loaded.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
I'm stuck with problem "keyboardWillShow" fires twice, but the "keyboardWillHide" called once.
Here is an example where I'm printing the keyboard sizes as soon as "keyboardWillShow" fires.
I've also put breakpoint in "viewDidLoad" and the observer registers only once.
I've added two elements "UITextField" and "UITextView" and for both it is the same behaviour.
I'm using iOS 9.2, swift lang., xcode 7
Below my ViewController
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
print("keyboardWillShow sizes: \(keyboardSize)")
}
}
func keyboardWillHide(notification: NSNotification) {
print("HideHideHide")
}
}
UPDATE
First time it fires once with sizes:
keyboardWillShow sizes: (0.0, 568.0, 320.0, 253.0)
for the rest it twice with different sizes:(second y position is changed also the height changed)
keyboardWillShow sizes: (0.0, 568.0, 320.0, 216.0)
keyboardWillShow sizes: (0.0, 352.0, 320.0, 216.0)
Probably you subscribe to more than one UIKeyboardWillShowNotification and forgot to unsubscribe from them.
Try to add observer in viewWillAppear and remove it in viewWillDisappear.
Issue is connected to simulator
On the real device it fires once as supposed to be.
Are you only entering this ViewController or are you navigating through several ViewControllers? Right now I can't see any code to unsubscribe from the notifications which means than once you enter this ViewController again it will subscribe again (providing its viewDidLoad method runs again). Weird that only one of them fires twice though. Good practice is to subscribe and unsubscribe in the respective opposite methods. If you subscribe in ViewDidLoad then unsubscribe in deinit. If you subscribe in viewWillAppear, unsubscribe in viewWillDisappear etc.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
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)
}
Check so that deinit runs when leaving the ViewController.
I remove all added keyboards and leave only the system's , then the method will fire only one time.If add a new keyboard ,the method still fire two times. Maybe it's a system bug. System Keyboard
Are setting the Text Input Traits - Keyboard Type?
Example: If you set the Keyboard Type as "Number Pad", ideally it should call once, but it gets called twice. Please check that and be sure.
Resolution: You can maintain a bool to check if the keyboard is already up or not, and check its value while executing the selector code block.
I have developed custom keyboard. Now I want to give functionality like if some user choose color from my container app and then open my keyboard the background color of my keyboard changes to that color. How to achieve this? Which method gets called every time when some one switch to my custom keyboard so that i can write code on that method?
there is not a predefined method called, but you can set a NSNotification. In your viewdidload method insert:
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
and then add the two methods that will be called the the keyboard appears or disappears:
func keyboardWasShown(notification: NSNotification) {
print("keyboard up")
}
func keyboardWillBeHidden(notification: NSNotification) {
print("keyboard down")
}
But remember to remove the notifications in viewWillDisappear:
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardDidShowNotification, object: self.view.window)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: self.view.window)
bye.
Save the color property as hex string in UserDefaults with suite name. Then use this color in extension app's viewDidLoad method as background color.
I'm using the the NSNotificationCenter.defaultCenter().postNotificationName function with the applicationDidEnterBackground function. So first I add these to AppDelegate.swift:
func applicationDidEnterBackground(application: UIApplication) {
println("applicationDidEnterBackground")
NSNotificationCenter.defaultCenter().postNotificationName("com.test.mytest", object: self)
}
And I add these to ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "myTestFunc", name: "com.test.mytest", object: nil)
}
func myTestFunc () {
println("CALLED")
}
And up to now, everything is working fine, the console print out the right thing when I enter background:
applicationDidEnterBackground
CALLED
But after I add a new view controller in Storyboard and connect both of them using any of Segue:
And now when I run the app, after I clicked two buttons and then back to the home page, the applicationDidEnterBackground is still calling once but the NSNotificationCenter is called twice:
applicationDidEnterBackground
CALLED
CALLED
So how can I solve this weird problem?
EDIT
I've also tried this, but still same result:
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().removeObserver(self, name: "com.test.mytest", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "myTestFunc", name: "com.test.mytest", object: nil)
}
Ah, I forget the viewDidLoad is loaded twice... I solved by:
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self, name: "com.test.mytest", object: nil)
}
I have experienced the same problem. In my case solution was enabling Background Modes in project capabilities tab.
I am aware of the keyboardWillShow and the keyboardWillHide events by:
override public func viewWillAppear(animated: Bool) {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}
But with the new keyboards in iOS8 the keyboard is able to change without dismissing the keyboard and I was wondering how to call a function on keyboard size change. Anyone know? Thanks.
Edit: It is now calling on frame change but using this code:
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
NSLog("\(keyboardSize.height)")
}
It returns the old keyboard height for example when the frame changes to "224.0" it returns "253.0" as if the height has not updated by time the code is called, and when it goes have to "253.0" it returns the old height again which is "224.0"
Edit 2:
Instead of using "UIKeyboardFrameBeginUserInfoKey", I used "UIKeyboardFrameEndUserInfoKey" and it is now working.
You want UIKeyboardWillChangeFrameNotification and/or UIKeyboardDidChangeFrameNotification.
See the documentation of UIWindow for all of the keyboard related notifications.