【问题标题】:Conditionally make a @property strong or weak有条件地使@property 强或弱
【发布时间】:2013-06-06 19:52:34
【问题描述】:

我正在从 API 下载对象列表以显示给用户。该列表混合了两种类型的对象。想象一下,它们是书籍和作者的组合,类定义如下所示:

@interface Book : NSObject

@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) Author *author;

@end

@interface Author : NSObject

@property (nonatomic, strong) NSString *fullName;
@property (nonatomic, weak) Book *book;

@end

每个Book 都可以从API 下载其Author 信息,反之亦然。

如果 API 给我一个Book,我可以在下载它后设置它的author 属性。 Author 对象通过book 属性指向Book,但这不会创建ARC Retain Cycle,因为book 属性是weak

但是,如果 API 先给我一个Author,然后我下载它的Book,那么一旦我设置它的方法返回,该对象就会被释放,因为相同的属性是weak

我想了几个办法解决这个问题:

  • 创建一个存储两者的Content 对象(不适用于多对多关系)
  • 创建单独的strongBookweakBook 属性,然后创建一个名为bookreadonly 属性,该属性检查哪个设置并返回那个

这两个对我来说似乎都很乱,虽然第二个选项更可取。

有没有办法使用 Objective-C 运行时将属性从 weak 动态更改为 strong(反之亦然)?

更新:我收到了一些关于如何解决该问题的建议,我自己想出这些建议并不困难。这个问题具体是关于是否有办法(a)为类的特定实例动态重新定义@properties,或(b)在特定情况下覆盖AR​​C的retain/release行为(因为这个问题不会' t 存在于 MRC 中)。

【问题讨论】:

  • 修复您的 API 定义。就是这么简单。
  • 为什么不让它们都变弱,然后保留所有书籍和作者的 NSArray 以保留它们?
  • @RichardJ.RossIII 是的,但在这种情况下我需要解决它。
  • @EricS 这可以工作,但是当我想删除一个项目时,我还有另一个维护点。
  • 作者要弱,书要强,反之不行。因此,如果一本书只有一个作者,则保留 1 次。你这样做的方式一个作者被保留 N 次。

标签: ios objective-c macos properties objective-c-runtime


【解决方案1】:

只是在黑暗中拍摄,但您可以创建属性而不指定,然后将动态与运行时 api 一起使用。我没有测试它,但我认为它应该可以工作:

//.h file
#import <Foundation/Foundation.h>

@interface SomeObject : NSObject
@property(nonatomic) NSObject *object;
@end


//.m file
#import "SomeObject.h"
#import <objc/runtime.h>
@implementation SomeObject
@dynamic object;

-(void)setObject:(NSObject *)object
{
    BOOL isWeak = NO;
    if(isWeak)
    {
        objc_setAssociatedObject(self, "object", object, OBJC_ASSOCIATION_ASSIGN);
    }
    else
    {
        objc_setAssociatedObject(self, "object", object, OBJC_ASSOCIATION_RETAIN);
    }
}

-(NSObject *)object
{
    return objc_getAssociatedObject(self, "object");
}

@end

【讨论】:

  • 这行得通。 (我最终制作了一个带有额外参数的 setter,例如 -[SomeObject setObject:isWeak:])。
  • 我会非常小心这个答案中建议的方法。使用“OBJC_ASSOCIATION_ASSIGN”,您可以创建等效于 assign/unsafeUnretained 的属性,而绝对不是 weak - 当对象被释放时,该属性不会自动设置为 nil。因此,如果您尝试访问该属性,您的应用程序将会崩溃。
【解决方案2】:

在下载期间,创建一个可变字典来临时存储在图书之前到达的作者对象。收到书后,查看该数组并查看作者信息是否存在,如果有,请附上。完成后清除可变数组。

【讨论】:

  • @RamyAlZuhouri,他必须查看集合中的每个项目才能找到合适的作者。假设有一些标识符可以用作键,字典为您提供了一种快速找到正确的方法。实际上,我以前曾多次使用过这种技术,而且取得了巨大的成功。
猜你喜欢
  • 2014-02-15
  • 1970-01-01
  • 2013-05-10
  • 1970-01-01
  • 2018-07-04
  • 2014-01-03
  • 1970-01-01
  • 2012-07-07
  • 2012-04-09
相关资源
最近更新 更多