colindunn
colindunn

Reputation: 3163

Swift: Best way to get value from view

I have a custom UIView (called GridView) that I initialize and then add to a ViewController (DetailViewController). GridView contains several UIButtons and I would like to know in DetailViewController when those buttons are touched. I'm new to Swift and am wondering what is the best pattern to use to get those events?

Upvotes: 0

Views: 351

Answers (3)

Sebastian
Sebastian

Reputation: 8164

If you want to do this with notifications, use 1:

func postNotificationName(_ notificationName: String,
    object notificationSender: AnyObject?)

in the method that is triggered by your button. Then, in your DetailViewController, add a listener when it is initialized with 2:

func addObserver(_ notificationObserver: AnyObject,
    selector notificationSelector: Selector,
        name notificationName: String?,
      object notificationSender: AnyObject?)

Both functions can be called from NSNotificationCenter.defaultCenter().

Another method would be to add callbacks which you connect once you initialize the GridView in your DetailViewController. A callback is essentially a closure:

var callback : (() -> Void)?

which you can instantiate when needed, e.g.

// In DetailViewController initialization
gridView = GridView()
gridView.callback = { self.doSomething() }

In GridView you can trigger the callback like this:

func onButton()
{
    callback?()
}

The callback will only execute, if unwrapping succeeds. Please ensure, that you have read Automatic Reference Counting, because these constructs may lead to strong reference cycles.

What's the difference? You can connect the callback only once (at least with the method I've showed here), but when it triggers, the receiver immediately executes its code. For notifications, you can have multiple receivers but there is some delay in event delivery.

Upvotes: 1

natuslaedo
natuslaedo

Reputation: 429

Lets assume your GridView implementation is like as follows:

class GridView : UIView {
    // Initializing buttons
    let button1:UIButton = UIButton(...)
    let button2:UIButton = UIButton(...)
    // ...

    // Adding buttons to view
    self.addSubview(button1)
    self.addSubview(button2)
    // ... 
}

Now, we will add selector methods which will be called when a button is touched. Lets assume implementation of your view controller is like as follows:

class DetailViewController : UIViewController {
    let myView:GridView = GridView(...)

    myView.button1.addTarget(self, action: "actionForButton1:", forControlEvents: UIControlEvents.TouchUpInside)
    myView.button2.addTarget(self, action: "actionForButton2:", forControlEvents: UIControlEvents.TouchUpInside)
    // ...

    func actionForButton1(sender: UIButton!) {
        // Your actions when button 1 is pressed
    }
    // ... Selectors for other buttons
}

I have to say that my example approach is not a good example for encapsulation principles of Object-Oriented Programming, but I have written like this because you are new to Swift and this code is easy to understand. If you want to prevent duplicate codes such as writing different selectors for each button and if you want to set properties of your view as private to prevent access from "outside" like I just did in DetailViewController, there are much much better solutions. I hope it just helps you!

Upvotes: 1

Lucas Huang
Lucas Huang

Reputation: 4016

I think you better create a class called GridView that is inherited from the UIView. Then, you can connect all you UI element with you class as IBOutlet or whatever using tag something like that. Later on, you can ask the instance of GridView in DetailViewController so that you can connect as IBAction.

Encapsulation is one of the principles of OOP.

Upvotes: 0

Related Questions