2010-06-07 85 views
27

我想有一个NSDictionaryUIView s映射到其他东西。UIView作为字典键?

但是,由于UIViews没有实现NSCopying协议,我不能直接将它们用作字典键。

+1

相关:http://stackoverflow.com/questions/1497622/nsmanagedobject-as-nsdictionary-key – kennytm 2010-06-07 19:10:16

+0

这听起来像是一个非常糟糕的主意。 – 2010-06-07 19:56:26

+0

只有当您不知道数据可能变成垃圾时(正如接受的答案指出的那样)。 – mrueg 2010-06-08 10:21:44

回答

30

您可以使用保存指向UIView的指针的NSValue并将其用作关键字。 NSValues 是可复制的。但是,如果视图被破坏,NSValue将保留 垃圾指针。

+0

太棒了!我正在将UIView的散列用作int来使用NSNumber。我认为这更好。 – 2011-09-18 23:45:17

+7

现在用ARC你必须使用'valueWithNonretainedObject'。 – 2011-09-18 23:50:46

+0

@Yar下面是使用luvieere和你自己的建议的实际代码:http://stackoverflow.com/a/11387017/974531 – 2012-07-11 08:50:36

17

下面是实际的代码(基于the answer by luvieere,并进一步建议由亚尔):

// 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]]; 
+0

如何检查视图是否被释放? – 2016-03-15 14:44:14

4

虽然这不是真的他们打算是什么,你可能会掀起一个功能类似于字典的接口使用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); 
} 

你甚至可以在类ThingWhatActsLikeADictionaryButWithKeysThatArentCopyable包装这件事。*;在这种情况下,您可能希望保留您用作键的视图。

像这样(未经):

#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 

*名称可能需要一些工作。

1

与其存储指向视图的指针并冒着垃圾问题的风险,只需给UIView一个标签并将标签的值存储在字典中即可。更安全。

0

我在Objective-C++提供的ARC下使用了一个简单的解决方案。

MyClass.mm:

#import <map> 

@implementation MyClass 
{ 
    std::map<UIView* __weak, UIColor* __strong> viewMap; 
} 

- (void) someMethod 
{ 
    viewMap[self.someView] = [UIColor redColor]; 
} 

在这个例子中,我通过使所有的值越来越强类型检查必须是UIColor*这是我所需要的本作。 std::map<UIView* __weak, id __strong> viewMap;同样的键:id __weak, id __strong> viewMap;

你也可以改变__strong__weak的属性需要的,但你也可以,如果你想允许任何对象作为值,前使用id作为值类型。在我的情况下,视图控制器已经保留了视图,我使用这个视图,所以我没有看到需要强大的指针。

+1

NSMapTable也提供了这个。 C.F. '[NSMapTable weakToStrongObjectsMapTable]' – nielsbot 2014-05-12 21:09:02

4

如果您在iOS 6之前不需要支持,NSMapTable(由neilsbot建议)可以很好地工作,因为它可以提供枚举器来覆盖集合中的键。这对所有文本字段通用的代码都很方便,例如设置委托或双向同步NSUserDefaults实例的文本值。

在viewDidLoad中

self.userDefFromTextField = [NSMapTable weakToStrongObjectsMapTable]; 
[self.userDefFromTextField setObject:@"fooUserDefKey" forKey:self.textFieldFoo]; 
[self.userDefFromTextField setObject:@"barUserDefKey" forKey:self.textFieldBar]; 
// skipped for clarity: more text fields 

NSEnumerator *textFieldEnumerator = [self.userDefFromTextField keyEnumerator]; 
UITextField *textField; 
while (textField = [textFieldEnumerator nextObject]) { 
    textField.delegate = self; 
} 

在viewWillAppear中:

NSEnumerator *keyEnumerator = [self.userDefFromTextField keyEnumerator]; 
UITextField *textField; 
while (textField = [keyEnumerator nextObject]) { 
    textField.text = [self.userDefaults stringForKey:[self.textFields objectForKey:textField]]; 
} 
在文本框

:shouldChangeCharactersInRange:replacementString:

NSString *resultingText = [textField.text stringByReplacingCharactersInRange:range withString:string]; 
if(resultingText.length == 0) return YES; 

NSString *preferenceKey = [self.textFields objectForKey:textField]; 
if(preferenceKey) [self.userDefaults setString:resultingText forKey:preferenceKey]; 
return YES; 

现在我会去哭,因为我实现了这一切在意识到我的iOS 5.1目标应用程序不能使用它之前。 NSMapTable在推出的iOS 6

+0

这是一个很好的解决方案! – 2016-04-18 08:19:09

0

一个简单的解决方案时,你只是想UIView为重点偶尔,我用它来存储UILabelUIColor

NSArray<UIView *> *views = @[viewA,viewB,viewC,viewD]; 
NSArray *values = @[valueA,valueB,valueC,valueD]; 

for(int i = 0;i < 4;i++) { 
    UIView *key = views[i]; 
    id value = values[i] 
    //do something 
} 

id value = values[[views indexOfObject:key]]