NSMutableDictionary以UIButton *作为键 - iPhone开发

时间:2010-05-12 15:38:09

标签: uibutton nsmutabledictionary

我是iPhone开发的新手,我有一个问题可能有一个非常简单的答案。我正在尝试向视图添加按钮,这些按钮与我定义的自定义类相关联。当我将按钮添加到视图时,我想知道这些按钮对应的类。这是因为当我按下按钮时,我需要获得有关该类的一些信息,但是消息的接收者是另一个类。我无法找到有关我在网上收到的错误的信息。我遇到的问题是我正在尝试创建一个NSMutableDictionary,其中键的类型为UIButton *,值是我的自定义类型:

   // create button for unit
   UIButton* unitButton = [[UIButton alloc] init];
   [sourceButtonMap setObject:composite forKey:unitButton];

当然,sourceButtonMap在类中定义,并在init函数中初始化为sourceButtonMap = [[NSMutableDictionary alloc] init];

我尝试添加键值对时得到的错误是:

  

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UIButton copyWithZone:]: unrecognized selector sent to instance 0x3931e90'

这是否发生是因为我无法将UIButton *存储为密钥? 谁能指出我为什么会收到这个错误?谢谢大家,

AA

4 个答案:

答案 0 :(得分:16)

我发现的一种方法是使用构造NSValue作为关键。要创建该用途:

[NSValue valueWithNonretainedObject:myButton]

这里需要注意的是,如果按钮被垃圾收集,该密钥将保留无效的引用。

您可以在循环浏览字典时再次获取对UIButton的引用,如下所示:

for (NSValue* nsv in myDict) {
    UIButton* b = (UIButton*)[nsv nonretainedObjectValue];
    ...
}

答案 1 :(得分:3)

来自Apple docs

  

复制密钥(使用   copyWithZone:;钥匙必须符合   NSCopying协议)。

UIButton不符合NSCopying协议,因此您不能将其用作NSDictionary中的密钥

答案 2 :(得分:2)

我有一个很酷的技巧。

我将指针转换为int(因为所有指针都是真的)并将其存储在NSNumber中。使用NSNumber作为键可以解决这个问题并且有意义,因为谁关心在按字典中存储按钮的副本?存储指针信息的副本对我来说更有意义。

如果你喜欢我,你也可能将这一点包装成一个宏。像这样:

#define BOX_AS_NUM(_ptr_) [NSNumber numberWithInt:(int)_ptr_]

然后在代码中使用它会更清晰......

NSDictionary* btnMap = [NSDictionary dictionaryWithObjectsAndKeys:some_obj, BOX_AS_NUM(some_btn), nil];
-(IBAction)someBtnAction:(id)sender
{
    SomeObj* obj = [btnMap objectForKey:BOX_AS_NUM(sender)];
    [obj doCoolStuffBecuaseIWasJustClicked];
}

答案 3 :(得分:2)

UIButtons具有description属性,可用作字典键:

NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] initWithCapacity:1];
UIButton *myButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 10.0f, 10.0f)];
id myObject;
[myDictionary setObject:myObject forKey:myButton.description];

// somewhere else in code
id myLookedUpObject = [myDictionary objectForKey:myButton.description];
// do something with myLookedUpObject