Swift NSNotificationCenter? - ios

I'm trying to get the UITextViewTextDidChangeNotification to work. I'm new to using the NSNotificationCenter, so I'm having a hard time understanding what's going on exactly. I have a UITextView in a storyboard, and I've created an IBOutlet for it in my ViewController class and called it textView.
This is my viewDidLoad function:
override func viewDidLoad() {
super.viewDidLoad()
origin = self.view.frame.origin.y
if let field = textView{
field.placeholder = placeholder
field.layer.cornerRadius = 8
field.layer.borderWidth = 0.5
field.layer.borderColor = UIColor.grayColor().CGColor
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyPressed:"), name:UITextFieldTextDidChangeNotification, object: nil);
}
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}
The keyboard notifications work great. To my understanding, they call a function with the same name as the selector. Is that correct? Or is there something more going on here? I made a function called keyPressed that took an NSNotification as a parameter, but that function never got called whereas when I engage the keyboard, the keyboardWillShow and keyboardWillHide functions are called. Can someone explain what's going on?

Alright, so I figured out a solution. I needed to post the notification in the textViewDidChange function. I did that using this:
NSNotificationCenter.defaultCenter().postNotificationName("keyPressed", object: nil)
Then I recognized the notification in my viewDidLoad function with this:
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyPressed:"), name:"keyPressed", object: nil);
Then I made this function under my viewDidLoad function:
func keyPressed(sender: NSNotification) {
}

Related

keyboardWillShow fire twice

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.

UIKeyboardWillShowNotification selector not called but HideNotification is called

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.

Which method is called when my custom keyboard is shown on screen?

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.

Send action to first responder doesn't work if it's not Initial View Controller

I'm trying to create sliding menu similar to Code Menu in SpringApp here (see CodeViewController):
https://github.com/MengTo/Spring/blob/master/SpringApp
It works just fine as long as SpringViewController is Initial View Controller.
If I create another ViewController and make it initial then minimizeView/maximizeView is never getting called:
UIApplication.sharedApplication().sendAction("minimizeView:", to: nil, from: self, forEvent: nil)
In this method "to:" is set to nil to use the first responder. So it looks like when SpringViewController stops being initial view controller it's no longer first responder.
How do I fix it to make minimizeView and maximizeView actions defined in SpringViewController always work?
I found a workaround using notification center.
In SpringViewController add:
override func viewDidLoad() {
super.viewDidLoad()
// Add observer in notification center
// It receives notifications from menu
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "minimizeView:",
name: "minimizeView",
object: nil)
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "maximizeView:",
name: "maximizeView",
object: nil)
}
In OptionsViewController:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(true)
// skipped ...
// Post notification
NSNotificationCenter.defaultCenter().postNotificationName("minimizeView", object: nil)
}
#IBAction func closeButtonPressed(sender: AnyObject) {
// skipped...
// Post notification
NSNotificationCenter.defaultCenter().postNotificationName("maximizeView", object: nil)
// skipped...
}
This makes maximizeView and minimizeView work properly. I wonder if the approach with first responder is better.
You need this for view controllers to be able to receive actions:
- (BOOL)canBecomeFirstResponder {
return YES;
}

Keyboard size changed event in swift?

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.

Resources