【问题标题】:UIButton title text is not updated even if I update it in Main thread即使我在主线程中更新 UIButton 标题文本也不会更新
【发布时间】:2013-11-27 05:15:34
【问题描述】:

当用户单击它时,我正在尝试更改我以编程方式创建的UIButton 的标题。所以,这是我创建UIButton的代码:

myButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, parentView.frame.size.width, parentView.frame.size.height)];
[myButton setBackgroundColor:[UIColor blackColor]];
[myButton setAlpha:0.7];
[myButton setTitle:@"Hello" forState:UIControlStateNormal];
[myButton addTarget:self action:@selector(userClicked:) forControlEvents:UIControlEventTouchUpInside];

[parentView addSubview:myButton];

而且,在我的 userClicked: 方法中,我这样做:

-(void) userClicked:(UIButton*)button
{
    NSLog(@"USER CLICKED!!!");
    if ([NSThread isMainThread])
    {
        NSLog(@"is main thread");
    }

    [button setTitle:@"Bye" forState:UIControlStateHighlighted];
    [button setTitle:@"Bye" forState:UIControlStateNormal];
    [button setTitle:@"Bye" forState:UIControlStateSelected];

    [self someLengthyComputation];
}

奇怪的是我可以看到打印的日志消息:

USER CLICKED!!! 
isMainThread

但是,按钮的标题并没有改变!我做错了什么?

编辑:为几个州设置标题也不起作用。

EDIT2:如果我在 Xcode 的调试器窗口中打印按钮的描述,它会显示正确的标题!

Printing description of button->_titleView:
<UIButtonLabel: 0xa4c9310; frame = (95 216; 130 22); text = 'Bye'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0xa44f080>>

【问题讨论】:

  • 也许你的按钮不在 UIControlStateNormal 状态?
  • 你在哪里添加了按钮作为子视图?
  • 什么是 parentView ..?
  • @AnandK parentView 是UIViewController 的主要UIView
  • 但是,即使我为 UIControlStateNormal、UIControlStateSelected 和 UIControlStateHighlighted 设置了标题,标题也不会改变。我会用我的实际代码更新我的问题。

标签: ios objective-c uibutton ios7 xcode5


【解决方案1】:

试试这个:

[button setTitle:@"Bye" forState:UIControlStateHighlighted];

或:

[button setTitle:@"Bye" forState:UIControlStateSelected];

你也可以修改你的 void 函数:

-(void) userClicked
{
    NSLog(@"USER CLICKED!!!");
    if ([NSThread isMainThread])
    {
        NSLog(@"is main thread");
    }

    [myButton setTitle:@"Bye" forState:UIControlStateNormal];
}

