通过Interface Builder创建的UIButton崩溃了。

3
我已经找到了一个很棘手的问题,但由于它似乎是nib/Interface Builder内部的问题,我不知道该怎么办。
我在IB中创建了一个UIView,用作自定义对话框。它显示一条消息和两个按钮(继续或取消)。两个按钮都在Interface Builder中设置了背景图像。
某些东西处理取消按钮的背景图像时出了问题。使用NSZombieEnabled,我一直在运行这个程序。最常见的情况是下面的方法记录了这个问题:
-[ModalDialog showInView:title:message:cancelText:proceedText:]
dialogProceedButton <UIButton: 0x7031f10; frame = (286 192; 90 31) // (etc.)
dialogProceedButtonBackground <UIImage: 0x3b36120>
dialogCancelButton <UIButton: 0x3b39cd0; frame = (104 192; 90 31) // (etc.)
dialogCancelButtonBackground <UIImage: 0x3b3a920>

这是完全正常的。但有时会出现这种情况(如果我快速点击某些界面按钮来“加快”UI速度,我可以让它重复一些):

-[ModalDialog showInView:title:message:cancelText:proceedText:]
dialogProceedButton <UIButton: 0x7031f10; frame = (286 192; 90 31) // (etc.)
dialogProceedButtonBackground <UIImage: 0x3b36120>
dialogCancelButton <UIButton: 0x3b39cd0; frame = (104 192; 90 31) // (etc.)
*** -[UIImage retain]: message sent to deallocated instance 0x3b3a920

如您所见,NSZombieEnabled发现取消按钮的背景图像已被释放,但仍收到了一个保留消息。(不是我发送的...该图像仅用于此按钮,且仅在Interface Builder中访问。我没有任何IBOutlets或与该图像相关联的变量。)
那么,现在怎么办?
编辑:
有时,并不是一个保留消息被捕获为zombie,有时是isKindOfClass:。
//(the object address is always dialogCancelButton.currentBackgroundImage)
-[UIImage isKindOfClass:]: message sent to deallocated instance 0x1661f0
//occasionally, these come along, too:
*** NSInvocation: warning: object 0x7e0d0b0 of class '_NSZombie_UIImage' does not implement methodSignatureForSelector: -- trouble ahead
*** NSInvocation: warning: object 0x7e0d0b0 of class '_NSZombie_UIImage' does not implement doesNotRecognizeSelector: -- abort

This is my custom UIViews "showInView" method:

- (void)showInView:superView 
             title:(NSString*)title 
             message:(NSString*)message 
             cancelText:(NSString*)cancelText 
             proceedText:(NSString*)proceedText {

NSLog(@"%s",__PRETTY_FUNCTION__);
NSLog(@"dialogProceedButton %@", dialogProceedButton);
NSLog(@"dialogProceedButtonBackground %@", dialogProceedButton.currentBackgroundImage);
NSLog(@"dialogCancelButton %@", dialogCancelButton);
NSLog(@"dialogCancelButtonBackground %@", dialogCancelButton.currentBackgroundImage);



CGRect rect;
dialogTitle.text = title;
dialogMessage.text = message;
[dialogProceedButton setTitle:proceedText forState:UIControlStateNormal];

if (cancelText == @"") { // SINGLE BUTTON DIALOG
  dialogCancelButton.hidden = YES;
  rect = [dialogProceedButton frame];
  rect.origin.x = 195; //center the button 
  [dialogProceedButton setFrame:rect];
} else {
  [dialogCancelButton setTitle:cancelText forState:UIControlStateNormal];
  dialogCancelButton.hidden = NO;
  rect = [dialogProceedButton frame];
  rect.origin.x = 286; //button on right of dialog box 
  [dialogProceedButton setFrame:rect];
}

[UIView beginAnimations:@"modalAppears" context:nil];
[UIView setAnimationDuration:0.5];
[superView addSubview:self];
self.alpha = 1.0;
[UIView commitAnimations];
}

谢谢!

2个回答

3

好的,这个问题有点让人摸不着头脑。我决定尝试颠倒“继续”和“取消”按钮的图像。结果是现在继续按钮的图像会导致崩溃(就像之前一样间歇性地)。我完全从我的项目和界面生成器中删除了该图像。然后我添加了一个新的副本,并命名并连接了它。

在之前的设置中,我能够约40%的时间复制崩溃。在这些更改之后,我尝试了大约20次复制崩溃,现在完全无法再复制崩溃。

如果图像或nib被损坏,为什么会导致随机/间歇性症状呢?

希望这个问题已经被彻底解决了。


更新:

所以事情还有点复杂。事实证明我巧合地在我的(不完整的)指令视图中使用了同一张图片作为占位符。为了临时方便,我正在使用[UIImage imageNamed:]来获取该图片。它被正确分配和释放,但似乎IB与imageNamed:方法和/或缓存的合作并不完美。

当我去获取图像的新副本时,我还给它了一个新的名称,这意味着现在IB按钮图像和临时占位符图像根本不是同一张图片。

我回到了几天前的项目备份来测试我的理论。我所做的就是告诉指令视图使用不同的占位符图像。崩溃停止了。

这可能是SDK的一个错误。没有任何理由不在IB中使用图像,并使用imageNamed:在其他地方使用相同的图像。如果有一天我感到狡猾或无聊,也许我会将其简化为一个示例项目发送给Apple radar。


这对我来说似乎非常不可能 - 我认为很多人一直在使用图像名称和IB。虽然测试一下会很有趣。 - Kendall Helmstetter Gelner

0
你的XIB文件是如何连接到你的视图的?你定义了哪些IBOutlets?我真的怀疑你用描述的方式解决了你的问题。

我同意看起来这不应该是问题的原因(或解决方法),但自从我做了那件事情后,它就没有崩溃过。在我确信可以前进之前,我大概试了50次左右去重现这个崩溃。在更改之前,我每尝试2到4次就会出现崩溃。 耸肩. - Rob
确实如此,还有更多的内容...请查看我完整答案中的更新。 - Rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接