1

I have been having a strange problem using a custom delegate class in ARC. In the viewcontroller after viewDidLoad I call the toolbars setDelegate method and assign the viewcontroller as the delegate.

Whenever I try to reference delegate, it is nil, even after being set in the viewcontroller.

//MPToolbar.h

#import <UIKit/UIKit.h>

//Define the protocol for the delegate
@class MPToolBar;
@protocol MPToolBarDelegate <NSObject>
@required
- (void)writeButtonSelected;
- (void)writeButtonDeSelected;
@end

@interface MPToolBar : UIView{
    id <MPToolBarDelegate> delegate;
}

@property(strong) UIButton *lastButton;

@property(strong) id <MPToolBarDelegate> delegate;
-(IBAction)buttonSelected:(id)sender;
-(void)resizeForOrientation:(UIInterfaceOrientation)orientation;

@end

//MPToolbar.m
#import "MPToolBar.h"

@implementation MPToolBar
@synthesize lastButton, delegate;

- (id)initWithFrame:(CGRect)frame
{
    if ((self = [super initWithFrame:frame])) {
        // Initialization code
    }
    NSArray *nibViews = [[NSBundle mainBundle] loadNibNamed:@"MPToolBar" owner:self options:nil];
    [self addSubview:[nibViews objectAtIndex:0]];
    return self;
}


#pragma button actions
-(IBAction)buttonSelected:(id)sender{
    UIButton *btn = (UIButton *)sender;
    if(lastButton && lastButton != btn)[self deselect:lastButton];

    if (btn.selected){
        [self deselect:btn];
        return;
    }

    [btn setSelected:YES];
    lastButton = btn;
    switch (btn.tag) {
        case 0:
            [self.delegate writeButtonSelected];
            break;
    }
}
-(void)deselect:(UIButton *)btn{
    [btn setSelected:NO];
    switch (btn.tag) {
        case 0:
            [self.delegate writeButtonDeSelected];
            break;
    }
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/
-(void)resizeForOrientation:(UIInterfaceOrientation)orientation{
    if (UIInterfaceOrientationIsLandscape(orientation)) {
        self.frame = CGRectMake(0, 44, 1024, 60);
    }
    if (UIInterfaceOrientationIsPortrait(orientation)) {
        self.frame = CGRectMake(0, 44, 768, 60);
    }
}
@end

//ViewTest.h
#import <UIKit/UIKit.h>
#import "MPToolBar.h"
@interface ViewTest : UIViewController <MPToolBarDelegate>
{
    MPToolBar *toolBar;
}
@property(strong) MPToolBar *toolBar;
@end

//ViewTest.m
#import "ViewTest.h"

@interface ViewTest ()

@end

@implementation ViewTest
@synthesize toolBar;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.toolBar = [[MPToolBar alloc] initWithFrame:CGRectMake(0, 44, 1024, 60)];
    [self.view addSubview:self.toolBar];
    [self.toolBar setAlpha:1.0];
    [self.toolBar setDelegate:self];
    // Do any additional setup after loading the view from its nib.
}
#pragma mark - MPToolBar Delegate Methods
-(void)writeButtonSelected{
    //set new annotation for write mode and size to screen bounds.
    NSLog(@"writeButtonSelected");
}
- (void)writeButtonDeSelected{
    NSLog(@"writeButtonDeSelected");
}
- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

@end
Joe
  • 234
  • 5
  • 18
  • Now updated with latest test class. Nothing seems to make my delegate stop disappearing after I set it. – Joe Jul 10 '12 at 06:44

4 Answers4

6

Ok so I finally found the problem. In my xib file I had set the UIView class to my custom controls class name instead of setting files owner.

once I changed the first UIView in the xib back to a standard UIView and then set the files owner to my custom class all was right with the world again!

-Thanks for everyone who tried to help!

Joe
  • 234
  • 5
  • 18
0

