我绝对是Objective-C的初学者!任何帮助将非常感激。NSFastEnumeration类的正确构建
这段代码对我很有用,但我真的觉得它在将来肯定会炸毁我。例如,如果某人在for循环的中间调用autorelease drain,该怎么办。另外,itemPtr和stackbuf之间的区别是什么?在苹果网站NSFastEnumeration的文档非常薄弱,我的代码是不是表现为描述:
stackbuf A C array of objects over which the sender is to iterate. itemsPtr A C array of objects
这不是非常有帮助。我只使用itemsPtr,它的工作原理。我应该怎样处理stackbuf,以及如何处理stackbuf和itemsPtr的内存分配/取消分配?我在macosx-dev上阅读了这个讨论(2009年10月)实现NSFastEnumeration,并且觉得我没有任何想法正在发生。
所以...帮助!这是正确的吗?我如何让它变得更好?我应该用stackBuf做什么?休息时如何避免麻烦?
代码作为源文件:http://vislab-ccom.unh.edu/~schwehr/Classes/2010/mbnutsandbolts/simple-fast-enum2.m(我共同教授这门课程在C++中,而是试图为自己做的一切在ObjC)
001: #import <Foundation/Foundation.h> 002: #include <assert.h> 003: 004: @interface Datagram : NSObject 005: { 006: int dgId; 007: } 008: -(id)initWithDatagramType:(int)datagramType; 009: -(void)dealloc; 010: -(NSString *)description; 011: @property (readonly) int dgId; 012: @end 013: 014: @implementation Datagram 015: @synthesize dgId; 016: - (NSString *)description { 017: return [NSString stringWithFormat: @"Datagram: dgId:", dgId]; 018: } 019: 020: -(id)initWithDatagramType:(int)datagramType { 021: self = [super init]; 022: if (!self) return self; 023: dgId = datagramType; 024: return self; 025: } 026: 027: -(void)dealloc { 028: NSLog(@"dealloc datagram: %d",dgId); 029: [super dealloc]; 030: } 031: @end 032: 033: // Pretend sequence of packet ID's coming from a sonar 034: int testSeq[] = { 035: 3, 12, 4, 19, 8, 036: 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 037: 2, 2, 2, 2, 9, 038: 2,2,2,2,9, 039: 1,2,3,4,5,6,7,8,9, 040: 11,12,13,14,15,16,17,18,19, 041: 3, 042: 0 // End of sequence/array sentinal 043: }; 044: 045: @interface DatagramFile : NSObject <NSFastEnumeration> 046: { 047: // No ivars 048: } 049: -(id)init; 050: @end 051: 052: @implementation DatagramFile 053: -(id)init { 054: self = [super init]; 055: if (!self) return self; 056: // NOP 057: return self; 058: } 059: 060: - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len 061: { 062: NSLog(@"In countByEnumeratingWithState: stackbuf: %p, count: %d", stackbuf, len); 063: NSLog(@"\t state struct: state=%d %p %p", state->state, state->itemsPtr, state->mutationsPtr); 064: if (stackbuf) { 065: NSLog(@"***INSPECTING STACKBUF\n"); 066: for(int i=0;i<1000 && stackbuf[i]!=0;i++) { 067: NSLog(@"Stackbuf %d: %p",i,stackbuf[i]); // What should I do with stackbuf[i]? 068: } 069: } 070: if (0 == state->state) { 071: NSLog(@"Initializing loop"); 072: assert(0==state->itemsPtr); 073: state->itemsPtr = malloc(sizeof(id)*16); 074: memset(state->itemsPtr, 0, sizeof(id)*16); 075: } elseif (0==len) { 076: // Will this get called if the call uses break inside the for loop? 077: NSLog(@"Finished loop. cleanup"); 078: free(state->itemsPtr); 079: state->itemsPtr = 0; 080: return 0; 081: } 082: state->mutationsPtr = (unsigned long *)self; // Tell the caller that the file has not changed 083: 084: NSUInteger count=0; 085: for (; count < len && testSeq[state->state]!=0; count++, state->state++) { 086: NSLog(@"Creating datagram of type %d state: %d count %d",testSeq[state->state], state->state, count); 087: Datagram *dg = [[Datagram alloc] initWithDatagramType:testSeq[state->state]]; 088: state->itemsPtr[count] = dg; 089: [dg autorelease]; 090: } 091: NSLog(@"countByEnumeratingWithState read %d datagrams. state->state: %d",count, state->state); 092: return count; 093: } 094: @end // implementation DatagramFile 095: 096: int main (int argc, const char * argv[]) { 097: NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 098: 099: DatagramFile *df = [[DatagramFile alloc] init]; 100: for (Datagram *dg in df) { 101: NSLog(@"About to read datagram in for"); 102: NSLog(@" Datagram type: %d", [dg dgId]); 103: } 104: 105: NSLog(@"about to drain pool"); 106: [pool drain]; 107: NSLog(@"pool drained. ready for winter"); 108: return 0; 109: }
谢谢。我现在发布了一个清洁版本的代码: http://schwehr.org/blog/attachments/2010-08/using-NSFastEnumeration.m – 2010-08-12 15:54:37
“直接C对象引用数组”的确切数据类型是?它是'unsigned long'的数组还是可以使用objective-c'id'类型实际创建一个c数组? – 2011-01-14 19:44:49
@大卫:是的,你可以做到这一点。事实上,你必须实现'NSFastEnumeration'。这就是'stackBuf'和'state-> itemsPtr'。 – 2011-01-14 22:11:28