how to reload NSTableView data from a different ViewController - swift

I'm working on a simple notes app for macOS. I have a home page which is has a NSTableView that displays all your notes, when you click the new note button a new View appears where you can create a new note. Once you click the note it adds the new note to the database and should reload the table view data, but I need to stop the current run and run the program again to see the changes.
I used this post to achieve the same effect on iOS but it seems to not work on MacOS
So how do I adapt:
override func viewDidLoad() {
super.viewDidLoad
NotificationCenter.default.addObserver(self, selector: #selector(loadList), name: NSNotification.Name(rawValue: "load"), object: nil)
}
In the home page VC
and the line:
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
Inside of the saveNewNote IBAction to work in macOS? also are you even able to use the NotificationCenter in macOS apps or is it only on iOS?

NSNotificationCenter is part of Foundation framework, so it's definitely available on macOS.
You should be able to use it the same way you've been using it on iOS.
If you have an IBAction called saveNewNote, inside that method you can posy the notification the way you wrote.
In the view controller which owns the table, add the observer like you wrote, and reload the table...
If it doesn't work, we might need some code example of how you set it up on the Mac app the better understand what isn't working.

Related

how to refetch data that has already been fetched

My tableView uses prefetching to cache images and works perfectly when I start the app but once I close out of the app, sending it to the background (not fully shutting it down) and click the app again, the cached images are gone but because the tableView already prefetched these images prior to closing, the prefetch method is not being called on the indexPaths that were previously loaded.
Im looking for a method or logic I can code that would call the prefetching method again based off the current indexPath allowing the indexPaths that were previously loaded and then lost to be reloaded. any help would be great?
When your app enters from background to foreground, in appDelegate file inside method
func applicationDidBecomeActive(_ application: UIApplication) {
NotificationCenter.default.post(Notification.init(name: Notification.Name(rawValue: "appDidEnterForeground")))
}
Now you can set up listeners in your UIViewControllers setup code :
override func viewDidLoad() {
NotificationCenter.default.addObserver(self,
selector: #selector(self.YOUR_METHOD_NAME),
name: NSNotification.Name(rawValue: "appDidEnterForeground"),
object: nil)
}
inside your UIViewController create your custom method and check if thats get called implement your logic inside that method.
#objc func YOUR_METHOD_NAME() {
print("notification method called")
}

Detect UIViewController changed in Swift

For analytics purposes, I would like to detect whenever the top UIViewController is modified.
I don't want to use inheritance, but rather delegate some event that I can use.
I see that Firebase have some type of mechanism for that but I couldn't figure how exactly.
Something like the following will be great:
NotificationCenter.default.addObserver(self, selector: #selector(topViewModified), name: .TopViewModified, object: nil)
Thanks.

willEnterForeground notification but isBeingPresented = false

I'm trying to work out the best way to update a view when the app comes into the foreground. Originally I had assumed that viewWillAppear would do the trick, but it appears I was incorrect.
I understand from other posts the correct way to do this is with the Notification Center:
NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)`
So far so good; this allows me to work out when this happens correctly. However it's possible I may have several views in a stack and I don't want lots of updates happening unless the view is actually visible.
I thought the following code would allow me to do this:
#objc func willEnterForeground() {
if(self.isBeingPresented) {
updateView()
}
}
But unfortunately isBeingPresented is always false when the view is restoring from the background.
Does anybody have any suggestions on the best way to tell if the current view is the 'top' view in the stack?

Where is the right place to remove notification observers in Swift 2?

I have this code, taken from this answer: https://stackoverflow.com/a/29099066/406322
extension NSNotificationCenter {
func setObserver(observer: AnyObject, selector: Selector, name: String?, object: AnyObject?) {
NSNotificationCenter.defaultCenter().removeObserver(observer, name: name, object: object)
NSNotificationCenter.defaultCenter().addObserver(observer, selector: selector, name: name, object: object)
}
}
Now, in my view controller, I am setting my observers in viewDidLoad():
override func viewDidLoad() {
super.viewDidLoad()
setObservers()
}
func setObservers() {
NSNotificationCenter.defaultCenter().setObserver(self, selector: #selector(BaseController.handleComment(_:)), name: "newComment", object: nil)
}
However, even with using this extension, where the observer is removed before getting added, each time I exit the view controller, and return to it, I get multiple notifications (one extra each time).
How is this possible?
If you need this setObserver extension, you are very likely doing something wrong. You should be able to balance your registration and removal easily. If you can't, your notification management is very likely too complicated or in the wrong place.
Typically the correct place to add observations is in viewWillAppear (or viewDidAppear, either is fine), and remove them in viewDidDisappear (or viewWillDisappear). This ensures that you do not receive notifications while you are offscreen, even if the view controller still exists (which is common).
If your view controller requires that it receive notifications while it is offscreen, then you have a design problem. View controllers should only manage onscreen views. If they're doing anything else, you have put too much of the model into the controller.
As #rmaddy notes, your specific problem is likely that you have two instances of this view controller. That's may be fine or it might be a mistake (it depends on how the view controller works). But if you balance adding and removing your registration when going on and offscreen, that part will be fine.

change UIButtonOutlet Image from AppDelegate

I would like to let the user know when new content is available via the image of a button. Take snapchat for instance: the user is aware of new snaps because the left button turns red (on the mainView). I would like to do the same.
I already processed the notification in the background in
didReceiveRemoteNotification. Thanks to this post, I was able to awake the app in the background when a new APN arrives.
Now I would like to update the image of a button straight from applicationWillEnterForeground. This is the only way that comes to my mind as the view is already loaded when the user clicks on the app (not the banner or the notification center).
Any help would be greatly appreciated. Thank you.
If anybody ever comes across the same problem...
Trying to interact directly with a ViewController from the AppDelegate was obviously a terrible idea. Instead I came across this post that tells me how to know when a ViewController enters the foreground. Here is #nsgulliver answer:
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector:"doYourStuff", name:
UIApplicationWillEnterForegroundNotification, object: nil)
}
func doYourStuff(){
// your code
}
Then remove the observer:
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}