【讨论】:

  • 谢谢! [button setTitle:@"Bye" forState:UIControlStateHighlighted]; 成功了!
  • OK,我的错,即使我为UIControlStateNormalUIControlStateSelectedUIControlStateHighlighted设置了标题,标题也没有改变。我会用我的实际代码更新我的问题。
  • 也编辑了我的答案。将 myButton 声明为属性,以便您可以在 void 函数中引用它。
  • 不工作 :( ,该问题与主线程无关,因为如果您没有导航到另一个 Uiviewcontroller,您可以更新按钮
【解决方案2】:

请看看这是否对你有帮助...当按钮被点击时检查条件如果 buttonToggled...当你有一个类似 changeButtonText 的功能时,如下所示

-(IBAction)changeButtonText:(id)sender {
    if (!buttonToggled) {
        [sender setTitle:@"Initial Text" forState:UIControlStateNormal];
        buttonToggled = YES;
    } else {
        [sender setTitle:@"Alternative Text" forState:UIControlStateNormal];
        buttonToggled = NO;
    }
}

【讨论】:

    【解决方案3】:

    我怀疑作为参数传入的'button'是否是myButton。无论如何,如果myButton是一个成员var,你可以[myButton setTitle:@"Bye" forState:UIControlStateNormal];

    【讨论】:

    • 我已经检查过了,并且 button 实际上等于 myButton。问题出在按钮状态。请参阅已接受的答案。还是谢谢你!
    • 我以为你会在永远点击按钮后更改文本。无论如何,恭喜。
    【解决方案4】:

    您的代码中有几个问题:

    您正在为按钮分配回调:

    @selector(userClicked:)
    

    但您的代码是另一种方法:

    -(void)userTapOnTapToRefreshView:(UIButton*)button
    

    要解决这个问题,您需要实现以下内容:

    -(void)userClicked:(id)sender
    {
        [(UIButton*)sender setTitle:@"Bye" forState:UIControlStateNormal];
    }
    

    这部分代码对我来说也没有意义:

    [parentView myButton];
    

    尝试将其更改为:

    [parentView addSubview:myButton];
    

    希望它会有所帮助:)

    【讨论】:

    • 非常感谢您的回答。事实上,所有这些错误都是我在尝试剥离我的真实代码以在这里发布我的问题时犯的。我已经编辑了我的原始帖子,以显示正确的代码以及您指出的更改。
    【解决方案5】:

    终于,我想通了。有两个问题:

    1) button 不在状态 UIControlStateNormal

    2) 我在设置标题[self someLengthyComputation] 后调用了一个执行长时间计算的方法。

    我已经解决了这个问题:

    1) 设置按钮所有状态的标题。

    2) 在另一个线程中执行大计算,而不是在主线程中。

    我现在的工作代码是:

    -(void) userClicked:(UIButton*)button
    {
        NSLog(@"USER CLICKED!!!");
        if ([NSThread isMainThread])
        {
            NSLog(@"is main thread");
        }
    
        [button setTitle:@"Bye" forState:UIControlStateHighlighted];
        [button setTitle:@"Bye" forState:UIControlStateNormal];
        [button setTitle:@"Bye" forState:UIControlStateSelected];
        dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
            [self someLengthyComputation];
        });
    }
    

    非常感谢所有回答/评论的人!

    【讨论】:

    • 不工作 :( ,该问题与主线程无关,因为如果您没有导航到另一个 Uiviewcontroller,您可以更新按钮
    【解决方案6】:

    这对我更新标题文本很有用(iOS 7.1,Xcode 5.1):

    button.enabled = FALSE;
    [button setTitle:@"Test" forState:UIControlStateNormal];
    button.enabled = TRUE;
    

    【讨论】:

    • 除了这个技巧对我有用。自从我切换到 XCode5.1/iOS7.1 后,它停止更新标题。太烦人了。
    • 似乎是 iOS7.1 SDK 上的一个已知错误。 prod.lists.apple.com/archives/cocoa-dev/2014/Mar/msg00274.html
    • 这真的让我想把我的拳头穿过我的显示器。很棒的收获。
    • 与 iOS 7.1 和 Xcode 5 完全相同的问题。很好。一个恼人的错误!
    • 使用 setTitle 而不是 button.titleLabel.text 对我有用。
    【解决方案7】:

    这有点晚了,有点与 Walter Schurter 的回应有关:

    在我更新到 7.1 之前,我遇到了类似的问题,我的按钮文本设置正确。然后我发现,由于我的按钮被禁用,我必须为禁用状态设置标题颜色和标题文本才能显示文本。然后一切都像魅力一样!

    【讨论】:

      【解决方案8】:

      嗯,关于 UIButton 的启用状态,Apple 在 7.1 中更改了一些内容,如果 UIButton 处于禁用状态,则不允许您更改标题,仅此而已。

      感谢 Apple,我已经失去了 10 分钟。调试运行良好的应用程序。

      今天早上才发现,昨天更新 XCode 到 5.1.1 和 iOS 到 7.1

      【讨论】:

        【解决方案9】:

        目前,我想到的最短的工作是调用:

        [button setNeedsLayout];
        

        更新标题后。

        这似乎发生在 iOS 7.1 中。 在 Xcode 5.1.1 SDK 7.1 中编译时,我所有的按钮在以前的 iOS 版本中表现正确(或者可能只是使用以前的 SDK 编译)突然停止了。

        看起来像 Apple 的错误。

        【讨论】:

        • 是正确的。 [button setNeedsLayout] 将在 iOS 7.1 中发挥作用
        • 在 iOS 9.2 中这对我来说仍然是必需的
        【解决方案10】:

        根据 Apple 开发人员指南,您不应将按钮标题标签文本或颜色直接设置为属性(例如,not 这样做:myButton.titleLabel.text=@"SomeText"或 myButton.titleLabel.textColor=[UIColor blackColor])。

        相反,您可以使用 UIButton 设置器功能设置它们,如下所示:

            [myButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        

        ...或者像这样:

            [myButton setTitle:@"SomeText" forState:UIControlStateNormal];.
        

        the Apple guide

        【讨论】:

        • 不是在我发布回复时。
        • 啊,¿有什么方法可以告诉我们吗?
        【解决方案11】:

        我遇到了同样的问题,我注意到我在其他任何地方都设置了属性标题。因此,对标题的任何更新都不会影响属性标题。

        我的解决方案:

        [button setAttributedTitle:@"" forState:UIControlStateNormal];
        

        而不是

        [button setTitle:@"" forState:UIControlStateNormal];
        

        【讨论】:

        • 这对我来说是个问题:我之前使用属性字符串引用了按钮的标题来调整跟踪,如果我只是使用 setTitle,它将不再更新。请注意,您不能传递简单的字符串,您需要这样的内容: [_myButton setAttributedTitle:[[NSAttributedString alloc] initWithString:@"New title for button" attributes:nil] forState:UIControlStateNormal];
        • 我在 XCode 9.4.1 / swift 上,我遇到了同样的问题。 setAttributedTitle 是唯一对我有用的解决方案
        【解决方案12】:

        在 UIButton 上设置文本之前总是做 addSubview。

        【讨论】:

        • 你能贴一些代码来说明你的意思吗?
        • 我们无法理解您的意思。
        【解决方案13】:

        可能是按钮布局刷新问题..... 尝试使用...

        [button setNeedsLayout];
        [button layoutIfNeeded];
        

        它将强制按钮更新布局。

        【讨论】:

          【解决方案14】:

          我在使用情节提要时遇到了类似的问题。使用上面的答案我不得不使用

          [mybutton setTitle:@"SomeText" forState:UIControlStateNormal];
          [button setNeedsLayout];
          [button layoutIfNeeded];
          

          而且我必须确保属性检查器中的按钮类型是“自定义”而不是“系统”。

          【讨论】:

          • 有了那个 AND ...评论你拯救了我的一天!谢谢你。就是这样 - 当你继承子类时,永远不要忘记在故事板中将按钮设置为“自定义”,否则行为可能会很奇怪。
          • 谢谢谢谢谢谢。在过去的 1 周里,我一直在头疼。你的“和”部分让我很开心..
          • 我只需要将类型设置为自定义,不需要添加setNeedsLayout或layoutIfNeeded。
          • 谢谢,您为我指出故事板中的按钮样式节省了我的时间!我的问题实际上是故事板中设置的按钮样式是系统而不是自定义:)
          • [按钮 setNeedsLayout];和[按钮布局IfNeeded];除了一个区别之外,它们是相同的。第一个异步工作,第二个同步工作。所以它们中的任何一个都可以正常工作,
          【解决方案15】:

          在 iOS 7 中,UIButton 的标题在禁用时不会更新。这似乎是 iOS 7 上的一个错误。

          作为一种解决方法,更新正常和禁用的标题。有效!

          [button setTitle:title forState:UIControlStateNormal];
          [button setTitle:title forState:UIControlStateDisabled];
          

          【讨论】:

          • 我爱你@ccoroom。拯救了我的夜晚。
          • 你也可以这样写一行:[button setTitle:title forState:UIControlStateNormal | UIControlStateDisabled];
          【解决方案16】:

          这可能是微不足道的,但如果您设置一些按钮图像(而不是背景图像)填充整个按钮框架,这将向右移动标题,从而使其不可见。 如果是这样,请尝试将按钮图像更改为背景图像。

          【讨论】:

            【解决方案17】:

            就我而言,我尝试了所有方法,但没有任何效果。 然后我只是将按钮类型从系统更改为故事板中的自定义。繁荣!一切开始正常运行。

            【讨论】:

              【解决方案18】:

              没有要求使用:

              [button setNeedsLayout];
              [button layoutIfNeeded];
              

              相反,首先将 type 设置为 DEFAULT 为 CUSTOM

              如果您申请了setAttributedTitle,则使用:

              [button setAttributedTitle:[NSAttributedString new] forState:UIControlStateNormal];
              

              否则无需更改任何内容。

              如果文本的颜色没有改变,则应用相同的内容并设置标题颜色:

              [button setTitleColor:[any_color] forState:UIControlStateNormal];
              

              【讨论】:

                【解决方案19】:

                尝试了很多解决方案后的结论是使用 setAttributedTitle 而不是 setTitle。

                为 AttributedString 制作标题字符串:

                NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:@" new Test "];
                
                [button setAttributedTitle:attString forState:UIControlStateNormal];
                

                顺便说一下,这个问题在正常情况下不是偶尔发生,而是突然发生主要有以下几个原因:

                1. 如果您更改UIButton 的启用状态并尝试更改标题。

                2. 如果您使用属性值,然后想使用 setTitle 更改它,那么在这种情况下,属性值优于标题。

                3. 如果您导航到另一个视图控制器,然后返回以更新按钮标题。

                【讨论】:

                  【解决方案20】:

                  尝试在界面或视图/视图控制器的实现部分中将按钮声明为属性

                  @property(nonatomic,strong) UIButton* myButton;
                  

                  然后创建它

                  self.myButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, parentView.frame.size.width, parentView.frame.size.height)];
                  [_myButton setBackgroundColor:[UIColor blackColor]];
                  ...
                  

                  它应该工作。不要问我为什么真的 - 我只是认为这完全是关于 ARC / 现代内存管理..

                  编辑:

                  如果您在实现中保留对按钮的引用,它也应该可以工作..

                  @implementation myViewController
                  {
                      UIButton* myButton;
                  }
                  
                  -(void)createButton
                  {
                      myButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, parentView.frame.size.width, parentView.frame.size.height)];
                      [myButton setBackgroundColor:[UIColor blackColor]];
                      ...
                  }
                  
                  ...
                  

                  【讨论】:

                    【解决方案21】:

                    将按钮类型更改为“自定义”,而不是“系统”,它将按预期工作:)

                    【讨论】:

                      【解决方案22】:

                      对于 Swift 35,只需使用以下代码:

                      button.setTitle("My title", for: .normal)
                      

                      或者对于属性文本使用这个:

                      button.setAttributedTitle(<AttributedString>, for: .normal)
                      

                      【讨论】:

                        【解决方案23】:

                        以上都不适用于我的情况(我在 UIPopoverController 呈现的视图顶部有一个按钮),我必须在 setTitle 之前 removeFromSuperview,然后 addSubview 回来 - 希望这对有类似问题的人有所帮助

                        【讨论】:

                          【解决方案24】:

                          而不是 yourButton.titleLabel?.text = "T"

                          使用这个 yourButton.setTitle("TITLE", for: .normal)

                          【讨论】:

                            猜你喜欢
                            • 2017-03-25
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2015-12-21
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多