Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
134 views
in Technique[技术] by (71.8m points)

ios - Navigation Controller Loop

enter image description here

I'm making an app which has a shopping cart feature. The shopping cart VC is accessible from several VCs via a button on the navigation bar. So far I only have one Navigation Controller and as shown in the image, each VC takes me to the next one, nothing fancy. The 3rd VC (blue arrow pointing to) is a VC that shows the product/item's details and enables me to add it to the cart.

Problem comes with the Shopping Cart VC. To edit the item, I'd like to re-use the same product/item's details (blue arrow pointing to) VC I used earlier.

Right now, I don't really have an issue but I have noticed that once I created the blue segue, the Navigation Bar of the 3rd VC disappeared in the Storyboard however I was still able to see it when I ran the app.

NOTE:

  1. All the segues in the picture are "Show"
  2. The shopping cart VC doesn't have a button to show itself like the other 3 does. So technically I prevented endless/loop of the shopping cart VC - product/item details VC showing one another.

My questions are:

  1. Is it wrong to design the app that way with a VC going to another VC and that other VC can go back to the first VC? Am I going to face issues down the road, perhaps memory leaks of some sort?
  2. Is there a better way to achieve what I am trying to achieve?

If someone needs further explanation please let me know and I'll edit my question.

EDIT: To clarify, the blue segue is basically a button in a UITableView in the cart VC. If you tap that button, it should open the product/item details VC and lets you edit the item's color, etc. In the item details VC, instead of adding the item as a new item to the cart, I'd show an Edit button which would send the edit request to the API and dismiss the VC back to the shopping cart, or I could use the back button in the navigation controller to get back to the shopping cart.

EDIT2: @beshio

Thanks for the answer. However VC1 is actually my root VC where all the app starts. I didn't get why removed VCs from the Navigation Controller's stack. I would like the Back button to work as intended.

So far I have achieved what I wanted but I'm afraid that having two VCs segue-ing to each other would cause a problem. I have already disabled the Cart button in VC3 in case VC3 was presented from the Cart so loops would be prevented. I am only worried about any memory leaks down the road.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's possible to achieve this kinda transition.

Here, I describe how to implement this with your chart. As your chart shows, assume you have VC1, VC2, VC3 (top to bottom) and VCX (w/ blue box). You need to define transitions and associated animation directions (push: right-to-left or pop:left-to-right). As your chart, if you define the transitions and animations as:

  1. VC1 to : VC2(push), VCX(push)
  2. VC2 to : VC3(push), VCX(push)
  3. VC3 to : VCX(push)
  4. VCX to : VC3(pop)

and assume we have all of the view controllers instantiated already, then,

  • VC1 to VC2 transition

at VC1:

navigationController!.pushViewController(VC2, animated: true)

at VC2:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    // remove VC1 from navigation stack (I assume VC1 is not a root VC)
    let allControllers = NSMutableArray(array: navigationController!.viewControllers)
    allControllers.removeObject(at: allControllers.count - 2)
    navigationController!.setViewControllers(allControllers as [AnyObject] as! [UIViewController], animated: false)
 }
  • VC1 to VCX transition

at VC1:

navigationController!.pushViewController(VCX, animated: true)

at VCX: (A)

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    let allControllers = NSMutableArray(array: navigationController!.viewControllers)
    if (navigationController!.viewControllers[allControllers.count-2] != VC3) {
        // if not from VC3, remove VC from stack and put VC3
        allControllers.removeObject(at: allControllers.count - 2)
        allControllers.insert(VC3, at: allControllers.count - 1)
        navigationController!.setViewControllers(allControllers as [AnyObject] as! [UIViewController], animated: false)
    }
  • VC2 to VC3 transition

at VC2:

navigationController!.pushViewController(VC3, animated: true)

at VC3: (B)

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    let allControllers = NSMutableArray(array: navigationController!.viewControllers)
    if (navigationController!.viewControllers[allControllers.count-2] == VC2) {
        // if from VC2, remove it
        allControllers.removeObject(at: allControllers.count - 2)
        navigationController!.setViewControllers(allControllers as [AnyObject] as! [UIViewController], animated: false)
    }
}
  • VC2 to VCX transition

at VC2:

navigationController!.pushViewController(VCX, animated: true)

at VCX: same as (A)

  • VCX to VC3 transition

at VCX:

navigationController!.popViewController(animated: true)

at VC3: same as (B)

Note viewDidAppear is called when users swipe (left-to-right) to go back and cancel it on the way (== swipe back to left). So, you need some more small code at viewDidAppear against that situation.

If you want the different animation direction, by manipulating stack and using push/pop, you can easily achieve it. This explains how.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...