Skip to content
This repository
Browse code

Publish blog posts

  • Loading branch information...
commit 8e441edbf7ed64f950205be5e770ccb90fbdb503 1 parent ca17993
Michael Baltaks authored July 31, 2012
52  _posts/2012-07-31-paying-the-arc-__bridge-toll.md
Source Rendered
... ...
@@ -0,0 +1,52 @@
  1
+---
  2
+layout: post
  3
+title: "Paying the ARC __bridge toll"
  4
+date: 2012-07-31 03:35:50
  5
+---
  6
+After years spent writing Objective-C code and getting completely comfortable with balancing every `alloc`, `retain` and `copy` with a `release` or `autorelease`, [ARC](http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/) messed with my brain a bit when I first encountered it. At first I ignored it, because it's optional, but when I discovered that in general it produces faster code, I started reading up on, and then using ARC.
  7
+
  8
+After a while I've gotten comfortable with no longer thinking about object ownership in Objective-C when ARC is enabled. Except of course for occasions where I need to use (weak) in property declarations, mostly for delegates.
  9
+
  10
+But one thing that hadn't crossed my path until recently was toll free bridging from Core Foundation to Objective-C, and at first it was also quite confusing. Especially since ARC means that you really don't think about this anymore for Objective-C, having to think again for CF is a bit of a jolt.
  11
+
  12
+The [Transitioning to ARC Release Notes](http://developer.apple.com/library/mac/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html) provide this example of equivalent code, first non ARC, then ARC:
  13
+
  14
+```
  15
+- (void)logFirstNameOfPerson:(ABRecordRef)person
  16
+{
  17
+    NSString *name = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
  18
+    NSLog(@"Person's first name: %@", name);
  19
+    [name release];
  20
+}
  21
+
  22
+- (void)logFirstNameOfPerson:(ABRecordRef)person
  23
+{
  24
+    NSString *name = (NSString *)CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
  25
+    NSLog(@"Person's first name: %@", name);
  26
+}
  27
+```
  28
+
  29
+This is helpful to see one example of how to start using ARC, but when migrating code the compiler actually prompts you to fill in with `__bridge` style cast specifiers, and that seems to be the style that's used a lot. So I had to understand how these differed, and I've come up with two more equivalent bits of ARC code that helped me understand:
  30
+
  31
+```
  32
+- (void)logFirstNameOfPerson:(ABRecordRef)person
  33
+{
  34
+    NSString *name = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
  35
+    NSLog(@"Person's first name: %@", name);
  36
+}
  37
+
  38
+- (void)logFirstNameOfPerson:(ABRecordRef)person
  39
+{
  40
+    CFStringRef nameRef = ABRecordCopyValue(person, kABPersonFirstNameProperty);
  41
+    NSString *name = (__bridge NSString *)nameRef;
  42
+    NSLog(@"Person's first name: %@", name);
  43
+    CFRelease(nameRef); // balance the *Copy*()
  44
+}
  45
+```
  46
+
  47
+There are some things to consider:
  48
+
  49
+- You can't use casts unless there is an Objective-C type to cast to, so sometimes you simple have to use `CFRelease()` anyway.
  50
+- You can't pass the Objective-C object out of the current scope unless you transfer ownership to ARC, using either `__bridge_transfer` or `CFBridgingRelease()`.
  51
+
  52
+So, in cases like this one, you actually have to choose between explicitly balancing the `*Copy*()` call with a `*Release()`, or handing over to ARC, using one of two styles. Which of these is preferable? I have no idea. I guess some kind of community consensus will develop over time, if it hasn't already, and we'll all just do it that way.

0 notes on commit 8e441ed

Please sign in to comment.
Something went wrong with that request. Please try again.