UIDeviceOrientationDidChange only works with iPhone 7 - ios

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)
}

Related

iOS viewWillAppear not being called when returning from background, even with UIModalPresentationStyle.FullScreen, in iOS 13+

Why isn't iOS calling viewWillAppear when our application is returning from the background, even when I've set UIModalPresentationStyle.FullScreen?
viewWillAppear is a function that responds to a view controller's state change. Background and foreground states are different; they are done at an app level.
You can still respond app state changes by using notifications:
override func viewDidAppear(_ animated: Bool) {
// ...
NotificationCenter.default.addObserver(self, selector: #selector(didReceiveForegroundNotification), name: UIApplication.willEnterForegroundNotification, object: nil)
}
#objc func didReceiveForegroundNotification() {
// app returned from the background
}
Your view controller will listen to events until it is deallocated or removed as an observer. If you don't want to execute code when the view controller has dissappeared, you can do it on viewDidDisappear:
override func viewDidDisappear(_ animated: Bool) {
// ..
NotificationCenter.default.removeObserver(self)
}

How run code if I go to background device (when click button Home) in iOS [duplicate]

This question already has answers here:
Detect iOS app entering background
(7 answers)
Closed 3 years ago.
I have code I want it run in click button home or go to background device.
self.ref.child("khlea").child("Users").child(self.user_random!).setValue(nil)
You can do this in two ways far as i know.
1 Through Appdelegate Or SceneDelegate (for iOS13)
Write your code in applicationWillResignActive() method in appdelegate and sceneWillResignActive method in scenedelgate.
2 Through Notification Center
NotificationCenter to observe the UIApplicationWillResignActive event. This event is fired every time the application will enter the background.
func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(saveToFirebase), name: UIApplication.willResignActiveNotification, object: nil)
}
func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
#objc func saveToFirebase(){
self.ref.child("khlea").child("Users").child(self.user_random!).setValue(nil)
}
In Swift 4.1 + Closure Version
var resignObserver: NSObjectProtocol!
override func viewDidLoad() {
super.viewDidLoad()
resignObserver = NotificationCenter.default.addObserver(forName: UIApplication.willResignActiveNotification, object: nil, queue: nil) { _ in
self.ref.child("khlea").child("Users").child(self.user_random!).setValue(nil)
}
}
deinit {
NotificationCenter.default.removeObserver(resignObserver!)
}

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.

NSNotificationCenter called twice in applicationDidEnterBackground when their is two view controller?

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.

Resources