change UIButtonOutlet Image from AppDelegate - swift

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

Related

Swift: View position resets when app is minimized, then brough back to foreground

I have a UIView that starts off in a random position (set up through storyboard), then finds its actual position when viewDidLoad() is called, depending on the user preferences stored in UserDefaults.
The problem is when the app is minimized, and then brought back to the foreground, the position of that UIView resets to the initial random position.
How could I prevent the app from releasing that position determined at runtime? Or do I need to re-calculate that position through a function that is triggered when the app is brought back from being inactive?
I don't think there is much use to include code for this, but the position of the UIView (named 'contextUnderscoreLine') is set in viewDidLoad() with contextUnderscoreLine.center = savedCGPoint.
I think I found a solution for this, in case someone else was going through the same issue:
Add an observer in viewDidLoad() to detect when the application is 'active'. From documentation, my understanding is that this will get called once when the app is launched, and then every time the app comes back from being in the background. So the initial formatting of the problematic UIView can be done there instead of in viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
}
#objc func applicationDidBecomeActive(notification: NSNotification) {
// Application is back in the foreground
//determine the position of the UIView here, instead of in viewDidLoad()
}
Edit
For my specific case it was better to use UIApplication.willEnterForegroundNotification instead of UIApplication.didBecomeActiveNotification. That way the changes in UIView are done before the Application is back in the foreground, and therefore you avoid the noticeable UIView jitters as the changes are made in front of the user.

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?

Swift, unable to reload chat window using JSQMessagesViewController

My app allows users to view another users info by tapping their avatar, at which they can block that user so that their message content is not visible.
What is the best way when returning to the chat view to clear the messages and reload them?
This would allow my blocking code to work on the fly. Currently it works when I dismiss the chat view and return but not when jump to another view and then back to the chat view.
Ive tried self.collectionView!.reloadData() but that does not do anything.
All you need is to implement
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.collectionView?.reloadData()
}
that is called when you come back from an already instantiated view.
Call the reloadData method after a delay.
self.performSelector(#selector(self.delayReload), withObject: nil, afterDelay: 0.1)
func delayReload() {
self.collectionView.reloadData()
}
Hope this will help you.
Sincerely,
Harri.

Segue following a change in criteria from a local notification in Swift

I have created a local notification in Swift which gives the option to end a current game without having to go back in to the app. That's all fine and works as it should. The issue I'm having is that if the user does this, I don't want them to go back to the Game view controller if that happens to be the last view that was open when the app entered the background. I would like them to go back to the app's Home view controller instead.
I expected to be able to add a perform segue to my Game view controller in the following way, should the criteria match. I tried adding it to viewDidAppear(), but it didn't work:
override func viewDidAppear(animated: Bool) {
if isThereACurrentGame() == false {
performSegueWithIdentifier("unwindToHomeScreen", sender: self)
}
}
Is this something to do with viewDidAppear() not being called when the app comes back to the foreground? If so, what might an alternative be?
P.S. My isThereACurrentGame() function works as it should, as does the performSegueWithIdentifier elsewhere in the view controller, so these aren't the cause of the problem.

Why NSNotification work slow?

I know its interesting title for my question. Sorry for that. Here is my problem;
I am doing simple login screen (with facebook frameworks). If user wants to login with his/her facebook account, firstly he/she must confirm facebook page. And then i get their email addres, name, surname..etc information of user.
After that i just ask them password for my app. This password screen is a view. and opening on main view(not as new viewcontroller. its view on main view) And after confirm facebook page then this wiew appear.
On this password view has 2 textbox and 2 button. textbox for paswword(and confirmation) and First button send request to my web service with user information. and other button is "cancel" button.
here is the problem. When user send request i create nsnotification for waiting respond. after getting respond. i want to this password view get hide.
here is the code:
#IBAction func buttonSave(sender: AnyObject) {
var myObj = connectObject()
myObj.sendRequest("http://localhost:8888/iphone/hearMe/index.php", param: "id=test123")
NSNotificationCenter.defaultCenter().addObserver(self, selector: "actOnSpecialNotification", name: "sendDataCheck", object: nil)
}
func actOnSpecialNotification() {
println("ok I got success respond from webservice")
self.viewPassword.hidden = true /*This is my view */
}
with this code. "viewPassword" view hided but not instantly. It hide after 10 or 15 seconds. How i can hide that view instantly after getting response from webservice?
It's not clear from your question whether the 10-15 seconds is between the pushing of the button and the hiding of the view, or between the printing of "ok I got…" and the hiding of the view.
If the lag is between pushing the button and calling actOnSpecialNotification(), then the above code doesn't help us. We need to know what object posts the notification sendDataCheck and why it takes so long. Maybe it just takes that long to talk to the network. Maybe it posts the notification before you start observing it. You probably want to call addObserver() before sending the request rather than after (just in case there's an async operation in there).
If the lag is between printing the "ok I go…" line and hiding the view, then the most common cause of that is that the notification was posted on a background queue. You can't interact with UIKit anywhere but the main queue, and weird lags are a common symptom when you do.
(Side note: when in doubt, use let, not var. myObj is better defined let here. This helps protect against many kinds of bugs.)