Tag: reminders


ARC, Blocks, and retain cycle reminders

May 3rd, 2012 — 2:53pm

I’ve been neck-deep in Cocoa / iOS / mobile work lately, trying to inhale everything as quickly and thoroughly as possible. Each discovery of a new way of doing things is exciting – in exploring a new ecosystem, it’s been a blast being exposed to different design patterns, best practices, and libraries.

A fellow YCer introduced me recently to BlocksKit (and A2DynamicDelegate), two libraries that rejigger the standard delegate pattern of lots of the normal framework classes into a block. For example, consider the difference between the framework-standard code to show a UIActionSheet:

And the same logic, with BlocksKit:

This feels sturdier, more compact, and more straightforward – especially considering my Ruby background. In integrating BlocksKit into my project, though, I started running into whispers about retain cycles – specifically, a situation in which a class has a strong reference to a block, which in turn has strong references to the local variables (often members of the class!) it might use or call.

After reading a bunch of different blog posts and StackOverflow answers discussing the same issue, I wanted to consolidate / quote a few of the most useful sources. In short, whenever using blocks (especially in ARC-enabled code, which handles most of the memory management for you), developers need to watch out for retain cycles and break them if necessary.

Blocks in Objective-C have one more very important difference from blocks in C in handling variables that reference objects. All local objects are automatically retained as they are referenced! If you reference an instance variable from a block declared in a method, this retains self, as you’re implicitly doing self->theIvar.

source: Programming with C Blocks. Click through for code snippets, examples, and a deeper discussion of Memory Management in blocks (section 4.2).

The __block qualifier allows a block to modify a captured variable:

id x;
__block id y;
void (^block)(void) = ^{
    x = [NSString string]; // error
    y = [NSString string]; // works
};


Without ARC, __block also has the side effect of not retaining its contents when it’s captured by a block. Blocks will automatically retain and release any object pointers they capture, but __block pointers are special-cased and act as a weak pointer. It’s become a common pattern to rely on this behavior by using __block to avoid retain cycles.

Under ARC, __block now retains its contents just like other captured object pointers. Code that uses __block to avoid retain cycles won’t work anymore. Instead, use __weak as described above.

source: Mike Ash on ARC – scroll down to the section on blocks.

In retrospect, I read a good number of these posts when I was first exploring iOS and ARC – I suppose it’s a testament to how much content is in some of these articles (or the complexity of changing ecosystems?) that I didn’t make all of the connections / pick up all of the tips that I should have.

You can use lifetime qualifiers to avoid strong reference cycles. For example, typically if you have a graph of objects arranged in a parent-child hierarchy and parents need to refer to their children and vice versa, then you make the parent-to-child relationship strong and the child-to-parent relationship weak. Other situations may be more subtle, particularly when they involve block objects.

In manual reference counting mode, __block id x; has the effect of not retaining x. In ARC mode, __block id x; defaults to retaining x (just like all other values). To get the manual reference counting mode behavior under ARC, you could use __unsafe_unretained __block id x;. As the name __unsafe_unretained implies, however, having a non-retained variable is dangerous (because it can dangle) and is therefore discouraged. Two better options are to either use __weak (if you don’t need to support iOS 4 or OS X v10.6), or set the __block value to nil to break the retain cycle.

source: Use Lifetime Qualifiers to Avoid Strong Reference Cycles – click through for code examples. Unsurprisingly, Apple’s own documentation is the most thorough – if only I’d found it first!

Specifically, I wanted to know how best to handle the case in which I called -dismissViewControllerAnimated:completion: when the user, say, clicked the “Done” button on the toolbar:

Thanks to the Apple docs, we have instead:

Time for a code audit – I hastily (aka giddily, aka excitedly) integrated BlocksKit yesterday without researching this too closely, but I know that I use blocks often elsewhere in my code, and it’s time to make sure everything’s correct before I push my latest set of commits.

Comment » | techy

Impetus

July 29th, 2009 — 1:40am

I’ve been trying to be on my own case this summer. Last summer I was in San Francisco, I was very comfortable – I took the last shuttle home (at 7pm!) every day, couldn’t do work at home (no VPN access for interns!), so did a lot of relaxing, watching Alias, and cooking.

I’d had the goal of going out and “doing the SF tech thing,” which to me at the time meant going to tech meetups and talks and meeting all sorts of cool people, and learning all sorts of cool things. Clearly, it didn’t happen.

So this year I’m trying something different. I’ve been much more proactive about getting out and talking to people – an interesting union of MIT friends in and out of the startup world, acquaintances with interesting backgrounds and experiences, and now and then the occasional stranger whose blog I find fascinating. (I hate the term networking. I prefer “being-enriched-by-the-wisdom-of”.)

While the first category of dinner partners definitely keeps me from feeling like I’m becoming a hermit, it’s the second two categories that are really pushing this summer and myself forward. I walk out of each of these dinners excited about everything I can and want to do, and even more convinced of the importance of constant self-improvement.

So. In the interest of committing myself to a number of things to achieve this goal, here goes the list:

  • Blog at least once a week. I’m going to set an alarm on my iCal and commit to posting something interesting I learned, or thought, or accomplished.
  • Read 1 ‘improvement’ book for every fun book. I’m in the middle of reading the LOTR series (for the first time!), and once I finish The Two Towers, until I finish a programming- or startup- or productivity-related book, I won’t let myself read Return of the King. Sniff.
  • Keep working a few nights a week on my side project (more later) – I feel like I need at least one or two non-school- or work-related projects under my belt before I can respect myself as a hacker. Or, as a lower standard, any sort of programmer.
  • Along that line of thought – be more disciplined about said project! Don’t just sit down and start coding. Plan out the project a little more (what do I want it to do? How should it behave?) and use version control / repo management tools as well.

(Side note: am still probably far too awkward to be going around meeting people and making these first impressions. Need to work on that, too – for now, just sadface)

(Last note: tonight’s conversation was described as “covering a lot of ground, both philosophically and academically.” Last week’s was described as “spontaneously deep conversation with strangers.” Good nights, both. :))

1 comment » | personal, techy

C++ Sanity Check

April 21st, 2009 — 8:21pm

Note to self: wondering how an element got added to your std::map that you didn’t actually put there?

std::map<..>[lid] will add an empty element to your list if the lid doesn’t currently exist in the table. Awesome.

Also note to self: printing out addresses of objects is done as follows:

obj *my_obj;
printf("address: %p\n", my_obj);

not &my_obj, not printing with %u or %s. Just the above.

Note to the rest of you: I’m going to figure out some way to separate my personal blog and my techy/notes-to-self blog. Apologies for now.

Comment » | techy

Fighting

August 8th, 2007 — 11:19am

I’ve never pretended I knew everything. In class, in my extracurriculars, or my personal pet projects. I’m not great at asking for help, either, but I find things out – I look things up, I test by trial and error, and I bang on it until I either cave in and ask for help or the magical cogs click into place and things work the way I expect them to.

In each challenge that matters to me, in each different situation I face, I try. Sometime it isn’t good enough – sometimes I get that B instead of that A, or take an extra three months to get the damn server doing what I want it to. But sometimes that effort spent trying to fix things… fighting to get things done my way, is what makes that success so much more triumphant – or that failure somewhat less harsh.

I’m trying to be better about it, actually. To be better about asking for advice, so that I can trim those three weeks of fighting with Apache down to two days, or to find the shortcut around brute-forcing a problem set. And maybe I’ll find that I learn just as much, and the answers given will stick with me as well as the answers I find myself. And maybe – just maybe – the victories will taste as sweet.

Comment » | personal

Back to top