【发布时间】:2013-06-15 05:56:59
【问题描述】:
我正在尝试在自定义类上实现 NSFastEnumeration 协议中的 countByEnumeratingWithState:objects:count: 方法。
到目前为止,我已经正确地遍历了我的对象,但返回的对象不是 Objective-C 对象,而是核心基础等价物。
这是设置状态的部分代码->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”循环
SomeOtherClass.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 *) 似乎转换为 void 类型的指针,其中 __bridge 用于将 obj-c 世界连接到 CF 世界。根据llvm docs,对于__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;
【问题讨论】:
标签: objective-c automatic-ref-counting nsfastenumeration toll-free-bridging