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

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.

Related

Why UIButton is unresponsive?

I have a UIButton on top of every other views, pushing the next screen, but it's unresponsive to tapping.
Debugging, I have noticed that the User Interaction is ON but also OFF. I mean:
When I select the button at the view hierarchy) it says is ON.
When I select the button directly at the storyboard, it says is OFF.
Take a look at the image above.
Also, the outlets are connected and the call is correct:
code
#IBAction public func onFrontPressed(_ sender: UIButton) {
let destination = OnboardingAViewController(nibName: "OnboardingAViewController", bundle: nil)
self.navigationController?.pushViewController(destination, animated: true)
}
Does anyone knows what's going on here?
Solved!
There was 1 fully transparent gradient view above the button.
When I deleted it, everything was working again.
Thanks, community!

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)

ios status bar with strange behaviour

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

navigating through desired views (while skipping some views) using UINavigationBar back button

I am using a UICollectionView to show a list of images.
1)By clicking on any cell the image and some description about it is displayed in the resulting view controller(using a push segue).
2)When i swipe from the left/right edge(using PanGesture) i need to display the details of the previous/next image in the collection view.
3)But the back button of the navigation bar has to take me back to the collection view and not to the previous displayed details (shown by the PanGesture).
I know how to get 1 and 2 done but don't have a concrete idea to get the 3rd job done.
Any help would be appreciated.
You can find your desired UIViewController in your navigation stack using for loop. Try this. This is in Swift
for (var i = 0; i < self.navigationController?.viewControllers.count; i++) {
if (self.navigationController?.viewControllers[i].isKindOfClass(YourViewController) == true) {
println("is sw \(self.navigationController!.viewControllers[i])")
(self.navigationController!.viewControllers[i] as! YourViewController)
self.navigationController?.popToViewController(self.navigationController!.viewControllers[i] as! YourViewController, animated: true)
break;
}
When you navigate from one view to another (e.g. by showing a detail view of your images one after the other, then all these views are internally piled up as a stack.
Thus, if you want to jump directly to a view somewhere in between this stack (e.g. the collection view), then you can use the Unwind Segue.
In your case it should work like this:
First, in your collection view (i.e. your back button destination) you need to implement a UIStoryboard Segue as follows
#IBAction func myGoBackPoint(segue: UIStoryboardSegue) {
println("Jump directly back here from any other view")
}
Then, in the storyboard of your detail view you ctrl-drag directly to top rightmost Exit marker and choose the previously created back button destination:
In the code of the detail view implement the "go back instruction"
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "My Unwind Segue" {
if let myUnwindSegue = segue.destinationViewController as? MyCollectionViewController {
// prepare for segue
}
}
}
Hope this helps.
Finally after researching a lot i found that using a collection view with each cell taking up the whole screen is the best way to go about solving this issue.
Thankyou

Launch Watch App into middle view

Basically, my app is laid out in the page format and I would like it to launch into the middle of the three pages. There is no way of setting a previous page segue, so I have been trying to do it in code.
I have the main view set to the first view, and I have tried a variety of methods to segue to the middle view as soon as the app is launched.
Here is the two ways I tried:
if segueCheck == true {
self.pushControllerWithName("budget", context: self)
self.presentControllerWithName("budget", context: self)
segueCheck = false
}
The first presents the view, but as a completely separate view, and the second replaces the first view with the middle view.
Does anyone know how I can launch into the middle view and allow the user to swipe left and right of it?
Thanks.
WKInterfaceController's becomeCurrentPage() should be what you're looking for.
Let's create a new class for the center view controller, CenterPageViewController, and change its initWithContext: method as follows
import WatchKit
class CenterPageViewController: WKInterfaceController {
override init(context: AnyObject?) {
super.init(context: context)
super.becomeCurrentPage()
}
}
Now let's set the Custom Class for the middle page in your storyboard to CenterPageViewController
and finally hit run.
You won't be able to get rid of the initial transition from the left page to the center page, but the app will finally begin on the middle page.
Update Swift 3.0
class CenterPageViewController: WKInterfaceController {
override init (){
super.init()
super.becomeCurrentPage()
}
}
This will works...!!!
Thanks
The new way to do this in watchOS 4 and higher is:
WKInterfaceController.reloadRootPageControllers(withNames:
["Controller1" "Controller2", "Controller3"],
contexts: [context1, context2, context3],
orientation: WKPageOrientation.horizontal,
pageIndex: 1)
Now you don't get the annoying animation when using becomeCurrentPage() when you want to start with the middle page.

Resources