Turn an IBOutlet into a property?

Discussion in 'iOS Programming' started by ArtOfWarfare, Dec 30, 2011.

  1. ArtOfWarfare macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #1
    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;
    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...
     
  2. admanimal macrumors 68040

    Joined:
    Apr 22, 2005
    #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.
     
  3. xStep, Dec 31, 2011
    Last edited: Dec 31, 2011

    xStep macrumors 68000

    Joined:
    Jan 28, 2003
    Location:
    Less lost in L.A.
    #3
    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;
     
  4. admanimal macrumors 68040

    Joined:
    Apr 22, 2005
    #4
    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.
     
  5. ArtOfWarfare thread starter macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #5
    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.
     
  6. xStep macrumors 68000

    Joined:
    Jan 28, 2003
    Location:
    Less lost in L.A.
    #6
    I think the reference you are looking for is the Clang page about 'Automatic Reference Counting' where they talk about Ownership qualification.


    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
     

Share This Page