Pregunta

I am trying to create a custom category to extend the functionality of a UIViewController, and within this category I would like to store a pointer to a view for reuse. I'm using associative references as described by Ole Begemann. However, it seems that while the associative reference itself can store and retrieve a UIView, adding that UIView to the currentView will add the view as a subview, but a subsequent comparison such as [self.view.subviews containsObject:self.storedView] will always return NO even if self.storedView (an associative reference) has indeed been added to self.view. Additionally, code like self.storedView.superview will always turn up nil even if self.storedView has been added to the view hierarchy. I'm guessing this is because I'm not fully understanding how associative references work.

Any ideas what might be going wrong? I can provide a code sample if that would helpful.

Thank you!


UPDATE 1: Here is a code snippet on how I am creating self.storedView in the category via an associative (associated?) reference and then attempting to add and remove it from the view controller's view via IBAction methods.

//  UIViewController+TestCategory.m

#import <objc/runtime.h>

static char const * const StoredViewKey = "storedView";

- (void)setStoredView:(UIView *)storedView
{
    objc_setAssociatedObject(self, StoredViewKey, storedView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIView *)storedView
{
    UIView *storedView = objc_getAssociatedObject(self, StoredViewKey);
    if (!storedView)
    {
        storedView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.bounds.size.width/2.0, self.view.bounds.size.height/2.0)];
        [storedView setBackgroundColor:[UIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:0.25]];
        [storedView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin)];
    }
    return storedView;
}

- (IBAction)buttonActionAddStoredView:(id)sender
{
    if (![self.view.subviews containsObject:self.storedView]) // always returns YES
    {
        [self.view addSubview:self.storedView];
    }
}

- (IBAction)buttonActionRemoveStoredView:(id)sender
{
    if ([self.view.subviews containsObject:self.storedView]) // always returns NO
    {
        [self.storedView removeFromSuperview];
    }
}
¿Fue útil?

Solución

I don't think this is related to your problem, however -storedView does a lazy creation if it can't find the stored view (which is fine), BUT it doesn't associated that view it just created. I would have it store the view as well, that way there's no chance of it returning a new object that isn't associated.

Second, I'll admit I've not used that static char const * const method of keying so I don't know if it could be giving you grief (a quick google shows others on SO are posting questions about associate issues and using the same keying method). There's another method of keying the associated objects which I use (and know is working) wherein you use the selector for the property/method that 'owns' that associated object as the key. It results in less code, and is self documenting which I'm a big fan of.

objc_setAssociatedObject(self, @selector(storedView), storedView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top