我真的不知道这是线程的问题,但我不知道还有什么可能导致我的问题。我有一个iOS应用程序,它有一个NSStreamDelegate调用
- (void) stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
代理被赋予AppDelegate的句柄,并且在StreamDelegate的每个其他部分中,AppDelegate都存在。但是,在stream:handleEvent:中,当我尝试将结果传递回AppDelegate进行其他处理时,我收到一个EXC_BAD_ACCESS错误。
我认为它可能是一个线程问题的唯一原因是流上的文档:handleEvent:states:
仅当在运行循环上调度了流时,委托才会收到此消息。消息在流对象的线程上发送。委托应该检查streamEvent以确定它应该采取的适当行动。
“流对象的线程”是否指向我的StreamDelegate?或者是对流传递给方法的引用?我假设后者,但我想确保我没有弄错。
如果是与我的AppDelegate不同的线程,那么是什么导致了我的问题?如果是这样,那我该如何处理呢?
编辑:根据@bbum,我正在更新以表明我已完成的工作。
在黑客攻击之后,我尝试了一些我考虑过的东西然后被解雇了。实际上,我创建了一个虚拟类,它可以实例化并从stream调用:handleEvent:。我将使用的方法称为:
[man performSelectorOnMainThread:@selector(saveEvent:) withObject:jsonDict waitUntilDone:YES];
在saveEvent:中,我回到AppDelegate并且(几乎!)从那时起一切正常。
我目前遇到调试器的问题,抱怨尝试写入不存在的文件。我不知道为什么会这样做。文件名看起来像是在应用程序的“iPhone模拟器/ 5.0 /应用程序/”下创建的散列目录,但我还没弄清楚错误发生在哪里。
真正混乱的一部分是我无法在任何崩溃上获得堆栈跟踪。我已经尝试使用LLVM 3.0和LLVM GCC 4.2,以及相应的调试器,但没有。我正在使用Xcode 4.2。 4.1我没有遇到这个问题。
感谢智慧的话,@ bbum。非常感激。一旦我完全删除了,我会发布另一个更新。
编辑(2011-10-18): [更新:没关系;我是个白痴。我正在将流读入字节数组但未声明显式大小。我遇到了某种缓冲区溢出。现在一切正常。]
由于上述错误,我一直在墙上撞了几天,然后重写了代码。我几乎已经把所有事情都搞定了,但线程似乎仍然在咬我。
我收到以下错误:
警告:无法恢复以前选择的框架。
我正在做的是接收NSInputStream上的数据,并将其写出,然后尝试刷新视图,以指示更新。在调用之后的某个时刻,我应该看到对viewWillAppear:(BOOL)动画的调用,但上面的警告首先出现,应用程序锁定。
我已经广泛搜索了上面的内容,通常会出现错误,当有某种无限循环,或堆栈溢出,或者是一些锤击内存的东西时。我看不到那种类型的事情发生了。我仍然认为我遇到了一个问题,我遇到了我的线程,而且堆栈变得混乱。我只是无法弄清楚原因。
上面调用的saveEvent:选择器执行其操作,然后修改视图中的属性以指示它是脏的。这个属性被触动了。我看到它发生在我休息时。但是viewWillAppear:永远不会被调用。
这令人沮丧。这似乎是一件很简单的事情,但这一直是一团糟。
答案 0 :(得分:1)
“流对象的线程”是否指向我的StreamDelegate?或者是 那个流被引入方法的引用?我在假设 后来,但想确保我没有弄错。
每个线程只能有一个runloop。该委托将在任何线程上调用,即调度流的runloop。
如果它与我的AppDelegate所在的线程不同,那么就是 是什么导致了我的问题?如果是这样,那我该如何处理呢?
可能是;如果你的AppDelegate不是线程安全的,并且流是在非主线程上安排的,那很可能是问题。
没有更多信息,就不可能多说。由于应用程序崩溃,您至少应该发布回溯。
答案 1 :(得分:0)
你解决了吗?我正在做一些非常相似的事情,并让它工作,虽然我遇到一个问题,随机没有收到应该出现在流上的所有字符。
如果有帮助我可以发布在我的情况下工作的代码。
实际上,我的代码启动了一个后台线程,委托随后用它来监视流。
-(void)backgroundThreadFunction:(NSObject*)obj
{
[self setBackgroundThread:[NSThread currentThread]];
[streamDelegate OpenSession:accessoryInfo];
while(_continueRunning) {
NSAutoReleasePool *_pool = [[NSAutoReleasePool alloc] init];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate date]];
[_pool release];
}
[self setBackgroundThread:nil];
}
Stream委托OpenSession指定以下列方式在当前线程上运行。
[[currentSession inputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[currenSession outputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
当我希望appDelegate知道某些东西时,我通常会使用已经为该事件注册的NSNotification。
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataReceived" object:_receivedData];
希望有所帮助。
此致