5

Consider this ARC code:

- (void)main {
    NSString *s = [[NSString alloc] initWithString:@"s"];
    [NSApp beginSheet:sheet 
           modalForWindow:window 
           modalDelegate:self 
           didEndSelector:@selector(sheetDidEnd:returnCode:context:) 
           contextInfo:(__bridge void *)s
    ];
}

- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode context:(void *)context {
    NSString *s = (__bridge_transfer NSString *)context;
}

Question: on line 7, should __bridge be used, or __bridge_retained, or does it not matter, or does the choice depend on the string's retain count (that is, whether the string is explicitly alloced vs being autoreleased through a class initializer like +[NSString stringWithString:]?

Steveo
  • 2,238
  • 1
  • 21
  • 34
  • This isn't an exact duplicate, but may answer your question: http://stackoverflow.com/q/12916491/1445366. (Also, irrelevant to your question: this NSApp method is deprecated in OS X 10.9.) – Aaron Brager Dec 30 '13 at 15:28
  • It does matter when you choose one over another. If you use bridge_retained then you are responsible for freeing the retained object but if you used __bridge, the ARC will take care of it for you. – ldindu Dec 30 '13 at 15:32
  • @ldindu: If __bridge_retained is matched by (exactly one) __bridge_transfer, ARC will also "take care" of releasing the object. – Martin R Dec 30 '13 at 15:55
  • @Martin R agreed with your statement, I am explaining between __bridge and __bridge_retained as asked in the question as the Steveo hasn't mentioned about bridge transfer, so left explaining it. – ldindu Dec 30 '13 at 16:42
  • Consider using CFBridgingRetain() and CFBridgingRelease() instead of __bridge_retained and __bridge_transfer. They do the same thing, but you may find the CF functions easier to reason about. – Greg Parker Jan 01 '14 at 02:20

1 Answers1

11

Generally, it is either

// Object to void *:
contextInfo:(__bridge void *)s

// void * to object:
NSString *s = (__bridge NSString *)context;

or

// Object to void *, retaining the object:
contextInfo:(__bridge_retained void *)s

// void * to object, transferring ownership.
// The object is released when s goes out of scope:
NSString *s = (__bridge_transfer NSString *)context;

In the first case, there is no transfer of ownership, therefore the main program must hold a strong reference to the object as long as the sheet is active.

In the second case, the object is retained when creating the sheet, and released in the sheetDidEnd: method. It is not required that the main program holds a strong reference, so this is the safe method.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • 3
    A third case: __bridge_retained or CFBridgingRetain() when setting the context, but plain __bridge cast when using the context. This is used when the context should live forever but there's no other convenient place to store a strong reference to it. – Greg Parker Jan 01 '14 at 02:20