重要更新:我发现我的大多数问题都是基于错误的前提(请参阅下面的答案)。通知实际上已经到达接收器,他们刚刚到达那里太快了。 (尽管如此,它仍然无法解释为什么断点和没有断点的行为不同。)
我正在开发一个应用程序来计算给它的文件的哈希值。计算在SHHashComputer中进行。它是一个抽象类(好吧,意图是抽象的,因为Objective C中没有抽象类),它接受文件路径并创建NSInvocationOperation。反过来,它调用方法(void)computeAndSendHash,它使用对象中保存的文件路径来计算哈希并将其作为通知发送。实际计算发生在子类需要覆盖的(NSString *)computeHash方法中。
这是SHHashComputer.m:
- (NSString*)computeHash {
return [NSString stringWithFormat:@"unimplemented hash for file %@", self.path];
}
- (void)computeAndSendHash {
NSString *result = [self computeHash];
NSString *notificationName = [NSString stringWithFormat:@"%@%@",
gotResultNotification,
self.hashType];
[[NSNotificationCenter defaultCenter] postNotificationName:notificationName
object:result];
self.operation = nil;
}
这是SHMD5Computer.m(SHHashComputer的子类):
- (NSString*)computeHash {
return @"MD5 test"; // it actually doesn't matter what it returns
}
我不会打扰通知的接收者。让我们说只要我在SHMD5Computer.m中注释掉computeHash方法,一切正常:收到带有文本“未实现的...”的通知&在GUI中显示。但如果我不这样做 - 那么它真的很有趣。
如果我没有设置任何断点,则通知永远不会。但是,如果我在SHMD5Computer.h 和中的computeHash声明中设置断点,则跳过“self.operation = nil”行,和继续执行那一点,通知到达目的地。如果我不停在那里,调试器突然切换到状态,好像它没有调试任何东西,并且应用程序冻结。
我不认为'WTF'在这里是一个很好的问题形式,所以让我这样说:我错过了什么?我的代码中是否有错误?什么可以导致xcode中的这种行为?我该如何解决这个问题?
(如果你想让我的所有代码重现它,我很乐意把它给你。)
更多实验:
如果我在断点处停止后完全继续执行,则应用程序在接收通知的代码中遇到EXC_BAD_ACCESS错误,在最后一行:
id newResult = [newResultNotification object];
if (newResult == nil)
[NSException raise:@"No object"
format:@"Expected object with notification!"];
else if (![newResult isKindOfClass:[NSString class]])
[NSException raise:@"Not NSString"
format:@"Expected NSString object!"];
else
self.result = (NSString*) newResult;
[self.textField setStringValue:self.result];
当我尝试重现之前的实验时,甚至发生了一些奇怪的事情。在我的调试设置中,我有两个哈希计算机对象:一个SHMD5HashComputer(我们正在讨论)和一个SHHashComputer(当然,它产生“未执行的”哈希)。在之前的所有实验中,只要app没有崩溃,SHHashComputer的通知形式总是成功到达。但在这种情况下,两个通知都没有到达,并且应用程序没有崩溃。 (所有步骤与前一步骤完全相同)。
更多更新:
我发送的通知应该到达SHHashResultViewController。这就是我创建它并注册通知的方式:
- (id)initWithHashType:(NSString *)hashType {
self = [self initWithNibName:@"SHHashResultView" bundle:[NSBundle mainBundle]];
if (self) {
[self setHashType:hashType];
}
return self;
}
- (void)setHashType:(NSString *)hashType {
[self.label setStringValue:[NSString stringWithFormat:@"%@:", hashType]];
_hashType = hashType;
NSString *notificationName = [NSString stringWithFormat:@"%@%@",
gotResultNotification,
_hashType];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(gotResult:)
name:notificationName
object:nil];
}
答案 0 :(得分:0)
实际上,问题是基于错误的前提。我认为通知从未通过,因为我从未看到GUI中显示的信息;但是,我的错误出现在控制器的代码中(未在那里发布),这使得GUI首先获得哈希计算结果的情况成为可能,并且只有在获得有关新输入的信息之后 - 这导致删除所有文本并激活进步动画。