0

I still don't have an answer after viewing many answers to a similar question eg. https://stackoverflow.com/questions/12509422/how-to-perform-unwind-segue-programmatically

I would like to try to restate what "programmatically" means to the question I'm posing.

All the solutions show using a storyboard and connecting the view controllers "exit" with an unwind method defined in some view controller. This works but isn't programmatically, but rather directly connecting through use by the Xcode tool. Sure the prepare method is programmatically involved in the final steps.

My challenge is that I'm using Cocoapods as a reusable library, and the storyboard has no way to know about users of this library. So they cannot connect to an unwind method, as there isn't one yet.

I want to use the language generic capabilities to specify the unwind method, programmatically (Swift or Objective-C).

The unwind method might also be in another bundle, further complicating things.

Note: Creating a placeholder unwind would be ok, assuming the value of the view controller name can be changed programmatically through the UIStoryboardSegue object (which has an unwindAction).

Thanks for any insight.

UPDATE ANSWER (it won't let me answer) First, my answer involves clarifying the original question, in particular the "without storboard" statement. This was meant to "unwind" to a ViewController that wasn't specified via the storyboard, in particular a new user of this library. My answer shows I can do this, but a storyboard is still required (just not for this new ViewController).

My question did state that a placeholder unwind could be created via a storyboard.

Note: Creating a placeholder unwind would be ok, assuming the value of the view controller name can be changed programmatically through the UIStoryboardSegue object (which has an unwindAction).

So my answer can call code that wasn't specified via the Xcode user interface (which is the UI process of connecting to a named unwind though dragging to the 'exit').

I was under the (wrong) assumption this was connecting to my unwind method (eg. unwindFromHelp), much like connecting a button to an IBAction in code. Instead it connects dynamically to anything matching that name in the runtime hierarchy.

The key insight to the answer is from What are Unwind segues for and how do you use them? where @shawkinaw states:

In other words, think of the unwind action as describing where the segue is coming from, rather than where it is going to.

This also means there can be many implementations of the same unwind method name! At runtime, the ViewController hierarchy keeps track of the unwind methods it's encountered along the way, and calling the Segue Unwind will unwind to the first one it finds.

Based on that new understanding, my quest to call an unwind method in some future ViewController is possible by creating a placeholder unwind that is manually added through the Xcode exit approach. That operation shows all the unwind methods available at that time.

So the solution involves using the storyboard, and a (potentially) unused ViewController, where an unwind method is defined. Then the exit of the desired ViewController connects through Xcode to that unwind.

A future user can also define this same unwind method in new code (eg. unwindFromHelp) and if the ViewHierarchy runtime stack is such that no other unwind is matched, their code is executed. Thus this delegation approach achieves my original question, where the future user must provide an implementation for the delegation (which here is an unwind method name, eg. unwindFromHelp).

I wrote a sample that shows how this can be accomplished and the unwind returns to different ViewControllers based on how it got there: github UnwindExample

An example flow diagram is based on the A or B calling Help idea.

matt
  • 515,959
  • 87
  • 875
  • 1,141
KonaCurrents
  • 11
  • 1
  • 5
  • Segues and storyboards are tightly coupled. You cannot perform an unwind segue without the segue appearing in the storyboard. You will need to manipulate the view controller hierarchy in code. – Paulw11 Feb 20 '21 at 00:08
  • It looks possible according to Apple Documentation on UIStoryboardSegue, "You might do so to initiate a segue from a source that was added programmatically and therefore not available in Interface Builder." – KonaCurrents Feb 20 '21 at 01:02
  • Why not *programmatically* just use the navigation controller? You know, work the controller stack? –  Feb 20 '21 at 05:18
  • @KnowledgeShark That is referring to programatically triggering an unwind segue from a *source* (like a UIButton) that you added using code rather than to the storyboard scene. Rather than having your framework try to figure out what to do, I would look at using a delegation pattern or a closure supplied by the caller that can be used when it is time to "unwind". That way the caller can do what is required. The caller may not even be using a storyboard – Paulw11 Feb 20 '21 at 05:53
  • Paulw11, that is exactly what I'm trying to accomplish and the unwind is the tool provided by Apple. So I need to parameterize the unwind with a known delegate. If I can retrieve the known UIStoryboardSegues and modify the unwindAction it would work. Proof is manually editing the storyboard xml and changing unwindAction string, and it unwinds to a view controller and method unknown previously. – KonaCurrents Feb 20 '21 at 06:17
  • Yes, unwinds are the tool that Apple provides for working with *storyboards*. What if there is no storyboard? You could allow the caller to specify the name of an unwind segue that you invoke, but you still need to handle the callers that aren't using storyboards. IMO your approach is too tightly coupled and violates the separation of concerns principle – Paulw11 Feb 22 '21 at 00:50
  • [link](https://stackoverflow.com/a/34297839/5496358) @shawkinaw provided the best insight of the unwind, "think of the unwind action as describing where the segue is coming from, rather than where it is going to.". And there can be many implementations of the same named unwind! So I can do what I want (with storyboards) by providing a placeholder unwind connected with the storyboard, and then a new user would provide the same unwind name, and if they are in the view hierarchy, it returns nicely. paulw I appreciate the storyboard constraint. I have a project I'll share to show all this. – KonaCurrents Feb 22 '21 at 06:00
  • I put together a quick demo that shows how the unwind endpoints differ depending on the path of the view controllers. The example from @shawkinaw was A or B calls H, so H doesn't know who to return to. My example expands on that and looks at dynamic ways of calling an unwind identifier. But it seems the storyboard has to put it in first, even if it's not the A or B (or other) recipients. [link](https://github.com/konacurrents/UnwindExample) – KonaCurrents Feb 22 '21 at 06:38
  • Please create an answer to answer your the question, instead of editing an answer into the question itself. – Yunnosch Feb 23 '21 at 23:29
  • My question with the answer is gone now? How can I get it back? The system wouldn't let me answer my own question. This was my first post so maybe I don't have enough points? – KonaCurrents Feb 24 '21 at 00:36
  • @matt thanks for the reply and I don't know why it won't let me answer. But as for "everyone already knows" that doesn't seem to be the case reading all the comments in the links I provided. Now I know and it seems my analysis was valuable. – KonaCurrents Feb 24 '21 at 05:16

0 Answers0