ARC: __bridge против __bridge_ удерживается с использованием контрольного примера contextInfo

Рассмотрим этот код ARC:

- (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;
}

Вопрос: в строке 7 следует __bridge быть использованы, или __bridge_retainedили это не имеет значения, или выбор зависит от количества сохраняемых строк (то есть, является ли строка явно выделенной по сравнению с автоматически высвобождаемой через инициализатор класса, такой как +[NSString stringWithString:]?

1 ответ

Решение

Как правило, это либо

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

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

или же

// 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;

В первом случае передача права собственности отсутствует, поэтому основная программадолжна сохранять четкую ссылку на объект, пока лист активен.

Во втором случае объект сохраняется при создании листа и освобождается в sheetDidEnd: метод. Не требуется, чтобы основная программа содержала сильную ссылку, поэтому это безопасный метод.