为什么 CFStringCreateArrayBySeparatingStrings 不创建 CFStringRef 值项?

Why Does CFStringCreateArrayBySeparatingStrings Does Not Create CFStringRef Value Items?

我正在尝试开发一个使用函数 CFStringCreateArrayBySeparatingStrings() 的非常简单的 Core Foundation 程序。然而,它并没有像我预期的那样工作。

程序如下:

#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>

void applier(const void *value, void *context) {
  printf("%s\n", CFStringGetCStringPtr((CFStringRef)value, CFStringGetSystemEncoding()));
}

int main(int argc, const char * argv[]) {
  CFStringRef stringToParse = CFSTR("John Pappas,Mary Foo,Peter Pan");
  CFStringRef separatorString = CFSTR(",");
  
  CFArrayRef array = CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault, 
                                                            stringToParse, 
                                                            separatorString);
  
  CFArrayApplyFunction(array, 
                       CFRangeMake((CFIndex)0, 
                                   (CFIndex)CFArrayGetCount(array)), 
                       applier, 
                       NULL);
  
  CFRelease(array);
  
  return 0;
}

当我运行程序时,输出如下:

John Pappas
(null)
(null)
Program ended with exit code: 0

我不明白为什么第二个和第三个值没有按预期打印。

在尝试调试程序时,在退出之前,调试器显示数组确实有 3 个元素,但其值的类型并非全部相同。这是我在调试器的断点处停止时看到的内容:

此外,通过查看调试器,我有点惊讶数组的元素具有涉及 NS 的类型值。我以为我使用的是 Core Foundation 而不是 Foundation 框架。所以,我希望这些值具有 CFStringRef.

这样的类型

你能帮助我使用 Core Foundation API 成功地制作这个程序 运行 吗?

作为对 a related question 的回应,我深入研究了文档。这是我的发现:

来自 Foundation Release Notes for OS X v10.10 and iOS v8

NS/CFStrings now use a “tagged pointer” format where the string contents are stored in the pointer directly in some cases. This happens automatically thru the existing APIs that create strings, without need to use any new API.

This change will break any code which treats NS/CFStrings objects as pointers

的确,CFStringCreateArrayBySeparatingStrings returns NSTaggedPointerStrings.

来自CFStringGetCStringPtr的文档:

This function either returns the requested pointer immediately, with no memory allocations and no copying, in constant time, or returns NULL. If the latter is the result, call an alternative function such as the CFStringGetCString(::::) function to extract the characters.

Whether or not this function returns a valid pointer or NULL depends on many factors, all of which depend on how the string was created and its properties. In addition, the function result might change between different releases and on different platforms. So do not count on receiving a non-NULL result from this function under any circumstances.

CFStringGetCStringPtr 不能 return 一个 NSTaggedPointerString 的指针。使用 CFStringGetCString 而不是 CFStringGetCStringPtr 或尝试 CFStringGetCStringPtr 如果结果是 NULL 然后调用 CFStringGetCString.