5
votes

I have created a custom subclass of UIView along with a xib file and declared IBOutlets and IBActions within the custom class.

@interface ContactUsView : UIView

@property (nonatomic, weak) IBOutlet UIButton *displayCloseButton;

- (IBAction)callButtonPressed:(id)sender;
- (IBAction)emailButtonPressed:(id)sender;
- (IBAction)displayCloseButtonPressed:(id)sender;

@end

In the xib file I have dragged in a UIView to represent my custom view. I have set:

  • Files owner = to my custom class
  • Have set the dragged in UIView to my custom class.

I have then added various buttons which are hooked up to the 3 methods stated above.

Inside the ContactUsView.m I have the following:

- (id)initWithFrame:(CGRect)frame 
{
    if (self = [super initWithFrame:frame]) {
        NSArray* array = [[NSBundle mainBundle] loadNibNamed:@"ContactUsView" owner:self options:nil];
        for (id object in array) {
            if ([object isKindOfClass:[ContactUsView class]])
                self = (ContactUsView *)object;
        }
    }
    return self;
}

When I come to create this view I do the following:

- (void)viewWillAppear:(BOOL)animated
{
    ContactUsView *contactUs = [[ContactUsView alloc] initWithFrame:CGRectZero];

    CGPoint origin = self.view.frame.origin;
    CGSize size = self.view.frame.size;
    [contactUs setFrame:CGRectMake(origin.x,
                              CGRectGetMaxY(self.view.frame) - 100,
                              size.width,
                              contactUs.frame.size.height)];

    [self.view addSubview:contactUs];
}

Issue When I press on one of the buttons the application crashes with: Thread 1: EXC_BAD_ACCESS(code=2, address=0xb0c

Can anyone help me with this. I feel like I am probably making a mistake somewhere in regards to creating and loading custom uiviews from xibs.

If you require anymore information let me know. Many thanks.

Future reference When creating a custom view using a xib DO NOT set the files owner. Instead create all your IBOutlets and IBActions as you normally would and then to hook them up open the Utilities tab and control drag from there.

enter image description here

3
Can you post the whole error? Or the line where the error actually happens? Enable breakpoints on exceptions in XCode.KerrM
If I put a break point in one of the methods that is called, it never hits the break point. It just crashes with the code above and nothing shows in the output. I added an 'All exceptions' breakpoint and still nothing shown in output.pls

3 Answers

4
votes

• Files owner = to my custom class

Wrong. Files owner should be empty. The view itself is files owner. It means that you should connect all actions and outlets with ContactUsView in your xib.

[[NSBundle mainBundle] loadNibNamed:@"ContactUsView" owner:self options:nil]

...

self = (ContactUsView *)object;

After you passed self as ownerparameter. You changing it. Which means that previously allocated ContactUsView (self) will be destroyed since -loadNibNamed:owner:options: do not retain it. If you apply my first advice you should send nil as owner parameter

forloop here is not necessary use just array[0], because this is always your view if you have valid views hierarchy in your xib

2
votes

If you are loading a UIView for an xib then you should create a class method to load the view.

In your customview.h

+(id)customView;

& in your customview.m

+ (id)customView
{
    CustomView *customView = [[[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:nil options:nil] lastObject];
    if ([customView isKindOfClass:[CustomView class]])
        return customView;
    else
        return nil;
}

You can initialize it anywhere using:

CustomView *myView = [CustomView customView];

EDIT: Make sure you have changed your customview's class in identity inspecter & also make sure your connection of IBActions are with that class' methods.enter image description here

enter image description here

1
votes

You can use delegate for this this is how you can do this

        @protocol CustomViewDelegate <NSObject>
- (void)callButtonPressed:(id)sender;
- (void)emailButtonPressed:(id)sender;
- (void)displayCloseButtonPressed:(id)sender;

@end

@interface ContactUsView : UIView

@property (nonatomic, weak) IBOutlet UIButton *displayCloseButton;

@property (nonatomic, weak) id<CustomViewDelegate> ButtonDelegate;

- (IBAction)callButtonPressed:(id)sender;

- (IBAction)emailButtonPressed:(id)sender;
- (IBAction)displayCloseButtonPressed:(id)sender;


@end

and in .m file

- (IBAction)callButtonPressed:(id)sender
{
[self.ButtonDelegate callButtonPressed:sender];
}

- (IBAction)emailButtonPressed:(id)sender{
[self.ButtonDelegate emailButtonPressed:sender];
}

- (IBAction)displayCloseButtonPressed:(id)sender{
[self.ButtonDelegate displayCloseButtonPressed:sender];
}

After that just set the delegate with viewcontroller refrence and use those delegate here

- (void)viewWillAppear:(BOOL)animated

{

ContactUsView *contactUs = [[ContactUsView alloc] initWithFrame:CGRectZero];
contactUs.ButtonDelegate = self;

CGPoint origin = self.view.frame.origin;
CGSize size = self.view.frame.size;
[contactUs setFrame:CGRectMake(origin.x,
                          CGRectGetMaxY(self.view.frame) - 100,
                          size.width,
                          contactUs.frame.size.height)];

[self.view addSubview:contactUs];

}

- (void)callButtonPressed:(id)sender

{}

- (void)emailButtonPressed:(id)sender

{}

- (void)displayCloseButtonPressed:(id)sender

{}

I have done this and works totlly fine