Several things that could be causing problems:

  1. Do you actually declare your view controller as a MPToolBarDelegate in its header? (that code is not present).

  2. These are the delegate functions in your code:

-(void)ButtonSelected;

-(void)ButtonDeSelected;

However, you're actually invoking this one:

[_delegate writeButtonSelected];

which is not part of your protocol.

Dima
  • 23,484
  • 6
  • 56
  • 83
  • Sorry, Yes I do declare the delegate *updated code above. Also the delegate functions were just renamed for simplicity for this post, also updated above. If I place a breakpoint on [__delegate ButtonSelected]; delegate is nil – Joe Jun 29 '12 at 16:08
  • I think I found the problem. the variable declaration in your header should be `delegate` not `_delegate`. Although you should actually just be able to remove it altogether. the @property directive is enough for the compiler to fill in the declaration for you. In your current code, if you changed `[_delegate ButtonSelected]` to `[self.delegate ButtonSelected]`, it should actually work. Because your function declaration and property have different names, they are actually 2 different fields. Currently, you are setting one, but trying to use the other. – Dima Jun 29 '12 at 16:55
  • There is a good explanation on what is happening and what you need to change [here](http://stackoverflow.com/questions/5466496/why-rename-synthesized-properties-in-ios-with-leading-underscores) – Dima Jun 29 '12 at 16:59
  • I have tried your suggestion I changed to _delegate to self.delegate, the breakpoint shows the delegate is still 0x000000 in the debug area, and the breakpoint in my viewcontroller ButtonSelected function is never hit. – Joe Jun 29 '12 at 17:50
  • also get rid of `__unsafe_unretained id _delegate; ` in your interface. That should work. – Dima Jun 29 '12 at 18:09
  • :( still no luck after deleting that line. My viewcontoller is using a third party viewcontroller that inherits from UIViewController, so I am going to try to make a new class that inherits directly from UIViewController in case the third party framework class is the culprit. – Joe Jun 29 '12 at 23:54
  • Ok so after creating abrand new class that simply inherits from UIViewController type, I added my toolbar in set the delegate, allocated the toolbar and still after setting the delegate, it gets lost somewhere. if i break immediately after setting the delegate, then the debug area has a proper value, if i set the break point in my toobar class where it calls delegate function after then it is 0x000000. This is driving me nuts. – Joe Jul 10 '12 at 06:36
  • can you post your whole project or some stripped version of it that has the problem? I'd have a much easier time helping you if I could compile the code and see for myself. – Dima Jul 10 '12 at 14:01
0

Try changing your delegate declarations like this:

@interface MPToolBar : UIView{
    id delegate;
}

@property (nonatomic, assign) id <MPToolBarDelegate> delegate;

then when you call your delegate method use this:

[self.delegate ButtonSelected];

Also, the original iPad is upgradeable to iOS 5.0. If you are using ARC you can't be compatible with 4.3 anyway, ARC only started at 5.0 as I understand it.

Justin Paulson
  • 4,388
  • 1
  • 23
  • 28
  • ARC is compatible with 4.3 as well. – Dima Jun 29 '12 at 17:38
  • As I understand it you cannot use nonatomic, assign with ARC, which is why I have an issue. – Joe Jun 29 '12 at 17:53
  • 1
    @Dima, you are correct. I just assumed since ARC was realeased with iOS 5 that it was a requirement, but it looks like it is backward compatible to iOS 4 as well. Thanks! – Justin Paulson Jun 29 '12 at 18:04
  • Tried changing it to (nonatomic, assign) still returns nil and does not break in the delegate function – Joe Jun 29 '12 at 23:43
0

With a similar symptom for me, my problem was that the segue's destinationViewController was NOT the object I was expecting it to be, because it was embedded in a UINavigationController.

Easy fix. See here. Lose pointer to Delegate while going through Navigation Controller

Community
  • 1
  • 1
radsdau
  • 495
  • 5
  • 16