将 CFArrayRef 转换为 NSArray 时崩溃

发布于 2024-12-14 16:52:07 字数 390 浏览 0 评论 0原文

这很好:

CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
NSLog(@"%@", (__bridge NSArray *)windowList);

这会导致 EXC_BAD_ACCESS:

CFArrayRef windowIDList = CGWindowListCreate(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
NSLog(@"Array %@", (__bridge NSArray*) windowIDList);

This is fine:

CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
NSLog(@"%@", (__bridge NSArray *)windowList);

This causes EXC_BAD_ACCESS:

CFArrayRef windowIDList = CGWindowListCreate(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
NSLog(@"Array %@", (__bridge NSArray*) windowIDList);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

执手闯天涯 2024-12-21 16:52:18

来自文档 NSArray:

NSArray 与其对应的 Core Foundation 是“免费桥接”的,
CFArray 参考。这意味着核心基础类型是
在函数或方法调用中可与桥接互换
基础对象,让您可以将一种类型转换为另一种类型。
因此,在您看到 NSArray * 参数的 API 中,您可以
传入 CFArrayRef,并在 API 中看到 CFArrayRef
参数,可以传入一个 NSArray 实例。这样的安排也
适用于 NSArray 的具体子类。

所以问题肯定出在调用的两个方法上。同样,从文档中,CGWindowListCopyWindowInfo 有返回值:

CFDictionaryRef 类型的数组,每个类型都包含信息
关于当前用户会话中的窗口之一。如果没有
窗口匹配所需的条件,该函数返回一个空
大批。如果您从 GUI 安全性外部调用此函数
会话或没有窗口服务器运行时,此函数返回
空。

并且CGWindowListCreate有返回值:

与所需窗口相对应的 CGWindowID 值数组。如果
没有符合所需条件的窗口,函数
返回一个空数组。如果您从外部调用此函数
GUI 安全会话或没有窗口服务器运行时,这
函数返回 NULL。

当您调用 NSLog(@"%@",array); 时,消息 description 会发送到数组中的每个对象。浮点数、BOOL 和整数不响应此消息。例如,您将收到错误,

NSLog(@"Printing 2: %@",2);

但如果使用 int 调用,错误就会消失:

NSLog(@"Printing 2: %d",2);

对于您的情况,CGWindowListCreate 返回一个 CGWindowID< 数组/code> 值,这些是 32 位无符号整数。因此,它们不会响应%@,但会响应%u。因此,修复方法是使用 %u 手动打印数组。

From the documentation on NSArray:

NSArray is “toll-free bridged” with its Core Foundation counterpart,
CFArray Reference. What this means is that the Core Foundation type is
interchangeable in function or method calls with the bridged
Foundation object, providing you cast one type to the other.
Therefore, in an API where you see an NSArray * parameter, you can
pass in a CFArrayRef, and in an API where you see a CFArrayRef
parameter, you can pass in an NSArray instance. This arrangement also
applies to your concrete subclasses of NSArray.

So the problem must be with the two methods being called. Again, from the documentation, CGWindowListCopyWindowInfo has return value:

An array of CFDictionaryRef types, each of which contains information
about one of the windows in the current user session. If there are no
windows matching the desired criteria, the function returns an empty
array. If you call this function from outside of a GUI security
session or when no window server is running, this function returns
NULL.

and CGWindowListCreate has return value:

An array of CGWindowID values corresponding to the desired windows. If
there are no windows matching the desired criteria, the function
returns an empty array. If you call this function from outside of a
GUI security session or when no window server is running, this
function returns NULL.

When you call NSLog(@"%@",array);, the message description is sent to each object in the array. Floats, BOOLs and ints do not respond to this message. For example, you will get an error for

NSLog(@"Printing 2: %@",2);

but the error goes away if you use the int call:

NSLog(@"Printing 2: %d",2);

For your case, CGWindowListCreate is returning an array of CGWindowID values, and these are 32 bit unsigned integers. Therefore they do no respond to %@, but will respond to %u. Hence the fix is to print the array manually using %u.

长安忆 2024-12-21 16:52:16

创建为 NSArrays 只能包含类似于 Objective-C 对象的元素。

创建为 CFArray 的数组s 可以包含任何内容,如果您传递适当的 CFArrayCallBacks CFArrayCreate

CGWindowListCreate 正在创建一个 CFArray,并用不像对象的东西填充它,但 CGWindowListCreate 正在使用 CFArrayCallbacks 不关心这个。

当您尝试使用 %@ 格式说明符打印此 CFArray 时,NSLog 会发送一个 Objective-C -description消息到数组。 CFArray 通过向其每个元素发送一条 Objective-C description 消息来处理此问题。不幸的是,它的元素不是对象,因此不可能向它们发送 Objective-C 消息。因此崩溃了。

请尝试以下操作:

CFStringRef description = CFCopyDescription(windowIDList);
NSLog(@"Array %@", description);
CFRelease(description);

CFCopyDescription 函数对数组的每个元素使用 CFArrayCallbacks 函数之一,而不是尝试向每个元素发送一条 Objective-C 消息。回调知道如何处理数组元素,因此它可以正常工作。我在测试程序中得到以下输出:

2011-11-10 18:50:23.888 test[15156:707] <CFArray 0x1001140c0 [0x7fff7fd24ea0]>{type = mutable-small, count = 19, values = (
    0 : <0x7d7>
    1 : <0x2d>
    2 : <0x20>
    3 : <0x21>
    4 : <0x1e>
    5 : <0x9>
    6 : <0x7a8>
    7 : <0x2c>
    8 : <0x2e>
    9 : <0x743>
    10 : <0x32>
    11 : <0x85>
    12 : <0x695>
    13 : <0x62a>
    14 : <0x62b>
    15 : <0xa>
    16 : <0x26>
    17 : <0x18>
    18 : <0x2>
)}

Arrays created as NSArrays can only contain elements that act like Objective-C objects.

Arrays created as CFArrays can contain anything, if you pass the appropriate CFArrayCallBacks to CFArrayCreate.

CGWindowListCreate is creating a CFArray, and filling it with things that don't act like objects, but CGWindowListCreate is using CFArrayCallbacks that don't care about that.

When you try to print this CFArray with the %@ format specifier, NSLog sends an Objective-C -description message to the array. The CFArray handles this by sending an Objective-C description message to each of its elements. Unfortunately, its elements are not objects and so it's impossible to sending Objective-C messages to them. Thus the crash.

Try this instead:

CFStringRef description = CFCopyDescription(windowIDList);
NSLog(@"Array %@", description);
CFRelease(description);

The CFCopyDescription function uses one of the CFArrayCallbacks functions on each element of the array, instead of trying to send an Objective-C message to each one. The callback knows how to handle the array element, so it works fine. I get this output in my test program:

2011-11-10 18:50:23.888 test[15156:707] <CFArray 0x1001140c0 [0x7fff7fd24ea0]>{type = mutable-small, count = 19, values = (
    0 : <0x7d7>
    1 : <0x2d>
    2 : <0x20>
    3 : <0x21>
    4 : <0x1e>
    5 : <0x9>
    6 : <0x7a8>
    7 : <0x2c>
    8 : <0x2e>
    9 : <0x743>
    10 : <0x32>
    11 : <0x85>
    12 : <0x695>
    13 : <0x62a>
    14 : <0x62b>
    15 : <0xa>
    16 : <0x26>
    17 : <0x18>
    18 : <0x2>
)}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文