我需要一些关于在iOS中使用__bridge的建议.

希望下面的SSCCE1能比我用语言更好地解释这个问题,但我需要知道如何将void*转换为NSMutableArray*;应该使用哪一个变量(参见代码中的注释).

读到不同的桥梁,我推断我需要__bridge_transfer个,但随后我在addObject:上收到了一个EXC_BAD_访问权限

最后,我希望在CGPathApply被调用之后,在CGPath中有一个CGPoints的array.

#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);
    }
}

推荐答案

关于bridge关键字can be found here使用的文档.具体而言,我想指出§3.2.4:

(__bridge T) op将操作数强制转换为目标类型T.如果T是可保留的对象指针类型,则op必须具有不可保留的指针类型.如果T是不可保留的指针类型,则op必须具有可保留的对象指针类型.否则演员阵容就不好.没有所有权转让,ARC Insert也没有保留操作.

(__bridge_retained T) op将操作数(必须具有可保留的对象指针类型)强制转换为目标类型(必须是不可保留的指针类型).ARC将保留该值,并根据通常的局部值优化,接收者负责平衡+1.

(__bridge_transfer T) op将操作数(必须具有不可保留的指针类型)强制转换为目标类型(必须是可保留的对象指针类型).ARC将在封闭的完整表达式的末尾释放该值,并对局部值进行通常的优化.

传入的指针(void*)是不可保留的指针类型,而NSMutableArray是可保留的指针类型.这就排除了__bridge_retained的可能性.所以问题是,到__bridge还是到__bridge_transfer

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

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

But wait, when I use __bridge, my code gets memory access errors!?

啊,这是你发布的代码的问题,与整个桥接讨论无关.对于处理函数_processPathElement,需要将void*传递给CGApplyPath.你通过的是NSMutableArray**.

当你重铸到NSMutableArray*,你实际上是在铸造一个NSMutableArray**.这将导致臭名昭著的EXC_坏访问.您需要传递指针本身,而不是指向指针的指针.ButCGPathApply(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}"
)

Objective-c相关问答推荐

跨平台 iPhone/Android 代码共享

如何获取 NSDictionary 中的第一个元素?

NSBundle pathForResource 为 NULL

如何复制 .xib 文件?

如何可靠地检测 iOS 9 上是否连接了外部键盘?

为什么在目标 c 的静态上下文中允许 self

将 HEX NSString 转换为 NSData

如何在 UICollectionView 中居中行?

具有匿名函数/块的 NSTimer?

如何连续关闭 2 个模态视图控制器?

在Objective C中迭代枚举?

NSInternalInconsistencyException: '无效参数不满足: !stayUp || CLClientIsBackgroundable(内部->fClient)'

UIScreen MainScreen Bounds 返回错误的大小

设置数据后调整 UICollectionView 单元格的大小

StoryBoard 助理编辑器停止显示相关文件

Lipo错误!!无法打开输入文件

如何在表格视图中的两个单元格之间留出空间?

UITextField:键盘出现 timeshift 动视图

Xcode 警告未使用属性访问结果 - getter 不应用于副作用

如何更新 Core Data 中的现有对象?