Note that there are some explanatory texts on larger screens.

plurals
  1. POHow do I use strong and weak with sibling objects (either can be the parent) in Objective-C ARC?
    primarykey
    data
    text
    <p>I have two Objective-C objects that relate to each other in some way. You may think of this as a two-way relationship. With ARC, I understand that the parent should hold a strong reference to its child object, while the child holds a weak reference pointing back to its parent. But what if the parent can be either object? Or if the objects are "siblings"?</p> <p>Let's say I have a Person class and I would like to instantiate two objects whose brother properties point to each other.</p> <pre class="lang-c prettyprint-override"><code>@implementation Person @property (strong, nonatomic) Person *brother; Person personA = [Person new]; Person personB = [Person new]; personA.brother = personB; personB.brother = personA; </code></pre> <p>Wouldn't this lead to a retain cycle?</p> <p>Here's another scenario: Let's say I have an Appointment class and Staff class.</p> <pre class="lang-c prettyprint-override"><code>@implementation Appointment @property (strong, nonatomic) Staff *staff; @implementation Staff @property (strong, nonatomic) NSArray *appointments; </code></pre> <p>On a view staff, I may want to show all the staff member's appointments. Therefore I might instantiate all my objects like so...</p> <pre class="lang-c prettyprint-override"><code>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]; </code></pre> <p>Wouldn't this lead to a retain cycle since all the references are strong?</p> <p>Finally, consider this scenario: Let's say I change Appointment's staff property to weak.</p> <pre class="lang-c prettyprint-override"><code>@implementation Appointment @property (weak, nonatomic) Staff *staff; </code></pre> <p>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 new staff member, then pass the object somewhere else for processing?</p> <pre class="lang-c prettyprint-override"><code>+ (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? } </code></pre> <p>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)?</p> <p><strong>EDIT:</strong> As <a href="https://stackoverflow.com/users/335858/dasblinkenlight">@dasblinkenlight</a> <a href="https://stackoverflow.com/a/18158285/493229">explained</a>, the <code>app.staff</code> object would still exist as the local <code>staff</code> variable (from <code>buildAppointment</code>) is still on the stack. However, what if I had:</p> <pre class="lang-c prettyprint-override"><code>+ (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? } </code></pre> <p>My co-workers seem to have handled it by using two properties, one strong and the other weak:</p> <pre class="lang-c prettyprint-override"><code>@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; } </code></pre> <p>Then when setting the staff property, they would use the setStaffStrong or setStaffWeak as appropriate. However this seems very hacky — surely there is a more elegant solution? How would you build your classes to handle my above scenarios?</p> <p>PS: My apologizes for the long question; I tried to explain it as best I could. :)</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload