Update variables when day changes Swift [duplicate] - ios

I want my app to act when there is a change to another day.
So, in my appDelegate, I put
func applicationSignificantTimeChange(_ application: UIApplication){
//this one fires
}
and in the ViewController that should update its content I do:
override func viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(self.dayChanged(notification:)), name: Notification.Name("significantTimeChangeNotification"), object: nil)
}
and
#objc func dayChanged(notification: NSNotification){
//this one doesn't fire
}
somehow, while the func in AppDelegate is called, the observer seems to be blind for that event.
Is this syntax, or just plain misunderstanding of the mechanism?

You need to add an observer for "UIApplicationSignificantTimeChangeNotification":
NotificationCenter.default.addObserver(self, selector: #selector(dayChanged), name: UIApplicationSignificantTimeChangeNotification, object: nil)
For Swift 4.2 or later
NotificationCenter.default.addObserver(self, selector: #selector(dayChanged), name: UIApplication.significantTimeChangeNotification, object: nil)
Note: If your intent is to be notified when the day changes you can use .NSCalendarDayChanged ("NSCalendarDayChangedNotification") instead of UIApplication.significantTimeChangeNotification.
NotificationCenter.default.addObserver(self, selector: #selector(dayChanged), name: .NSCalendarDayChanged, object: nil)
And add the selector method to the view controller where you would like to monitor the day changes:
#objc func dayChanged(_ notification: Notification) {
}

Related

Notification Center Observer Selector Method does not get called

I am adding an observer on A view controller and view controller B is presenting on A.
While dismissing Controller B , I have posted the notification but It does not called the selector method added in A.
Also notification get registered first and the post method is get called. I have already checked that.
Here is the sample code:
NotificationCenter.default.addObserver(self, selector: #selector(closButtonPressed(notification:)) ,name: Notification.Name("CloseButtonPressed"), object: nil)
#objc func closButtonPressed(notification: Notification){
}
NotificationCenter.default.post(name: Notification.Name("CloseButtonPressed"), object: self)
Any help would be appreciated.
Make sure posting notification in completion handler
self?.dismiss(animated: true, completion: {
NotificationCenter.default.post(name: Notification.Name("CloseButtonPressed"),
object: self)
}
Make sure you implement Notification correctly. I recommend you to create an extension for Notification Name & make it static.
extension Notification.Name {
static let didTapCloseButton = Notification.Name("CloseButtonPressed")
}
NotificationCenter.default.addObserver(self, selector: #selector(didTapCloseButton(_:)), name: .didTapCloseButton, object: nil)
#objc func didTapCloseButton(_ sender: Notification?) {
}
NotificationCenter.default.post(name: .didTapCloseButton, object: nil)
I am not sure what's wrong with your project. To solve your problem, I create a test project and write some code like this:
//ControllerA.swift
override func viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(getNotification(notification:)), name: NSNotification.Name("CloseButtonPressed"), object: nil)
}
getNotification(notification: Notification) {
print(notification)
}
#objc func buttonAClick() {
navigationController?.present(ViewControllerB(), animated: true, completion: {
})
}
//ViewControllerB.swift
#objc func buttonClick() {
NotificationCenter.default.post(name: Notification.Name("CloseButtonPressed"), object: self)
self.dismiss(animated: true) {
}
}
As you said, I add notification in ControllerA, and present ControllerB, When ControllerB close, post notification and dismiss, console can print the notification object, so may I miss something?

iOS - NotificationCenter addObserver "UIMenuControllerWillHideMenu"

