ios status bar with strange behaviour - ios

Using iOS-9.2 and Swift-2.1:
Getting back to my rootViewController using the below code, unfortunately leads to a very strange behaviour of the status-bar of my App !
static func returnToRootViewController(sender: AnyObject) {
let initialscene = sender.storyboard?!.instantiateInitialViewController()
for _ in sender.view!!.window!.subviews {
sender.dismissViewControllerAnimated(true, completion: nil)
}
sender.view!!.window!.rootViewController = initialscene
}
The two images below show the status bar in its normal condition (i.e. left image) and after returning by above returnToRootViewController-Code (i.e right image with strange coloring) !
Prior to applying the above code, the navigation-controller was navigated to severeal modal popovers....
Any help on this appreciated !

You're dismissing the same viewcontroller several times. Calling dismissViewController will only dismiss the one presented by the sender, not the several underneath it (I'm assuming sender is the topmost one)
From this answer, it sounds like you might be able to dismiss all of them just by dismissing the first one presented by your rootViewController: https://stackoverflow.com/a/23566262/78496

Related

iOS tableView not reloading until click, scroll, or switch tabbar items

I have this problem where (in several places) after executing an API call, the view does not refresh until a user action - like a btn click, tab bar switch, etc occurs. I have a feeling it is related to threading, but I can't seem to figure it out and I am new to iOS programming. I have tried different solutions with DispatchQueue etc, using it, and not using it. Trying to call setNeedsDisplay on the controller view. But no luck yet. The following is an example of code pulled right from one of my tab bar item view controllers:
func getEmployeeUpdates(){
self.showLoader()
APIAdaptor.shared.getEmployeeUpdates(forEmployee: Session.shared.employee, completion: {
(updates:[ScheduleUpdate]?, error:Error?) in
guard error == nil else{
DispatchQueue.main.async {
// self.resetMainScreen()
self.hideLoader();
}
return
}
DispatchQueue.main.async {
self.hideLoader();
self.ScheduleUpdates = updates!
self.tableView.reloadData();
}
})
}
func showLoader(){
NSLayoutConstraint.activate([
activityIndicator!.centerXAnchor.constraint(equalTo: self.tableView.centerXAnchor),
activityIndicator!.centerYAnchor.constraint(equalTo: self.tableView.centerYAnchor)])
activityIndicator?.startAnimating();
}
func hideLoader(){
print("Hiding");
activityIndicator?.stopAnimating()
}
I have attached two images. The first image is where the api call has finished (confirmed through testing) but the view is not refreshing. The loader is frozen. It should disappear after a call to hideLoader(). the second Image is after a click, or tab bar item switch.
I should also mention that in this example, as well as in other api calls the view will refresh eventually after completing, but only after a significant delay.
If anyone can help I would appreciate it very much!
This was a problem caused by the simulator on Xcode 10.1. If you run into this problem, try updating Xcode, or using a real device.

Ios navigation - custom back button or removing viewcontriller from stack?

I'am new to ios. I have several view controllers and I want back button to get user to level up controller. Example.
But if user comes from gameOver view, back button sent him back to gameOver and I don't want such behavior (I want user to be sent at second level (games level) controller as shown). On android I could set the pop behavior for the navigation actions with mouse very easily.
What is the correct way to do the same in ios? Or I have to create the custom back button and do everything manually?
Using Swift this can be achieved using below code:
func popToViewController(_ specificViewController: Swift.AnyClass) {
let viewControllers = self.navigationController!.viewControllers
for eachViewController in viewControllers {
if eachViewController.isKind(of: specificViewController) {
self.navigationController!.popToViewController(eachViewController, animated: true)
break;
}
}
}
Usage:
self.popToViewController(gameLevelViewController.self)

Close a viewcontroller after a segue

What I want is to close a viewController after performing a segue so that the back button of the navigation controller on the new view doesn't go back to the view that I just closed, but it goes to the view that precedes it in the storyboard like it is the first time that it is loaded.
I already tried stuff like dismiss and so but it doesn't really work for me as it only closes the view in which the button that I pressed for performing the function is located :
#objc func goToList(){
self.dismiss(animated: true, completion: nil)
performSegue(withIdentifier: "goToList", sender: nil)
}
The navigation controller maintains a stack (array) of ViewControllers that have been opened (pushed). It also has the ability to pop these ViewControllers off the stack until it gets to a specific one.
For example, if you wished to return to a previous view controller of type MyInitialVC then you'd want to search through the stack until you found that type of VC, and then pop to it:
let targetVC = navigationController?.viewControllers.first(where: {$0 is MyInitialVC})
if let targetVC = targetVC {
navigationController?.popToViewController(targetVC, animated: true)
}
NB. written from memory without XCode, so you may need to correct minor typos
You can use unwind segue to get back to each viewController that you want.
Read more here:
Unwind Segues Step-by-Step (and 4 Reasons to Use Them)

Missing Navigation's or Back Button's Title When Push ViewControllers in Succession

I have a problem on UINavigationController when pushing view controllers in succession.
For information, I use XCode 7.0, build targeting iOS 8, and the app running on Simulator 9.0.
Here's the view when user manually tap the tableview's cell:
As shown on the above screenshots, the navigation's and back button's title were rendered normally.
But when I did this programmatically, like this (stack is array of UIViewController):
for controller in stack {
self.mainNavController.pushViewController(controller, animated: false)
}
or using delay on 0.0 second like this:
for controller in stack {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64((0.0 * Float(NSEC_PER_SEC)))), dispatch_get_main_queue(), {
self.mainNavController.pushViewController(controller, animated: false)
})
}
It will show the final result like this (left is w/o delay, right is w/ delay):
Notice the missing navigation title on the left screenshot (w/o delay) and missing back button title on the right screenshot (w/ delay).
This issue has confuse me for days. Any idea of why this is happening? Does anyone know how to fix this? Or at least, work around this issue?
Thanks in advance.
This is what I have done in the past. You might find it helpful:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let myBackButton = UIBarButtonItem()
myBackButton.title = "This is my back button"
navigationItem.backBarButtonItem = myBackButton
}
This is happening because the intermediate view controllers are not being told to load so it isn't able to load things properly like the correct messaging for the back button. For any intermediate viewControllers, call loadViewIfNeeded() and then the upper view controllers can get all the required info from them.

Swift: Buggy Navigation Bar Behavior With popViewControllerAnimated

I want to use a push segue to edit an "entry" that is otherwise added via a present modally segue. It doesn't dismiss using the normal dismissViewControllerAnimated method when pressing cancel. Because of this I had to combine the popViewControllerAnimated method at the same time, so that depending on whether they click cancel when editing an entry or adding it, it will try both.
Both are done via NSNotifcation, because of objects I need to carry back from the last viewcontroller to the first:
func cancel(notification: NSNotification){
println("Cancel Executed")
let userInfo:Dictionary<String,EntryItem!> = notification.userInfo as Dictionary<String,EntryItem!>
entry = userInfo["Object"]
tableView.reloadData()
self.navigationController?.popViewControllerAnimated(true)
dismissViewControllerAnimated(true, completion: nil)
dataModel.saveEntries()
}
The problem with this is that if I go through the segues to arrive at the third view controller (in a string of 5), I cancel, and it goes back to the entries screen, but a messed up looking navigation bar takes the place of what is supposed to be there. There's no title showing either. It has a cancel button which causes a crash if you press it.
Here's what it's supposed to look like:
Here's what the popViewControllerAnimated does to it.

Resources