10

我是 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* 存储为键吗?谁能指出我为什么会收到此错误?谢谢你们,

4

4 回答 4

16

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

[NSValue valueWithNonretainedObject:myButton].

这里的警告似乎是,如果按钮被垃圾收集,则密钥将持有无效引用。

您可以在遍历 Dictionary 时再次获得对 UIButton 的引用,如下所示:

for (NSValue* nsv in myDict) {
    UIButton* b = (UIButton*)[nsv nonretainedObjectValue];
    ...
}
于 2010-07-07T18:28:48.167 回答
3

来自苹果文档

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

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

于 2010-05-12T15:44:12.187 回答
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
于 2011-12-07T16:58:19.517 回答
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];
}
于 2011-05-15T04:29:29.627 回答