在哪里以及如何__bridge

我需要关于iOS中__bridge -ing的一些build议。

希望下面的SSCCE 1能更好地解释这个问题,但我需要知道如何将void*转换为NSMutableArray* ; 应该使用__bridge变体(参见代码注释)。

读了不同的桥梁,我推断,我将需要__bridge_transfer但接着我收到addObject的addObject:

最终,我想在调用CGPath之后在CGPoints中创build一个CGPath数组。

 #import <Foundation/Foundation.h> void _processPathElement(void* info, const CGPathElement* element) { NSMutableArray *array = (/* WHAT BRIDGE HERE */ NSMutableArray*) info; switch (element->type) { case kCGPathElementMoveToPoint: case kCGPathElementAddLineToPoint: { CGPoint point = element->points[0]; [array addObject:[NSValue valueWithCGPoint:point]]; break; } default: break; } } int main(int argc, char *argv[]) { @autoreleasepool { //Create path CGMutablePathRef path = CGPathCreateMutable(); CGPathMoveToPoint( path, NULL, 0, 0); CGPathAddLineToPoint(path, NULL, 1, 0); CGPathAddLineToPoint(path, NULL, 1, 1); CGPathAddLineToPoint(path, NULL, 0, 1); CGPathCloseSubpath(path); NSMutableArray *pathPoints = [NSMutableArray array]; CGPathApply(path, &pathPoints, _processPathElement); NSLog(@"Points:%@", pathPoints); } } 

1: SSCCE

有关使用bridge关键字的文档可以在这里find 。 具体来说,我想指出§3.2.4:

(__bridge T) op将操作数转换为目标typesT.如果T是可保留的对象指针types,则op必须具有不可保留的指针types。 如果T是一个不可保留的指针types,那么op必须有一个可保留的对象指针types。 否则,演员阵容不健全。 没有所有权转让,并且ARC不插入保留操作。

(__bridge_retained T) op将必须具有可保留对象指针types的操作数强制转换为目标types,该目标types必须是不可保留的指针types。 ARC会保留这个值,但是必须遵守本地值的通常优化,接收者负责平衡+1。

(__bridge_transfer T) op将必须具有不可保留的指针types的操作数强制转换为目标types,该types必须是可保留的对象指针types。 ARC将在封闭的完整expression式的末尾释放该值,受当地值的通常优化。

你传入的指针( void* )是一个不可保留的指针types,而你的NSMutableArray是一个可保留的指针types。 这直接排除了__bridge_retained 。 所以问题是, __bridge__bridge_transfer

__bridge_transfer通常用于从返回已保留的CF对象的方法中获取Objective-C指针。 例如,CFStringCreateWithFormat将返回一个保留的CFString,但是如果你想要一个NSString,你需要在它们之间进行__bridge_transfer 。 这将使ARC在合适的时候释放CF保留的对象。 例如, NSString* str = (__bridge_transfer NSString*) CFStringCreateWithFormat(...);

你的代码没有这样做,你不需要干涉所有权。 你的主要方法是控制它的内存pipe理,只是简单的传递一个它所调用的方法的引用(虽然是间接的,但都在main的范围之内)。 因此,您可以使用__bridge

但是等等,当我使用__bridge时,我的代码会得到内存访问错误!

啊,这是你发布的代码的问题,而不是整个桥接讨论。 你需要传递一个void*到CGApplyPath,为你的处理函数_processPathElement 。 你传递的是NSMutableArray**

当你重铸到NSMutableArray* ,你实际上正在施放一个NSMutableArray** 。 这将导致臭名昭着的EXC_BAD_ACCESS。 您需要传递指针本身,而不是指向指针的指针。 但是CGPathApply(path, pathPoints, _processPathElement)将不起作用,您不能将NSMutableArray*作为void*传递。 你需要什么(讽刺),是一座桥梁。 出于同样的原因,所有你需要的是__bridge 。 看到下面的代码,正确的桥梁,并按预期工作:

 #import <UIKit/UIKit.h> #import <Foundation/Foundation.h> void _processPathElement(void* info, const CGPathElement* element) { NSMutableArray *array = (__bridge NSMutableArray*) info; switch (element->type) { case kCGPathElementMoveToPoint: case kCGPathElementAddLineToPoint: { CGPoint point = element->points[0]; [array addObject:[NSValue valueWithCGPoint:point]]; break; } default: break; } } int main(int argc, char *argv[]) { @autoreleasepool { //Create path CGMutablePathRef path = CGPathCreateMutable(); CGPathMoveToPoint( path, NULL, 0, 0); CGPathAddLineToPoint(path, NULL, 1, 0); CGPathAddLineToPoint(path, NULL, 1, 1); CGPathAddLineToPoint(path, NULL, 0, 1); CGPathCloseSubpath(path); NSMutableArray *pathPoints = [[NSMutableArray alloc] init]; CGPathApply(path, (__bridge void*)pathPoints, _processPathElement); NSLog(@"Points:%@", pathPoints); } } 

这将打印出来:

 Points:( "NSPoint: {0, 0}", "NSPoint: {1, 0}", "NSPoint: {1, 1}", "NSPoint: {0, 1}" ) 

我不太确定这是为什么,但我发现解决scheme是:

 NSMutableArray *array = (__bridge NSMutableArray*) info; //AND CGPathApply(path, (__bridge void*)pathPoints, _processPathElement); 

如果有人能解释为什么这个工作,并确认没有(/)有任何内存泄漏,我会很感激