6

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

pls
  • 1,522
  • 2
  • 21
  • 41
  • Can you post the whole error? Or the line where the error actually happens? Enable breakpoints on exceptions in XCode. – KerrM Dec 05 '14 at 11:24
  • 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 Dec 05 '14 at 11:39

3 Answers3

4

• 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

Community
  • 1
  • 1
Silmaril
  • 4,241
  • 20
  • 22
  • Thanks very much Silmaril. That has sorted my issue. For future reference when creating a custom view you need to open up the Utilities tag and control drag from there. – pls Dec 05 '14 at 13:35
3

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

Ajay
  • 1,622
  • 20
  • 36
  • Hi Ajay. Yeah I will probably implement this as a class method. However the code within your method is the same as my code and still causes the same crash. – pls Dec 05 '14 at 13:25
  • Silmaril answer made me realise what I was doing wrong. I already accepted his answer before seeing your edited answer which has the same solution. I have up voted your answer as well. Many thanks. – pls Dec 05 '14 at 13:44
1

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

Arun Kumar
  • 788
  • 5
  • 15
  • Thanks for the response. Are you loading the xib in the same way I do? My app crashes when I click a button that is tied to an IBAction. However it crashes straight away meaning nothing in the method happens. If seems to me like something to do with memory when the view is loaded. – pls Dec 05 '14 at 12:57