ios - child 失去了对 parent 的弱引用

标签 ios objective-c automatic-ref-counting

我有一个 AMContact 对象,其中一个强大的属性是 AMEmailAddress 对象数组。一个联系人可以有多个电子邮件地址。我可以在我的电子邮件地址对象上创建一个指向联系人对象的强属性吗?

我觉得如果它是一个强引用,就可以有一个保留周期。如果我让它变弱,当我查询以获取所有电子邮件地址对象时,在某个时候每个人的联系人对象都会变成 nil。

- (NSArray*)allEmailAddresses
{
    NSArray *allContacts = [self allContacts];
    NSMutableArray *emailAddresses = [NSMutableArray array];

    for (AMContact *contact in allContacts) {
        if (contact.emailAddresses) {
            for (AMEmailAddress *address in contact.emailAddresses) {
                [emailAddresses addObject:address];
            }
        }
    }
    if (emailAddresses.count > 0) {
        return emailAddresses;
    }
    return nil;
} 


@interface AMContact : NSObject

@property (nonatomic, strong) NSString *firstName;
@property (nonatomic, strong) NSString *lastName;


// arrays of AMEmailAddress, AMPhoneNumber objects
@property (nonatomic, strong) NSArray *emailAddresses;
@property (nonatomic, strong) NSArray *phoneNumbers;

@end

@interface AMEmailAddress : NSObject

@property (nonatomic, strong) NSString *label;
@property (nonatomic, strong) NSString *email;
@property (nonatomic, strong) AMContact *contact; // IS THIS OK OR A RETAIN CYCLE?

@end

最佳答案

对您的问题的简短回答:我可以在我的电子邮件地址对象上创建一个指向联系人对象的强属性吗?

可以吗?是的。你应该?绝对不。您的模型设计已经暗示了这种关系应该是什么——AMContact 对象拥有电子邮件地址,而不是相反。让电子邮件地址具有对父对象的强引用并不是解决此问题的好方法。从 child 到所有者的引用应该很弱。您的 AMContact 实例将变为 nil 的事实是范围界定和设计的问题,您不应该使用强引用来解决这个问题。

至于为什么您的 AMContact 实例变为 nil - 这有点奇怪,因为如果 AMContact 对象变为 nil,它的子对象也应该变为 nil。它是在您发布的代码中变为零,还是在其他一些方法中变为零?看到你试图引用它的代码,它是零,这很好。

更新:

如果您想要一个包含电子邮件地址的联系人列表,您应该更改返回该地址的方法。但是我猜你的意思是你想要一个他们的电子邮件地址列表以及他们的相关联系人。在这种情况下,您将不得不翻转关系并将电子邮件视为父项,将联系人视为子项。请注意,如果一个联系人有多个电子邮件地址,那么您将有多个对同一联系人的引用。假设您的 AMEmailAddress 对象中有一个类型为 AMContactcontact 属性,我将添加一行如下:

for (AMEmailAddress *address in contact.emailAddresses) {

            //Assign the contact as a property of the email address
            //Make sure the contact property is strong
            address.contact = contact;

            [emailAddresses addObject:address];
        }

 //Nil out the emailAddresses array
 contact.emailAddresses = nil;

更新:

好的,现在您应该有一个翻转的对象 - emailAddress 作为父对象,contact 作为子对象,没有来自 contact 的强引用到 emailAddress 了。这意味着您将无法再次使用 contact 对象来获取电子邮件地址。如果您需要按原样维护原始 contact 对象,那么您是对的,您必须将其作为属性存储在 View Controller 或另一个类中 - 对于像这样的方法,我必须处理人员对象(允许用户邀请 friend 等)我使用“人员管理器”单例并将所有原始对象保留在那里。

关于ios - child 失去了对 parent 的弱引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20624067/

相关文章:

objective-c - NSString 让我大吃一惊

objective-c - 导致错误的对象的内存地址,找到哪个对象

ios - 从播放列表 Spotify 中获取所有轨道

ios - UIViewController 不保留其以编程方式创建的 UISearchDisplayController

ios - 我可以将 retain 与 ARC 一起使用吗?

java - Android 和 iOS 中的文件安全

ios - 通过适用于 iOS 的 Facebook SDK 在 Azure 移动服务上每天一次的身份验证问题(500 错误)

objective-c - 核心数据实体中 bool 属性的类型是什么?

ios - xcode 自定义叠加捕获

iOS:使用 ARC 在 UIScrollView 中延迟加载