【问题标题】:UIButton won't enable under some circumstancesUIButton 在某些情况下不会启用
【发布时间】:2016-01-15 11:30:19
【问题描述】:

在我的应用程序中,我使用的是 UIButton (myButton),这是我通过 Storyboard 添加的。
因此,当点击按钮时,IBAction 会被调用:

-(IBAction)buttonAction:(UIButton*)sender{
    [myCustomClass doSomeCrazyStuff];
    [sender setEnabled:NO];
}

如您所见,我正在从 myCustomClass 调用一个方法(myCustomClass 是我的网络服务的 REST 客户端)。
按钮所在的viewControllermyCustomClass 的代表。
实现了两种委托方法,一种用于成功,一种用于错误

-(void)requestSucceeded{  
    /* If the request succeeded i want the button to be enabled again, and it's selected  
       state inverted */  
    NSLog(@"This gets called");
    [myButton setEnabled:YES];
    [myButton setSelected:!myButton.selected];
}

这完全正常:我按下按钮,在myCustomClass 上完成操作,请求成功,按钮设置为倒选状态。
但现在对于另一个委托方法:

-(void)requestFailed{
    /* If the request failed i want the button to be enabled again, and it's selected  
       state stays the same */   
    NSLog(@"That gets called"); 
    [myButton setEnabled:YES];
}

如果requestFailed 被调用,控制台会按预期打印That gets called,但按钮保持禁用状态...我不知道为什么。
我在requestFailed 中尝试过其他的东西,比如:

[myButton setHidden:YES];

只是看看对myButton 的引用是否有效...
它是。

我现在可能遗漏了什么,但我想不通。
感谢您的帮助。

编辑:
我不认为requestFailed 可以从不同的线程调用(正如@gonji-dev 提到的那样),因为requestSucceededrequestFailed 都是从同一个方法调用的。
在我的doSomeCrazyStuff 方法中,我设置了一个完成块来处理连接成功和错误。如果发生错误,它将在另一个类中处理。如果连接成功,我将请求 HTTP 状态代码来决定是调用 requestFailed 还是 requestSucceeded

【问题讨论】:

  • 你能告诉我们你调用requestFailed的代码吗?可能你是从另一个线程调用它
  • 我会在[myButton setEnabled:YES];之后在requestFailed设置一个断点并检查目标是否仍然指向你的控制器。
  • 将 UI 更新强行转移到主线程,而不是假设 您不认为 会更容易,因为应该调试问题不基于随机假设;因为如果这是您的应用程序中的后台网络请求,那么它必须在后台线程中,并且无论他们调用它在该线程上执行什么。
  • 所以我尝试在 dispatch_async 中调用 request failed(dispatch_get_main_queue(), ^{ });现在按钮再次启用...谢谢但我仍然不知道为什么requestSucceeded 有效而requestFailed 无效。尽管我不知道为什么,但我很高兴它有效;)
  • @AlexanderHarl:直到我发布我的分析器后才看到此评论。如果您认为合适,我可以删除我的回复。此外,发生日志的简单断点会显示您所在的线程。

标签: ios objective-c uibutton


【解决方案1】:

https://stackoverflow.com/a/31952060/218152中的情况类似。
您是否绝对肯定您正在调用:

[myButton setEnabled:YES];

在主线程上?

在操作 UI 以响应通知或多线程环境时的行业标准是:

dispatch_async(dispatch_get_main_queue(), ^{
    // update UI
});

【讨论】:

  • 谢谢,我尝试在主线程上显式调用委托方法,现在它适用于两种方法。不知道为什么它以前不适用于requestFailed。但它一定与它在另一个线程上有关。
  • 安全胜于遗憾:在主线程之外调用 UI 是有风险的,并且可能会在生产环境中崩溃。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-02
  • 1970-01-01
  • 1970-01-01
  • 2021-06-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多