IBOutlet is nil inside custom UIView (Using STORYBOARD)
Asked Answered
A

7

23

I have a custom UIView class. Inside it I have declared an IBOutlet property for UIImageView.

#import <UIKit/UIKit.h>

@interface SettingItem : UIView{

}

@property (strong, nonatomic) IBOutlet UIImageView *myImage;

@end

Now i am using storyboard. There is a viewcontroller. I dragged UIView to viewcontroller. I dragged one UIImageView as a subview of above UIView. I set the "SettingItem" class to UIView from storyboard. I connected the outlet to myImage by normal dragging from outlets of SettingItem from utilities window.


SettingItem implementation

#import "SettingItem.h"

@implementation SettingItem

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

-(id) initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if (self) {
        // Initialization code
        [self baseInit];
    }
    return self;
}

- (void) baseInit{
    NSLog(@"myImage %@"self.myImage);
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

@end

Now my problem is myImage is always nil, above NSLog just print (null) for the outlet. I checked the view in storyboard and checked its outlet reference and its pointing to myImage. I am missing something. I googled for the help but couldn't find any solution.

Can you please point out what am i doing wrong ?

Allie answered 30/12, 2012 at 8:37 Comment(2)
Why do you declare the IBOutlet property as strong instead of weak? Is it because it's a property of the UIView itself so it is the only owner of the property? ThanksGametocyte
@PabloA. Yes It is the only owner. Also Xcode IB of that time used to put strong to outlets by default, i think. So you would have to reedit to weak or take care of it with the situation in hand.Allie
K
80

Override awakeFromNib in your view - this is the first lifecycle method to be called after the IBOutlets have been assigned and is the right place for your code.

Knut answered 26/6, 2014 at 13:11 Comment(3)
Short: this is the only correct answer here, others should be wrapped into lead cover and sent to space. Long: Oh, how I hope when I'm going to ask anything on SO, there would be somebody like @Oly to provide the only reasonable and correct answer. Other answers are so rubbish, that it just demonstrates absence of required knowledge. Please, be more like Oly and less like the rest in this thread.Renita
@Renita You've just cheered up my day, I've just returned to work after a horrible accident last year and needed some encouragement ;-)Knut
In awakefromNib, it is still getting null values, i have searched many things on stackoverflow, and answer i got at many links is that content is lazy loaded, so in awakefromnib, you can have iboutlets values nullLoverly
H
4

initialize them in awakeFromNib:

- (void)awakeFromNib
{
    //init code
}
Harrisharrisburg answered 16/4, 2016 at 5:52 Comment(0)
F
2

I just had the exact same problem and the solution is really easy:

You're accessing myImage to soon - that's it.

Withing -(id) initWithCoder:(NSCoder *)aDecoder{ and - (id)initWithFrame:(CGRect)frame the UIView is not already drawed. So myImage is not initalized yet.

You can test it if you add a UIButton and an IBAction and do something like this:

- (IBAction)buttonClicked:(id)sender {
    NSLog(@"%@",myImage);
}

And you'll see how myImage is not nil anymore.

Freyah answered 13/1, 2013 at 18:26 Comment(0)
S
0

I had similar problems, but I finally figured out what was wrong - It was a difference in the idiom between XIB files and Storyboards.

In all the tutorials that I had seen with Xib files, if I had a UITableViewController create a DetailViewController to let me edit the content of the items in the table, then the tableViewController created an instance of the DVC once when it first revealed it, but then reused that same DVC instance whenever it needed to edit another item on the list.

With storyboards, it appears that the a view that is revealed by a table view is typically created new each time the table view calls it up (and it doesn't call up the version of init that is in the UIViewController template). As a previous answer stated, you have to wait until "ViewDidLoad" to access any of the controls, even if you have shown this view before.

I hope this helps.

Shapeless answered 30/4, 2013 at 15:52 Comment(0)
P
0

Can you not use the setter for properties, that way you can do what you need when it's actually populated?

@IBOutlet weak var xxx:UIKitClass! {
  didSet { 
    outletSetup() 
  }
}
Purposeless answered 28/11, 2019 at 12:4 Comment(0)
T
-4

Call [self baseInit] inside -(void)viewWillAppear:(BOOL)animated. myImage should have a value there.

#import "SettingItem.h"

@implementation SettingItem

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

    }
    return self;
}

-(id) initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if (self) {
        // Initialization code

    }
    return self;
}
-(void)viewWillAppear:(BOOL)animated
{
   [self baseInit];
}

- (void) baseInit{
    NSLog(@"myImage %@"self.myImage);
}
Trilobate answered 9/1, 2013 at 19:59 Comment(1)
viewWillAppear doesn't belong to UIView, is it ? Its in UIViewController.Allie
A
-6

in your .h file you need to replace your code:

#import <UIKit/UIKit.h>

@interface SettingItem : UIView{

}

@property (strong, nonatomic) IBOutlet UIImageView *myImage;

@end

With this code

#import <UIKit/UIKit.h>

@interface SettingItem : UIView{

  IBOutlet UIImageView*myImage;

}

@end

You are not actually telling Xcode what myImage is, you are just making it a strong, nonatomic property

Argot answered 30/12, 2012 at 9:2 Comment(7)
then how am i supposed to connect outlet to it from storyboard since property is not visible anymore ?Allie
if you click on the status bar of the view and then go to the connections inspector then link itArgot
Thanks but still getting nullAllie
@Argot You're wrong. The IBOutlet in the @property-declaration does mean, it's available in the UIStoryBoard. You shouldn't use @interface Class : SuperClass { IBOutlet ... } anymore.Freyah
@Argot Of course it's not wrong but it's not the solution.Freyah
Those two declarations are, firstly, equivalent with respect to their ivar storage (modulo the ivar's name: in the first one, the property will be auto-synthesized to _myImage, whereas the second one is named myImage), but second and more importantly, this has nothing to do with the question being asked.Tarton
But you are not answering his question.Finedraw

© 2022 - 2025 — McMap. All rights reserved.