我有两个以某种方式相互关联的 Objective-C 对象。您可能会认为这是一种双向关系。使用 ARC,我知道父对象应该持有对其子对象的强引用,而子对象持有指向其父对象的弱引用。但是如果父母可以是任何一个对象呢?或者如果对象是“兄弟姐妹”?
假设我有一个 Person 类,我想实例化两个其兄弟属性相互指向的对象。
@implementation Person
@property (strong, nonatomic) Person *brother;
Person personA = [Person new];
Person personB = [Person new];
personA.brother = personB;
personB.brother = personA;
这不会导致保留周期吗?
这是另一种情况:假设我有一个 Appointment 类和 Staff 类。
@implementation Appointment
@property (strong, nonatomic) Staff *staff;
@implementation Staff
@property (strong, nonatomic) NSArray *appointments;
在视图人员中,我可能想显示所有工作人员的约会。因此我可能会像这样实例化我的所有对象......
Staff *bob = [Staff new];
Appointment *apptA = [Appointment new];
Appointment *apptB = [Appointment new];
apptA.staff = bob;
apptB.staff = bob;
bob.appointments = [NSArray arrayWithObjects:apptA, apptB, nil];
由于所有引用都很强大,这不会导致保留周期吗?
最后,考虑这种情况:假设我将 Appointment 的人员属性更改为 weak。
@implementation Appointment
@property (weak, nonatomic) Staff *staff;
这可能会解决我的第二个问题(上述场景),但是如果我正在创建一个新约会并且我想附加一个新员工,然后将对象传递到其他地方进行处理怎么办?
+ (void)buildAppointment {
Appointment *appt = [Appointment new];
Staff *staff = [Staff new];
appt.staff = staff;
[self saveAppointment:appt];
}
+ (void)saveAppointment:(Appointment *)appt {
// Do something with appt here.
// Will I still have appt.staff?
}
因为我在 Appointment 上的工作人员属性现在很弱,当垃圾收集运行时是否有可能将其设置为 nil(因为没有对工作人员对象的强引用)?
编辑:正如@dasblinkenlight 解释的那样,该app.staff
对象仍然存在,因为局部staff
变量(来自buildAppointment
)仍在堆栈上。但是,如果我有:
+ (void)createAndSaveAppointment {
Appointment *appointment = [self createAppointment];
[self saveAppointment:appointment];
}
+ (Appointment *)createAppointment {
Appointment *appt = [Appointment new];
Staff *staff = [Staff new];
appt.staff = staff;
return appt;
}
+ (void)saveAppointment:(Appointment *)appt {
// Do something with appt here.
// Will I still have appt.staff?
}
我的同事似乎通过使用两个属性来处理它,一个强,另一个弱:
@implementation Appointment
@property (strong, nonatomic) Staff *staffStrong;
@property (weak, nonatomic) Staff *staffWeak;
- (Staff *)staff {
if (staffStrong != nil) {
return staffStrong;
}
return staffWeak;
}
- (void)setStaffStrong:(Staff *)staff {
staffStrong = staff;
staffWeak = nil;
}
- (void)setStaffWeak:(Staff *)staff {
staffStrong = nil;
staffWeak = staff;
}
然后在设置人员属性时,他们将酌情使用 setStaffStrong 或 setStaffWeak。然而,这似乎很 hacky——肯定有更优雅的解决方案吗?你将如何构建你的类来处理我的上述场景?
PS:我为这个冗长的问题道歉;我尽力解释它。:)