0

I had wrote a block of code which made a UIButtons in a UIView with a segue action all in the ViewController file. The segue action allows the user to press on the a UIButton and pushes a new UIView with the title of that button on it. This worked well.

Then I learned about MVC and decided to split up the code into their appropriate places. So I moved the code which created the UIView and UIButtons into a new file called ButtonView.

Now I am confused where to get access to the segue functions, since the segue code is defined in the ViewController file using @IBAction.

// Segue action - pushing to the new view
@IBAction func buttonAction(sender: UIButton!) {
    performSegueWithIdentifier("saveButton", sender: sender)
}

// Button action - saves the title of the button pressed into var buttonPressed
@IBAction func saveButton(sender: UIButton!) {
    buttonPressed = sender.currentTitle
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "saveButton"
    {
        // pass the button title string into var buttonPressed of ViewController
        if let destinationVC = segue.destinationViewController as? ViewController{
            destinationVC.buttonPressed = buttonPressed
        }
    }
}

When I created the buttons I don't know how to hook the buttons up to the segue functions. Before I defined the buttons as follows:

var button = UIButton.buttonWithType(UIButtonType.System) as! UIButton
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
button.addTarget(self, action: "saveButton:", forControlEvents: UIControlEvents.TouchDown)
addSubview(button)

Is the practice to move the segue code into the view...(which I didn't think will work and looks just wrong) or is there a way to gain access to the segue functions through a call?

Thanks for any help! Cheers,

Paul Deng
  • 59
  • 8

1 Answers1

2
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
button.addTarget(self, action: "saveButton:", forControlEvents: UIControlEvents.TouchDown)

The normal thing is that the button should be sending messages to its view controller. That is the standard MVC thing to do - indeed, that is the VC in MVC (the View is letting the Controller know there has been a user interaction, and the Controller is responsible for the subsequent logic).

So, in your code, I take it that self is not the view controller but a view. It seems to me that what you really want to know is: how do I turn self here into "my view controller, where the segue code is"?

And the answer is: walk the UIResponder chain (nextResponder()) until you come to it. Let's say that self is a UIView in the interface. Then:

var resp : UIResponder! = self
while !(resp is UIViewController) { resp = resp.nextResponder() }
let vc = resp as! UIViewController

Now vc is the owning view controller, and you can now set him as the target for these button actions.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Thanks for the response. It seems the `nextResponsder()` chain is giving me `nil`. From what I can tell `self` is a UIView in the interface. Any ideas? – Paul Deng Jun 18 '15 at 00:53
  • The problem for me is that you did not tell _where_ you are running that code, so I don't know what the state of things is at that time... Ask `self` for its `window`. If that is `nil`, you are not in the interface. You need to wait until you are in the interface, because before that you have no view controller and you cannot direct the actions to it. – matt Jun 18 '15 at 01:00
  • Okay, I checked `self.window` and it is indeed nil. I am running this code in a UIView Class which I defined. I called this UIView Class in ViewController `self.view.addSubview()`, doesn't this mean I am in the interface? – Paul Deng Jun 18 '15 at 01:25
  • But you still have not answered my question of where _in the view's code_ you are calling this code! You are _concealing_ your code, not _revealing_ it. So I have to _guess_ what you might be doing. That is not very productive for you or for me. If you want help, _you_ must be more helpful! If you are calling it in `init(frame:)`, for example, that is too soon - you are created first and _then_ put into the interface - how could it be otherwise? – matt Jun 18 '15 at 01:38
  • I got it! From what you told me about `nextRepsonder()` chain and this [link](http://stackoverflow.com/questions/1372977/given-a-view-how-do-i-get-its-viewcontroller) I think I got access to my ViewController where the segue code is. Cheers! – Paul Deng Jun 18 '15 at 01:40
  • Sorry, I wasn't clear on what I should be telling you because I still don't really understand what the problem was...I was calling the code after `init(frame:)`. Now instead of calling your code snippet, I used the extension code from the link and it seems to work. – Paul Deng Jun 18 '15 at 01:43