1

I have a (simplified) Cocoa view hierarchy as follows:

window
- contentView
-- view1
---> button1
--view2
---> textField1

Importantly, the button1 & textField1 do NOT share an immediate superView.

I would like to add a target-action to button1 to perform something (not relevant what precisely) on textField1 (consider textField1 is some custom text field I have created).

In my understanding, the button will have to have a reference to textField1 at initialization so that you can add the "target-action".

My question is what is the best way for button1 to get hold of this reference in a manner that will scale to more complex/deep/nested view hierarchies

I am hopefully looking for something a little more elegant than:

let reference = self.superview.subview[0].subview[0] as NSView

Interface Builder allows you to right-click and drag from the button to the textField to make a 'connection' and it uses some sort of internal ID for this. Is their something similar to be done in code?

Sam
  • 2,745
  • 3
  • 20
  • 42
  • Have you tried to add event to the button in the contentView? You can access your textfield1 simply by calling self.view2.textField1. – Miknash Dec 10 '14 at 09:01
  • How would `contentView` know that it has a member `view2` and similarly, how would `view2` know that it had a member `textField1`? Are you suggesting I set them up as members over and above the fact that they have been added to the `subViews` array? – Sam Dec 10 '14 at 09:15
  • well you can check that, right? you have to add that subview and therefore you can check if they exists. You can add them as members as well and access like that because it will be easier to manage these views. – Miknash Dec 10 '14 at 09:40

1 Answers1

1

The two views wouldn't have a reference to each other at all. That doesn't scale well. That would be akin to a UITableView always having a reference to a UITextField.

Your views should be just displaying stuff. You need a controller, or more specifically the View Controller to let them interact, via a Model if you desire.

There are many ways to do this, but the guiding principle is that they are decoupled. The button would have an action. That action could have a target method on the view controller, it could fire a NSNotification,... the ViewController would handle this and then do something with textfield on the other view.

Maybe the button changes some data in your Model, and the textfield is somehow wired up via it's controller to listen for changes to the Model and display the data via the Model.

Just keep your view displaying stuff. Don't put Model stuff in the views. Let the controller manage the coordination of letting your views communicate.

bandejapaisa
  • 26,576
  • 13
  • 94
  • 112
  • I understand your answer - MVC good practise. What if the situation is one in which a bunch of views are working together to form a bigger (composite) control? As in all the components of a ScrollView or a TableView. So the "model" is actually the creation of a UI widget. – Sam Dec 10 '14 at 14:50
  • Well that sounds like you need a delegate & a datasource, just like Scrollview and TableView have. Use the delegate for sending actions back from your composite view, i.e. the button action, and use the datasource for pulling in data to populate the textfield. As an example I just pulled from github, a project I've used... see https://github.com/nicklockwood/SwipeView which uses a Delegate & Datasource. Not a brilliant example, as it's basically a UIView that hosts a UIScrollView - but you might get the gist. – bandejapaisa Dec 10 '14 at 15:54
  • Alternatively, if you really want them to talk to each other in the composite view, and it's a black box component - then declare the UITextField and UIButton at the top common level, saved as instance vars. Create the subviews of your component and put the textfield and button as subviews inside of these. Then they can communicate without having to use superview.subview (which is a code smell in my opinion). All depends on how much you want to engineer this and how reusable you want to make it. – bandejapaisa Dec 10 '14 at 16:01