Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIView as dictionary key?

I want to have a NSDictionary that maps from UIViews to something else.

However, since UIViews do not implement the NSCopying protocol, I can't use them directly as dictionary keys.

like image 218
mrueg Avatar asked Jun 07 '10 19:06

mrueg


3 Answers

You can use an NSValue holding the pointer to the UIView and use this as key. NSValues are copyable. but, if the view is destroyed, the NSValue will hold a junk pointer.

like image 172
luvieere Avatar answered Oct 05 '22 20:10

luvieere


Here is the actual code (based on the answer by luvieere and further suggestion by Yar):

// create dictionary
NSMutableDictionary* dict = [NSMutableDictionary new];
// set value
UIView* view = [UILabel new];
dict[[NSValue valueWithNonretainedObject:view]] = @"foo";
// get value
NSString* foo = dict[[NSValue valueWithNonretainedObject:view]];
like image 26
Rok Strniša Avatar answered Oct 05 '22 20:10

Rok Strniša


Although this isn't really what they're intended for, you could whip up a functional dictionary-like interface using Associative References:

static char associate_key;
void setValueForUIView(UIView * view, id val){
    objc_setAssociatedObject(view, &associate_key, val, OBJC_ASSOCIATION_RETAIN);
}

id valueForUIView(UIView * view){
    return objc_getAssociatedObject(view, &associate_key);
}

You could even wrap this up in a class ThingWhatActsLikeADictionaryButWithKeysThatArentCopyable*; in that case you might want to retain the views that you use as keys.

Something like this (untested):

#import "ThingWhatActsLikeADictionaryButWithKeysThatArentCopyable.h"
#import <objc/runtime.h>

static char associate_key;

@implementation ThingWhatActsLikeADictionaryButWithKeysThatArentCopyable

- (void)setObject: (id)obj forKey: (id)key
{
    // Remove association and release key if obj is nil but something was
    // previously set
    if( !obj ){
        if( [self objectForKey:key] ){
            objc_setAssociatedObject(key, &associate_key, nil, OBJC_ASSOCIATION_RETAIN);
            [key release];

        }
        return;
    }

    [key retain];
    // retain/release for obj is handled by associated objects functions
    objc_setAssociatedObject(key, &associate_key, obj, OBJC_ASSOCIATION_RETAIN);
}

- (id)objectForKey: (id)key 
{
    return objc_getAssociatedObject(key, &associate_key);
}

@end

*The name may need some work.

like image 42
jscs Avatar answered Oct 05 '22 21:10

jscs