【问题标题】:NSMutableDictionary with UIButton* as keys - iPhone developmentNSMutableDictionary 与 UIButton* 作为键 - iPhone 开发
【发布时间】:2010-05-12 15:38:09
【问题描述】:

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

【问题讨论】:

    标签: uibutton nsmutabledictionary


    【解决方案1】:

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

    [NSValue valueWithNonretainedObject:myButton]

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

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

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

    【讨论】:

    • 我也面临同样的问题。你能否详细说明如何实现这个技巧。我试过这样做:-但应用程序崩溃了。 NSDictionary *catPassdict=[NSDictionary 字典]; [catPassdict setValue:[NSValue valueWithNonretainedObject:catAppButton] forKey:@"btn"];
    【解决方案2】:

    来自Apple docs

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

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

    【讨论】:

    • 我就是这么想的,那么您对如何解决这个问题有什么建议吗?给定一个 UIButton,我需要获取该按钮所代表的自定义类。如果我不能使用字典,则必须有另一种方法来做到这一点。我不能使用数组,因为几个 UIButtons 可以引用同一个对象。有没有办法给按钮代表的类的id?或者类似的东西?
    【解决方案3】:

    我有一个很酷的技巧。

    我将指针转换为 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];
    }
    

    【讨论】:

    • 还有一个很酷的技巧:使用表单中提供的内置标记而不是 html-tags。
    【解决方案4】:

    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
    

    【讨论】:

    • 如果有多个 UIButton 被用作字典中的键,是否可以保证每个 UIButton 的 description 属性值都有一个唯一的、不变的值? (我尝试采用这种方法并自己设置 description 属性值,但它是只读的。)
    • 我将此解决方案与多个 UIButton 一起使用,效果很好。就我而言,不需要自定义描述。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多