0

I'm trying a storyboard-free approach, and attempted the following:

  1. I created a FooView.xib to hold my layout. It has a few buttons and labels.
  2. I created a FooView.swift to hold a FooView subclass of UIView. At the moment, it doesn't really do anything.
  3. I created FooViewController.swift to manage my FooView instances. I call it to create FooViews as follows:

    init() { super.init(nibName: "FooView", bundle: nil) }

  4. I set the File Owner of FooView.xib to the FooView class

  5. I set the custom class of the FooView view as FooView
  6. I dragged some @IBAction outputs from the IB to the FooView implementation

When my actions fire, I get a runtime exception: "unrecognized selector sent to instance" that references the FooViewController(!). I double checked the File Owner and all the outputs, all references look correct.

It acts like it ignores the File Owner with respect to the event dispatch.

(It feels like I'm fighting the framework and really am expected to implement all my outputs/actions inside the controller, but from an architectural purity perspective (to enhance testing) I was leaning towards hiding the xib control details and making a more opaque view that didn't directly expose its inner controls to the controller, but instead had a protocol/delegate kind of contract.)

I have a sneaky suspicion that if I moved all the xib-loading logic into the UIView implementation that things would work, but that feels like a larger adventure. Is there an easy way to set up my FooView subclass to receive the events?

Jolly Roger
  • 3,913
  • 4
  • 24
  • 23
  • The owner should be `FooViewController` class, not `FooView`. It seems like you don't have a clear distinction about what is a view and what is a controller. Show us the real initialization code please. – Sulthan Feb 21 '16 at 21:54
  • While you can load UIView's from nibs, you can do it via the `init` method - this is for UIViewControllers. You can load a NIB file and then extract the root view object. This answer shows how in Objective C. Translating to Swift is pretty trivial - http://stackoverflow.com/questions/15405916/correct-way-to-load-a-nib-for-a-uiview-subclass but really, I think you are misunderstanding what should be in the view controller and what should be in the UIView. – Paulw11 Feb 21 '16 at 22:07
  • Pretty sure that I do understand the distinction between a View and a Controller. I see no reason why a View can't self-manage the details (i.e. field setting, event handling) to its own children without delegating that to a Controller. I actually think the typical iOS implementations have muddled responsibilities. A controller should be a mediator, and just as there typically should be a protocol to talk to models, there commonly (in other frameworks, anyway) should also be a protocol to talk to views. All I'm trying to do is to abstract the view details away from the controller. – Jolly Roger Feb 21 '16 at 22:13

1 Answers1

1

Another thing you could use is set the First Responder as the target for your action. Although you won't get the nice neat indicator in XCode that you IBAction is connected, it will pass the message to the first class in the responder chain that implements that method.

To set it up in interface builder, click on First Responder and open the Attributes inspector. Add your method to the User Defined list as someAction: (don't forget the colon). Then you can connect your button to the first responder and that method will be an available option for you to connect it.

Lastly you declare your IBAction just like normal in the view class you want to implement it.

GW.Rodriguez
  • 1,181
  • 8
  • 18