One general note on the strong vs. weak reference: strong references denote ownership, while weak references denote association. When neither object owns the other, there's usually other objects that own them, or they both have strong references coming from local variables.
Wouldn't [the
Person
class] lead to a retain cycle?
Yes, it would, because a Person
owns his brother, but he shouldn't: this should be a weak property. It should be OK, because there should be another object (a list of all persons, a dictionary organizing persons by name, or something like it) that owns all of the Person
objects. As long as a Person
object is in that collection of persons, it's not going to be released.
Wouldn't [
Appointment
andStaff
] lead to a retain cycle since all the references are strong?
Correct, that is what is going to happen. NSArray
retains objects that go into it, closing the loop on the retain cycle. Note that you cannot make NSArray
weak to break that cycle: it needs to be Staff
that gets weak, not appointments
.
Finally, consider this scenario: Let's say I change
Appointment
'sstaff
property toweak
. This may solve the issue for my second (above scenario), but what if I am creating a new appointment and I want to attach a staff member, then pass the object somewhere else for processing?
There's no problem with that: stack variable staff
has a strong reference on it, so it wouldn't get released.
Because my
staff
property on Appointment is now weak, is there the potential for it to be set to nil when garbage collection runs (as there are no strong references to the staff object)?
ARC is not a garbage collection system: retains and releases happen at specific, deterministic time points. The staff
is not going to be released, because Staff *staff = [Staff new];
is strong by default.
EDIT : The edited example will indeed release the Staff
object. However, such example is unusual, because it is unlikely that your createAppointment
would make a new instance of Staff
. Rather, it would grab an existing instance from some registry containing all members of staff, like this:
+ (Appointment *)createAppointment {
Appointment *appt = [Appointment new];
// Registry gives you a reference to an existing Staff.
// Since the object remains registered, that's not the last strong reference.
Staff *staff = [staffRegistry reserveMember];
appt.staff = staff;
return appt;
}
staffRegistry
is a class that manages (and owns) all Staff
objects, keeping them in an array, a dictionary, or some other collection. All other references to Staff
objects (apart from temporary references by stack variables) should be weak. This way removing a member from the registry will also release him from all the appointment objects in which he may participate.
My co-workers seem to have handled it by using two properties, one strong and the other weak
If you are thinking it's a hack, you are 100% right. The strong vs. weak issue gets straightforward once you make a decision on who knows what; you don't need to come up with code that promises some serious maintenance nightmare to address it.