对于Objective-C,我绝对是初学者!任何帮助都将非常感激。
这段代码对我有用,但我觉得将来肯定会对我有所影响。例如,如果有人在for循环中调用autorelease drain,该怎么办?另外,itemPtr和stackbuf之间的区别是什么? Apple网站上的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: } else if (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: }
答案 0 :(得分:1)
奇;我确信在The Objective-C Programming Language中曾经有过更全面的文档。无论如何,要回答您的具体问题:state->itemsPtr
是您放置实际结果的地方。 stackbuf
和len
提供了可用于此目的的临时空间,但您无需这样做。例如,如果您的集合使用直接C对象引用数组,则可以直接将其放在state->itemsPtr
中,从而一次性返回所有对象。
至于你的实施:
stackbuf
的初始内容永远不会有用。malloc()
而不是stackbuf
缓冲区。使用len
代替硬编码16。