0

这是我设置关联对象的方法:

objc_setAssociatedObject(navigationItem, "rightButton", leftButtonView, OBJC_ASSOCIATION_RETAIN);

这就是我得到它的方法:

UIButton *favoriteButton = (UIButton *)objc_getAssociatedObject(self.navigationItem, "rightButton");

两个实例中的对象都是 a UIButton,我#import "objc/runtime.h"在两个类中都有。

问题是,它曾经可以工作,但现在由于某种原因它返回了null。有任何想法吗?

编辑

我通过navigationItem作为参数传递在另一个类中设置关联的对象:

+ (void)setNavigationBarTitle:(NSString *)title 
                andLeftButton:(NSString *)leftButtonTitle 
                 withSelector:(SEL)leftSelector 
               andRightButton:(NSString *)rightButtonTitle 
                 withSelector:(SEL)rightSelector 
                    andTarget:(id)target 
            forNavigationItem:(UINavigationItem *)navigationItem;

我在我的实用程序类中使用这种便捷方法为我的应用程序中的每个新视图控制器设置导航栏。创建导航栏按钮时,我将它们与导航项相关联 - 我在问题中的第一行代码。

4

3 回答 3

5

这是在黑暗中拍摄的,因为我无法重现该问题。问题可能在于 的key参数objc_set/getAssociatedObject()是唯一指针

"rightButton"因此,如果两个不同的类在不同的内存位置使用字符串,您的代码将无法工作 。字符串具有相同的内容,但指针不同。

在任何情况下,您都应该确保使用相同的来设置和检索关联的对象:

  • 在通用头文件(或 .pch 文件)中放置extern声明:

    extern const void *rightButtonKey;
    
  • 恰好一个.m 文件中定义变量。“自引用”保证指针具有唯一值:

    const void *rightButtonKey = &rightButtonKey;
    
  • 然后像这样使用它

    objc_setAssociatedObject(navigationItem, rightButtonKey, leftButtonView, OBJC_ASSOCIATION_RETAIN);
    
于 2013-11-12T20:14:33.867 回答
2

您使用不同的键:您为 key 设置对象"leftButton"并为"rightButton".

于 2013-11-12T15:24:37.613 回答
2

引用一位名人的话:

一旦你消除了不可能,剩下的无论多么不可能,都必须是事实。

由于所有其他猜测都是错误的,我能想到的唯一其他问题来源是你objc_removeAssociatedObjects()在某个时候打电话。在您的问题中,您说您的代码曾经可以工作,因此我们必须假设某处发生了变化,从而导致执行路径突然发生了变化。

  • 可能性 1:执行路径现在通过该调用到达objc_removeAssociatedObjects()之前没有的地方。
  • 可能性 2:您之前已经调用objc_removeAssociatedObjects()过,但现在您将不同的值传递给函数。

不可能说它是这两者中的哪一个。

您在评论中说您没有通过相关navigationItem问题并要求解释。不幸的是,我无法提供一个。根据我目前掌握的知识,我必须假设您的声明或该功能的 Apple 文档不正确。由于objc_removeAssociatedObjects()过去曾为我工作,我自然倾向于相信 Apple :-)

我可能会问:你是如何验证你没有将错误的对象传递给函数的?我的建议:NSLog在代码中添加两个语句,就在调用objc_getAssociatedObject()and之前objc_removeAssociatedObjects(),在其中打印要传递给两个函数的对象的指针。

于 2013-11-12T21:18:05.673 回答