objc_getAssociatedObject返回null

时间:2013-11-12 15:21:00

标签: ios objective-c-runtime

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

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

以下是我如何得到它:

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

两个实例中的对象都是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;

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

3 个答案:

答案 0 :(得分:5)

这是一个黑暗中的镜头,因为我无法重现这个问题。问题可能是 key的{​​{1}}参数是唯一的指针

因此,如果两个不同的类使用字符串,则代码将无效 objc_set/getAssociatedObject()位于不同的内存位置。字符串具有相同的内容, 但指针是不同的。

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

  • 在公共头文件(或.pch文件)中放入"rightButton"声明:

    extern
  • 中只有一个 .m文件定义变量。 “自引用”保证指针具有唯一值:

    extern const void *rightButtonKey;
    
  • 然后像

    一样使用它
    const void *rightButtonKey = &rightButtonKey;
    

答案 1 :(得分:2)

您使用不同的密钥:您为密钥"leftButton"设置对象并获取"rightButton"

答案 2 :(得分:2)

引用famous person

  

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

由于所有其他猜测都是错误的,我能想到的唯一问题的另一个原因是你在某个时候正在调用objc_removeAssociatedObjects()。在您的问题中,您说您的代码曾经工作过,所以我们必须假设某些地方发生了变化,导致执行路径突然变得不同。

  • 可能性1:执行路径现在通过该objc_removeAssociatedObjects()的调用,之前没有。{/ li>
  • 可能性2:您之前已经调用了objc_removeAssociatedObjects(),但现在您正在为该函数传递不同的值。

不可能说出那两者中的哪一个。

您在评论中说,您没有通过相关的navigationItem并要求解释。不幸的是我不能提供一个。根据我目前的知识,我必须假设您的声明或Apple docs for the function不正确。由于objc_removeAssociatedObjects()过去对我有用,我自然倾向于相信Apple: - )

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