iOS Turn an IBOutlet into a property?

ArtOfWarfare

macrumors G3
Original poster
Nov 26, 2007
8,703
4,328
I have a UITableViewController that manages a list of available in-app purchases and a UIViewController that shows the details on the purchases.

I'd like to set up my detail view in storyboard (and thus need IBOutlets,) but I'd like my UITableViewController to be able to set the details using properties of the UIViewController. This is what I attempted to do in the header:

Code:
@interface ProductViewController : UIViewController
{
	IBOutlet	UIButton	*purchaseButton;
	IBOutlet	UILabel		*productLabel;
	IBOutlet	UITextView	*productDetails;
}

@property UIButton *purchaseButton;
@property UILabel *productLabel;
@property UITextView *productDetails;

@end
But it's generating three errors, one for each object, on the line where I synthesize the variables in my .m.

Code:
@synthesize purchaseButton, productLabel, productDetails;
Existing ivar 'productDetails' for unsafe_unretained property 'productDetails' must be __unsafe_unretained
I suspect that the issue is that I never taught myself enough on C (I stopped somewhere during pointers.) Possibly going back and teaching myself the rest would be a good idea...
 

admanimal

macrumors 68040
Apr 22, 2005
3,531
2
I haven't been able to find a reference to verify this, but I'm pretty sure the problem has to do with conflicting ownership specifiers for your ivars/properties.

By default with ARC, explicitly declared pointer ivars have strong ownership in ARC terms (i.e. they are retained). Properties are assigned by default (i.e. are unsafe unretained). Since you don't explicitly specify any ownership for your ivars or properties, it is using the default for both, which conflict with each other.

You need to either specify your properties as strong or your ivars as unsafe unretained.
 

xStep

macrumors 68020
Jan 28, 2003
2,013
100
Less lost in L.A.
I cut and pasted your code into an existing ARC project and got the same error for all three ivars. I didn't even hookup or use the ivars in a method. The fix for me was to explicitly declare the attributes.

Code:
@property (nonatomic, strong) UIButton *purchaseButton;
@property (nonatomic, strong) UILabel *productLabel;
@property (nonatomic, strong) UITextView *productDetails;
I think I also saw this problem last week when I had two objects importing each other. So I'm thinking a circular reference could confuse the compiler.

By the way, you may be able to save your self some typing by not declaring the ivars in the braces and just doing this.

Code:
@property (nonatomic, strong) IBOutlet UIButton *purchaseButton;
@property (nonatomic, strong) IBOutlet UILabel *productLabel;
@property (nonatomic, strong) IBOutlet UITextView *productDetails;
 
Last edited:

admanimal

macrumors 68040
Apr 22, 2005
3,531
2
I think I also saw this problem last week when I had two objects importing each other. So I'm thinking a circular reference could confuse the compiler.
It has nothing to do with IBOutlets or circular references. The error is caused by conflicting default ownership specifiers between the explicit ivars and corresponding properties.

By explicitly declaring the properties as strong, you are making them match the ivars' default ownership (also strong) and therefore removing the conflict. The default ownership of properties is assign.

Of course the other solution as you pointed out is to simply not bother declaring the ivars at all and let the compiler create them based on the properties, which it will do without any conflicts.
 

ArtOfWarfare

macrumors G3
Original poster
Nov 26, 2007
8,703
4,328
Xstep's code compiled, but it didn't work on account of the fact I wanted to change the text inside the label inside of prepareForSeque:sender:

This caused an issue because prepareForSeque: was called before the view finished loading.

So instead I made my IBOutlets as ivars and had NSStrings as properties. Inside of prepareForSeque, the NSString was assigned what I wanted the contents of the labels to be, and then inside of viewWillAppear (which is called after the view finishes loading,) I changed the text of all my labels to match up with the NSStrings.
 

xStep

macrumors 68020
Jan 28, 2003
2,013
100
Less lost in L.A.
I haven't been able to find a reference to verify this, but I'm pretty sure the problem has to do with conflicting ownership specifiers for your ivars/properties.
I think the reference you are looking for is the Clang page about 'Automatic Reference Counting' where they talk about Ownership qualification.


It has nothing to do with IBOutlets or circular references. The error is caused by conflicting default ownership specifiers between the explicit ivars and corresponding properties.
I didn't say IBOutlets had anything to do with the issue. As for the circular references, I'll ignore that since I couldn't back track my code to review what the mess was. I wouldn't doubt that I was having multiple issues that confused me. :eek:


Although I don't think this is what ArtOfWarfare wants, an alternative to get rid of the error is the following. I wonder if there is a scenario one would want to do this with UI elements. Anyway, it just shows that matching the qualifiers supports your thinking.

Code:
@interface ProductViewController : UIViewController
	IBOutlet [COLOR="Red"]__weak[/COLOR] UIButton		*purchaseButton;
	IBOutlet [COLOR="DarkOrange"]__unsafe_unretained[/COLOR] UILabel	*productLabel;
	IBOutlet __unsafe_unretained UITextView	*productDetails;
}

@property ([COLOR="red"]weak[/COLOR]) UIButton *purchaseButton;
@property ([COLOR="DarkOrange"]assign[/COLOR]) UILabel *productLabel;
@property (assign) UITextView *productDetails;

@end
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.