【问题标题】:Proper construction of NSFastEnumeration classNSFastEnumeration 类的正确构造
【发布时间】:2010-08-12 13:48:41
【问题描述】:

我绝对是 Objective-C 的初学者!任何帮助将不胜感激。

这段代码对我有用,但我真的觉得它将来肯定会在我身上炸毁。例如,如果有人在 for 循环中间调用 autorelease drain 怎么办。另外,itemPtr 和 stackbuf 之间到底有什么区别? Apple 网站上 NSFastEnumeration 的文档非常薄弱,我的代码与描述的不一样:

stackbuf
    发送方将对其进行迭代的对象的 C 数组。
项目指针
    C 对象数组

这不是很有帮助。我只使用 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 
002: #include 
003:
004:@interface 数据报:NSObject
005:{
006: int dgId;
007:}
008:-(id)initWithDatagramType:(int)datagramType;
009:-(无效)dealloc;
010:-(NSString *)描述;
011:@属性(只读)int dgId;
012:@结束
013:
014:@实现数据报
015:@synthesize dgId;
016:-(NSString *)描述{
017: 返回 [NSString stringWithFormat:@"Datagram: dgId:", dgId];
018:}
019:
020:-(id)initWithDatagramType:(int)datagramType {
021:自我=[超级初始化];
022: if (!self) return self;
023:dgId =数据报类型;
024:返回自我;
025:}
026:
027:-(无效)dealloc {
028: NSLog(@"dealloc 数据报: %d",dgId);
029:[超级释放];
030:}
031:@结束
032:
033: // 假装来自声纳的数据包 ID 序列
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 //序列结束/数组标记
043:};
044:
045:@interface 数据报文件:NSObject 
046:{
047: // 没有 ivars
048:}
049:-(id)初始化;
050:@结束
051:
052:@实现数据报文件
053:-(id)初始化{
054:自我=[超级初始化];
055: if (!self) return self;
056://没有
057:返回自我;
058:}
059:
060:-(NSUInteger)countByEnumerationWithState:(NSFastEnumerationState *)状态对象:(id *)stackbuf计数:(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:如果(堆栈缓冲区){
065: NSLog(@"***检查堆栈缓冲区\n");
066: for(int i=0;iNSLog(@"Stackbuf %d: %p",i,stackbuf[i]); //stackbuf[i]应该怎么做?
068:}
069:}
070:如果(0 ==状态->状态){
071: NSLog(@"初始化循环");
072: 断言(0==state->itemsPtr);
073: 状态->itemsPtr = malloc(sizeof(id)*16);
074: memset(state->itemsPtr, 0, sizeof(id)*16);
075: } 否则 如果 (0==len) {
076: //如果调用在for循环中使用break,这个会被调用吗?
077: NSLog(@"完成循环。清理");
078:免费(状态->itemsPtr);
079: 状态->itemsPtr = 0;
080:返回 0;
081:}
082:状态->突变点=(无符号长*)自我; // 告诉调用者文件没有​​改变
083:
084: NSUInteger 计数=0;
085: for (; count state]!=0; count++, state->state++) {
086: NSLog(@"Creating datagram of type %d state: %d count %d",testSeq[state->state], state->state, count);
087: 数据报 *dg = [[数据报分配] initWithDatagramType:testSeq[state->state]];
088: 状态->itemsPtr[计数] = dg;
089:[dg自动释放];
090:}
091: NSLog(@"countByEnumeratingWithState 读取 %d 个数据报。state->state: %d",count, state->state);
092:返回计数;
093:}
094: @end //实现DatagramFile
095:
096: int main (int argc, const char * argv[]) {
097: NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
098:
099: 数据报文件 *df = [[数据报文件分配] 初始化];
100: for (数据报 *dg in df) {
101: NSLog(@"即将读取数据报");
102: NSLog(@"数据报类型: %d", [dg dgId]);
103:}
104:
105: NSLog(@"即将耗尽池");
106:[池排水];
107: NSLog(@"水池耗尽。准备过冬");
108:返回 0;
109:}

【问题讨论】:

    标签: objective-c cocoa


    【解决方案1】:

    奇数;我确信 The Objective-C Programming Language 曾经有更全面的文档。无论如何,回答您的具体问题:state->itemsPtr 是您放置实际结果的位置。 stackbuflen 提供可用于此目的的临时空间,但不是必须的。例如,如果您的集合使用对象引用的直接 C 数组,您可以将其直接放入 state->itemsPtr,从而一次性返回所有对象。

    至于你的实现:

    • 查看stackbuf的初始内容永远不会有用。
    • 不要使用malloc() 缓冲区,而是使用stackbuf。使用 len 而不是硬编码的 16。
    • “如果调用在 for 循环中使用了 break,这会被调用吗?”不,它不会。没有可靠的清理机会。
    • 如您所说,调用者可能会在循环中耗尽自动释放池。在这种情况下,没有一种完全“安全”的方式来处理临时对象。你所能做的就是记录调用者不能在迭代中耗尽在迭代之外创建的池。实际上,这不太可能成为问题。

    【讨论】:

    • 谢谢。我现在发布了一个更简洁的代码版本:schwehr.org/blog/attachments/2010-08/using-NSFastEnumeration.m
    • “对象引用的直接 C 数组”究竟是什么数据类型?它是一个 'unsigned long' 数组,还是你可以使用objective-c 'id' 类型创建一个c 数组?
    • @David:是的,你可以这样做。事实上,你必须实现NSFastEnumeration。这就是stackBufstate->itemsPtr 的含义。
    猜你喜欢
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 2016-08-29
    • 2020-10-07
    • 1970-01-01
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多