I have added notification observer for UIMenuControllerWillHideMenu but it does not call selector added/associated with notification center.
UIMenuControllerWillHideMenu is notification center identifier for UIMenuController and should be called when UIMenuController will hide. But somehow it's not working.
Here is code I've tried (Swift 3.x):
private func addMenuObserverNotification(){
NotificationCenter.default.addObserver(self, selector: #selector(self.menuControllerWillHideMenu), name: NSNotification.Name(rawValue: "UIMenuControllerWillHideMenu"), object: nil)
}
// This function should be called on 'UIMenuControllerWillHideMenu'
func menuControllerWillHideMenu() -> Void {
removeMenuObserverNotification()
}
private func removeMenuObserverNotification(){
NotificationCenter.default.removeObserver(self)
}
Unable to identify, what's wrong.
Found a solution by replacing NSNotification.Name(rawValue: "UIMenuControllerWillHideMenu") with just .UIMenuControllerWillHideMenu
private func addMenuObserverNotification(){
NotificationCenter.default.addObserver(self, selector: #selector(self.menuControllerWillHideMenu), name: .UIMenuControllerWillHideMenu), object: nil)
}
I did a mistake by adding it's initializer NSNotification.Name(rawValue: "UIMenuControllerWillHideMenu"), which may not require as NSNotificationName is typedef NSString, which directly allows an access to predefined values using .<value name>
For more details:
addObserver:selector:name:object:
NSNotificationName

How to use selector function from different class in iOS Swift, mainly for NotificationCenter

I am using Tab Bar Controller in an iOS app and I am using reachability for checking the network availability and for achieving it I am using Notifications.
The basic syntax of a notification in Swift 3 is as follows -
NotificationCenter.default.addObserver(observer: Any, selector: Selector, name: NSNotification.Name?, object: Any)
and things happen generally this way -
NotificationCenter.default.addObserver(observer: self, selector: #selector(ViewControllerName.functionName), name: NameOfTheNotification, object: nil)
What I want to do is -
I want to use a static function present in different class for selector i.e.., when this notification is generated I want to call the static function which is present in the different class.
let's say the class name is "Functions" and the name of function is "myFunction()"
in simple words what I want to do is whenever the notification is there I want to call myFunction() function from class Functions.
What I had tried
I had tried doing this but it doesn't help -
NotificationCenter.default.addObserver(observer: Functions(), selector: #selector(Functions.myFunction), name: NameOfTheNotification, object: nil)
There occurs an error and that error is as follows -
I had attached the Xcode snapshot below.
The easiest fix is to add #objc to reachabilityStatusChanged.
// ↓
#objc func reachabilityStatusChanged(notification: Notification) {
...
}
But NotificationCenter doesn't really require your class to support Objective-C. You could use the block variant of the method:
NotificationCenter.default.addObserver(forName: Notification.Name("ReachStatusChanged"), object: nil, queue: nil) { notification in
// do whatever Swift code with `notification` here.
// no need to add #objc anywhere.
reachabilityStatusChanged(notification)
}
The main problem you're experimenting here is the interoperability with obj-C.
Make sure you expose the function `reachabilityStatusChanged' to obj-C with the #objc annotation.
#objc func reachabilityStatusChanged
Also, make sure the class Functions is visible to obj-c. (Inheriting it from NSObject)
An illustration of why you have to retain Functions()
class Foo {
#objc func test() {
print("Hello")
}
}
var foo: Foo? = Foo()
let nc = NotificationCenter.default
nc.addObserver(foo!,
selector: #selector(Foo.test),
name: NSNotification.Name(rawValue: "Barrr"),
object: nil)
nc.post(name: NSNotification.Name(rawValue: "Barrr"), object: nil)
nc.post(name: NSNotification.Name(rawValue: "Barrr"), object: nil)
foo = nil
nc.post(name: NSNotification.Name(rawValue: "Barrr"), object: nil)
This will print Hello twice instead of three times because foo class was deallocated before the third call.

NotificationCenter not receiving posts

I have a class that accepts accelerometer data and posts it in a notification like so:
func notify(accel: accelPoint){
NotificationCenter.default.post(name: Notification.Name("newRawData"), object: nil)
}
And two objects set up to observe this, the first being a viewController:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(FirstViewController.newRawData), name: Notification.Name("newRawData"), object: nil)
Which calls the function:
func newRawData(notification: NSNotification){ ...
This works just fine.
The other observer is in a regular Swift class, instantiated in the app delegate. (I have tried doing this before and after creating the notifying class):
init(){
NotificationCenter.default.addObserver(self, selector: #selector(FilterManager.newRawData), name: Notification.Name("newRawData"), object: nil)
}
Which should call the function below but for some reason it does not.
#objc func newRawData(){
print("WHYYY")
}
The name this class is correct, and I have seen the the observer is being registered and the notifications are being posted so why isn't this class being notified like the other?
Also, why do I have to expose the newRawData function in the second class to objective-C but not the newRawData in the viewController class?
did you referenced FilterManager class in your AppDelegate? if not add this code in you AppDelegate class. also you can make FilterManger singleton to solve this problem.
var filterManger = FilterManager()

Pausing timer when app is in background state Swift

My ViewController.swift
func startTimer() {
timer = NSTimer().scheduleTimerWithTimerInvterval(1.0,target: self,selctor: Selector("couting"),userinfo: nil, repeats: true)
}
func pauseTimer() {
timer.invalidate()
println("pausing timer")
}
and this is appDelegate.swift
func applicateWillResignActive(application: UIApplication) {
viewController().pauseTimer()
println("closing app")
}
It is printing pausing timer and closing app but when I open again I see it never paused. How do I do it correctly?
You have to set an observer listening to when the application did enter background. Add the below line in your ViewController's viewDidLoad() method.
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("myObserverMethod:"), name:UIApplicationDidEnterBackgroundNotification, object: nil)
Add the below function to receive the notification.
func myObserverMethod(notification : NSNotification) {
println("Observer method called")
//You may call your action method here, when the application did enter background.
//ie., self.pauseTimer() in your case.
}
Happy Coding !!!
Updated Answer for Swift 5:
NotificationCenter.default.addObserver
(self,
selector: #selector(myObserverMethod),
name:UIApplication.didEnterBackgroundNotification, object: nil)
#objc func myObserverMethod() {
print("Write Your Code Here")
}
Accepted answer by #Suresh in Swift 3
Set an observer listening to when the application did enter background in your ViewController's viewDidLoad() method.
NotificationCenter.default.addObserver(self, selector: #selector(myObserverMethod), name:NSNotification.Name.UIApplicationDidEnterBackground, object: nil)
Add the below function to receive the notification.
func myObserverMethod(notification : NSNotification) {
print("Observer method called")
//You may call your action method here, when the application did enter background.
//ie., self.pauseTimer() in your case.
}
Updated Answer for Swift 4:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(myObserverMethod), name:NSNotification.Name.UIApplicationDidEnterBackground, object: nil)
}
#objc func myObserverMethod() {
// Call your action method here, when the application did enter background.
}
You are creating a new object and calling pauseTimer() on it:
viewController().pauseTimer() // This line causes issue viewController(), creates a new instance
Instead of creating new object, either you should pass that instance to AppDelegate and call pauseTimer() on existing object or Listen for UIApplicationDidEnterBackgroundNotification notification in your view controller class and pause timer from there.

Resources