我正在尝试在自定义类上实现NSFastEnumeration协议中的countByEnumeratingWithState:objects:count:
方法。
到目前为止,我已经正确地迭代了我的对象,但是返回的对象不是 Objective-C 对象,而是核心基础等价物。
这是设置 state->itemsPtr 的代码部分:
MyCustomCollection.m
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState *)state
objects: (id __unsafe_unretained *)buffer
count: (NSUInteger)bufferSize {
// ... skip details ...
NSLog(@"Object inside method: %@", someObject);
state->itemsPtr = (__unsafe_unretained id *)(__bridge void *)someObject;
// ... skip details ...
}
然后我像这样在其他地方调用'for..in'循环
其他类.m
MyCustomCollection *myCustomCollection = [MyCustomCollection new];
[myCustomCollection addObject:@"foo"];
for (id object in myCustomCollection) {
NSLog(@"Object in loop: %@", object);
}
控制台输出为:
Object inside method: foo
Object in loop: __NSCFConstantString
如您所见,在 NSFastEnumeration 协议方法中,对象打印得很好,但是一旦它被强制转换,id __unsafe_unretained *
我就会丢失原始的 Objective-C 对应类。
老实说,我不太确定(__unsafe_unretained id *)(__bridge void *)
在这种情况下铸造是如何工作的。似乎要匹配正确的(__unsafe_unretained id *)
类型 itemsPtr 需要。(__bridge void *)
似乎使用 __bridge 转换为 void 类型的指针,用于将 obj-c 世界连接到 CF 世界。根据llvm 文档,对于__bridge
:
没有所有权转移,ARC 没有插入保留操作
那是对的吗?
据我了解,__NSCFConstantString 只是相当于 NSString 的核心基础。我也明白,使用 ARC,您需要从 Objective-C 对象桥接到 CoreFoundation 等价物,因为 ARC 不知道如何管理后者的内存。
我怎样才能让它工作,以便我的'for..in'循环中的对象是原始类型?
另请注意,在这种情况下,我将 NSStrings 添加到我的集合中,但理论上它应该支持任何对象。
更新
Rob 的答案是正确的,但为了测试这个理论,我将 for 循环更改为:
for (id object in myCustomCollection) {
NSString *stringObject = (NSString *)object;
NSLog(@"String %@ length: %d", stringObject, [stringObject length]);
}
理论上应该可以工作,因为对象是等效的,但它会因以下错误而崩溃:
+[__NSCFConstantString length]: unrecognized selector sent to class
看起来for
循环中返回的对象几乎是类而不是实例。这里可能有其他问题......对此有什么想法吗?
更新 2:解决方案
就这么简单:(感谢 CodaFi
state->itemsPtr = &someObject;