Cocoa应用程序表现不同,断点为&离

时间:2012-06-10 22:43:12

标签: objective-c xcode cocoa debugging nsoperation

重要更新:我发现我的大多数问题都是基于错误的前提(请参阅下面的答案)。通知实际上已经到达接收器,他们刚刚到达那里太快了。 (尽管如此,它仍然无法解释为什么断点和没有断点的行为不同。)

我正在开发一个应用程序来计算给它的文件的哈希值。计算在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中的这种行为?我该如何解决这个问题?

(如果你想让我的所有代码重现它,我很乐意把它给你。)

更多实验:

  1. 如果我在断点处停止后完全继续执行,则应用程序在接收通知的代码中遇到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];
    
  2. 当我尝试重现之前的实验时,甚至发生了一些奇怪的事情。在我的调试设置中,我有两个哈希计算机对象:一个SHMD5HashComputer(我们正在讨论)和一个SHHashComputer(当然,它产生“未执行的”哈希)。在之前的所有实验中,只要app没有崩溃,SHHashComputer的通知形式总是成功到达。但在这种情况下,两个通知都没有到达,并且应用程序没有崩溃。 (所有步骤与前一步骤完全相同)。

  3. 正如Josh Caswell在评论中指出的那样,我没有正确使用通知。我应该将对象本身作为通知对象as described in documentation发送。我解决了这个问题,我得到了完全相同的结果。 (这意味着我正确地修复了它,因为有时候通知工作正常,而且这也不是问题)。
  4. 更多更新:

    我发送的通知应该到达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];
    }
    

1 个答案:

答案 0 :(得分:0)

实际上,问题是基于错误的前提。我认为通知从未通过,因为我从未看到GUI中显示的信息;但是,我的错误出现在控制器的代码中(未在那里发布),这使得GUI首先获得哈希计算结果的情况成为可能,并且只有在获得有关新输入的信息之后 - 这导致删除所有文本并激活进步动画。