Reed
Reed

Reputation: 14984

Custom UIView variable / property Access

I've managed to setup a custom UIView class with a nib.

My .h looks like

@interface MyView : UIView <UITextFieldDelegate>

@property (nonatomic, weak) IBOutlet UITextField *textField;
@property (nonatomic, strong) MyView *topView;

And .m

 @implementation MyView

NSString *_detail;

    -(id)initWithCoder:(NSCoder *)aDecoder{
            if ((self = [super initWithCoder:aDecoder])&&self.subviews.count==0){

                MyView *v = [[[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self options:nil] objectAtIndex:0];
                self.textField = v.textField;
                if (self.topView == nil)self.topView = self;
                v.topView = self.topView;
                [self addSubview:v];
            }
            return self;
        }


    -(NSString *)topDetail{
        return _detail;
    }
    -(NSString *)detail{
        return [self.topView topDetail];
    }
    -(void)setTopDetail:(NSString *)detail{
        _detail = detail;
    }
    -(void)setDetail:(NSString *)detail{
        [self.topView setTopDetail:detail];
    }
    - (BOOL)textFieldShouldReturn{
        //here I show an UIAlertView using self.detail for the message
    }

Note: The setup I have works exactly how I want it to.

The problem
What I would like to do is remove my manual detail methods and turn NSString *_detail into @property (...)NSString *detail

When I try it with the @property, then within my ViewController if i call
myView.detail = someString, myView will be referring to the top most view. Then if textFieldShouldReturn gets called because of user interaction, then it calls the nested MyViews _detail which has not been set.

What I want: To not have to write extra code for access to _detail regardless of where I'm accessing it from. I want to merely declare the property and go on with my usual coding.

Upvotes: 1

Views: 1008

Answers (2)

Reed
Reed

Reputation: 14984

My xib contained one UIView (no controller). I had the UIView set to MyView for the class.

I changed the UIView back to just UIView then set File's Owner to MyView. This solved issues of recursion (which is why I had such a weird setup in the first place) and caused my variables and IBOutlets to be linked up properly.

Credit goes to How do I create a custom iOS view class and instantiate multiple copies of it (in IB)? and some of the comments which I missed the first couple times I read through it.

Upvotes: 0

E. Rivera
E. Rivera

Reputation: 10938

Your problem is that you're trying to keep the a class reference, topView, with an object property.

In other words every objects' topView is the object itself, which makes no sense.

Your definition should be:

@interface MyView : UIView <UITextFieldDelegate>

// Class "properties"
+ (instancetype)topview;
+ (void)setTopView:(UIView *)topView;

// Object properties
@property (nonatomic, weak) IBOutlet UITextField *textField;
@property (nonatomic, strong) NSString *detail;

Now you can keep track of the topView:

 static MyView * _topView;

 @implementation MyView

+ (instancetype)topView {return _topView}; // You could also create one here lazily
+ (void)setTopView:(UIView *)topView { _topView = topView };

-(id)initWithCoder:(NSCoder *)aDecoder{
            if ((self = [super initWithCoder:aDecoder])&&self.subviews.count==0){

                JUITextFieldHint *v = [[[NSBundle mainBundle] loadNibNamed:@"JUITextFieldHint" owner:self options:nil] objectAtIndex:0];
                self.textField = v.textField;
                if ([MyView topView] == nil)[MyView setTopView:self];
                v.topView = self.topView;
                [self addSubview:v];
            }
            return self;
        }

No more need for manual setters and getters. Now you can use your detail property, either with anyInstance.detail or [MyView topView].detail, or even MyView.topView.detail if you like dots like me ;)

You're init method still looks weird but should work. Check Apples init template.

Lastly, textField can be weak as long as it has a superview, otherwise make it strong.

Upvotes: 1

Related Questions