9
votes

Using Xcode 4.3.3, I can't figure out how to connect outlets in a custom UIView class with objects created in Interface Builder.

In one ViewController, I have a variety of buttons, sliders, etc that I'm trying to group into Views. So, within that ViewController in IB, I added 3 views. Only 1 view will be visible at any given time.

I derived custom UIView classes to handle each of these 3 views. My view controller instantiates each of the classes. I selected the view(s) in IB, opened the Identity Inspector and set the Class(es) to my custom class(es). But when I tried dragging connections from the view and/or it's constituent controls to the custom view's .h file IB won't add a connection.

IB allows me to add outlets/actions by dragging to the parent view controller's .h, but not to the custom view's .h file. I thought once I set the View's class to be my custom class, I could drag outlets for the view's components to my custom class rather than in the view controller.

This question seems identical to mine: how to connect UIview outlets to a custom subview The two solutions (manually adding outlets and setting the view's class in IB) did not change the behavior for me. Here are the manual outlets I added:

customView3.h

#import <UIKit/UIKit.h>

@interface customView3 : UIView

@property (retain) IBOutlet customView3 *view3;
@property (retain) IBOutlet UISlider *slider;

@end

customView3.m

#import "customView3.h"

@implementation customView3

@synthesize view3, slider;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
    // Initialization code
    }
    return self;
}
@end

What am I missing here? What else do I need to set/check in order to add outlets to my custom UIView rather than the view controller?

5
Swell. So, I can certainly define the create a control,say the slider, manually and position it where I want it. How, though, do I programmatically set the actions (like Value Changed) to functions in my custom class? Would I set slider.delegate = myCustomView ?Thunk
Honestly, I don't know. I hate Interface Builder and I use it rarely. To programmatically add actions, use the addTarget:action:forControlEvents: method of UIControl.user529758
Why not just use self rather than an IBOutlet to yourself with *view3?Bryan Luby
@Thunk Have you made any progress with this? I am seeing something similar in XCode 4.6 where IB won't accept the name of my UIView subclass (it beeps) even though clang compiles it successfully.trojanfoe
@trojanfoe Negative. Nothing useful to report since I filed the bug with Apple.Thunk

5 Answers

16
votes

Note that I did get this to work today, but had to insert/type the outlets by hand in the derived class, then I could drag from the header file to the UI element in the Storyboard, but not the other way around.

2
votes

I opened a bug with Apple. If anything interesting happens, I'll update this answer.

Updated 10/4/13: After much research, it seems the root of the problem is that IB believes that I'm trying to connect objects to properties within a class, that I'm going to then create a swarm of instances of this class and then IB won't be able to tell which instance should handle the messages. So, it disallows the connection on the belief that I'm (potentially) making simultaneous connections from one object to multiple copies of a property across several instances of the class.

My view is that I only want a single instance of the custom UIView, and that I should be able to tell IB, "don't panic, you're only dealing with this one instance."

I'm now focused on a new project and haven't had a chance to retry this in Xcode 5; however, given the info above, I'm not optimistic it will work in Xcode 5, either.

1
votes

What you're trying to do is certainly both sensible (IMO) and possible. XCode is however quite quirky when it comes to establishing connections to outlets in subviews.

I've found that cleaning, rebuilding and sometimes restarting XCode tends to help, but sometimes it just doesn't work. In some cases I got it working by manually creating the outlet and dragging from the outlet to the control rather than the other way.

This is not very helpful, I know, but I just wanted to make it clear that this is supposed to work and when it doesn't it is most certainly due to a bug in XCode.

0
votes

In my experience, you add IBAction and IBOutlet to subclasses of UIViewController and not subclasses of UIView. So within the MVC model, your "1" UIViewController has all of these IBOutlets in it and then you use the data from these IBOutlets to update your views.

So you are fine creating the UIViews objects in IB and then creating the corresponding classes in code and then changing the class of the UIViews objects in IB to your UIView subclass. Just put all IBOutlets in the UIViewController that has all the UIViews under it, get the values you need from the IBOutlets and then pass them down to (set them in) your UIView subclasses.

Hope this helps.

0
votes

I had the same problem and found a workaround:

1) Open the Assistant Editor with customView3.xib on the left and customView3.h on the right

2) ctrl + drag from UISlider in customView3.xib to the customView3.h code on the right

3) An option to create a new Outlet connection will pop up.

4) Name the connection and click connect

It will then create a connected IBOutlet.