是否可以创建非CFTypeRef
派生的不透明类型,可以使用CFRetain
/ CFRelease
保留/发布?或者我如何从CFType
?
答案 0 :(得分:8)
我从未这样做过,但可以使用私有API。很可能它将依赖于OS X的特定点发布,因为CF运行时可能会在发布之间发生变化。在任何情况下,CF都是开源的,所以我看看CFRuntime做了什么。我很高兴看到Apple有一个例子:
// ========================= EXAMPLE =========================
// Example: EXRange -- a "range" object, which keeps the starting
// location and length of the range. ("EX" as in "EXample").
// ---- API ----
typedef const struct __EXRange * EXRangeRef;
CFTypeID EXRangeGetTypeID(void);
EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length);
uint32_t EXRangeGetLocation(EXRangeRef rangeref);
uint32_t EXRangeGetLength(EXRangeRef rangeref);
// ---- implementation ----
#include <CoreFoundation/CFBase.h>
#include <CoreFoundation/CFString.h>
struct __EXRange {
CFRuntimeBase _base;
uint32_t _location;
uint32_t _length;
};
static Boolean __EXRangeEqual(CFTypeRef cf1, CFTypeRef cf2) {
EXRangeRef rangeref1 = (EXRangeRef)cf1;
EXRangeRef rangeref2 = (EXRangeRef)cf2;
if (rangeref1->_location != rangeref2->_location) return false;
if (rangeref1->_length != rangeref2->_length) return false;
return true;
}
static CFHashCode __EXRangeHash(CFTypeRef cf) {
EXRangeRef rangeref = (EXRangeRef)cf;
return (CFHashCode)(rangeref->_location + rangeref->_length);
}
static CFStringRef __EXRangeCopyFormattingDesc(CFTypeRef cf, CFDictionaryRef formatOpts) {
EXRangeRef rangeref = (EXRangeRef)cf;
return CFStringCreateWithFormat(CFGetAllocator(rangeref), formatOpts,
CFSTR("[%u, %u)"),
rangeref->_location,
rangeref->_location + rangeref->_length);
}
static CFStringRef __EXRangeCopyDebugDesc(CFTypeRef cf) {
EXRangeRef rangeref = (EXRangeRef)cf;
return CFStringCreateWithFormat(CFGetAllocator(rangeref), NULL,
CFSTR("<EXRange %p [%p]>{loc = %u, len = %u}"),
rangeref,
CFGetAllocator(rangeref),
rangeref->_location,
rangeref->_length);
}
static void __EXRangeEXRangeFinalize(CFTypeRef cf) {
EXRangeRef rangeref = (EXRangeRef)cf;
// nothing to finalize
}
static CFTypeID _kEXRangeID = _kCFRuntimeNotATypeID;
static CFRuntimeClass _kEXRangeClass = {0};
/* Something external to this file is assumed to call this
* before the EXRange class is used.
*/
void __EXRangeClassInitialize(void) {
_kEXRangeClass.version = 0;
_kEXRangeClass.className = "EXRange";
_kEXRangeClass.init = NULL;
_kEXRangeClass.copy = NULL;
_kEXRangeClass.finalize = __EXRangeEXRangeFinalize;
_kEXRangeClass.equal = __EXRangeEqual;
_kEXRangeClass.hash = __EXRangeHash;
_kEXRangeClass.copyFormattingDesc = __EXRangeCopyFormattingDesc;
_kEXRangeClass.copyDebugDesc = __EXRangeCopyDebugDesc;
_kEXRangeID = _CFRuntimeRegisterClass((const CFRuntimeClass * const)&_kEXRangeClass);
}
CFTypeID EXRangeGetTypeID(void) {
return _kEXRangeID;
}
EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length) {
struct __EXRange *newrange;
uint32_t extra = sizeof(struct __EXRange) - sizeof(CFRuntimeBase);
newrange = (struct __EXRange *)_CFRuntimeCreateInstance(allocator, _kEXRangeID, extra, NULL);
if (NULL == newrange) {
return NULL;
}
newrange->_location = location;
newrange->_length = length;
return (EXRangeRef)newrange;
}
uint32_t EXRangeGetLocation(EXRangeRef rangeref) {
return rangeref->_location;
}
uint32_t EXRangeGetLength(EXRangeRef rangeref) {
return rangeref->_length;
}
#endif
答案 1 :(得分:4)
CoreFoundation本身不提供任何此类机制,但所有Cocoa对象都可以使用CFRetain和CFRelease。所以唯一支持的答案是:创建一个基于Foundation的类,CoreFoundation会将它识别为CFTypeRef。