从后台线程中的委托方法更改 UILabel 的文本不起作用

Posted

技术标签:

【中文标题】从后台线程中的委托方法更改 UILabel 的文本不起作用【英文标题】:Change text of UILabel from Delegate Method in Background Thread Not Working 【发布时间】:2012-06-18 15:41:41 【问题描述】:

HomeViewController.h

#import "DataParser.h"
@interface HomeViewController : UIViewController <DataParserDelegate>

    UILabel *theLabel;

HomeViewController.m

#import "HomeViewController.h"
@implementation HomeViewController
-(void)viewDidLoad

    theLabel = [[UILabel alloc] initWithFrame:CGRectMake(200, 200, 100, 30)];
    theLabel.text = @"Bob";
    theLabel.font = [UIFont italicSystemFontOfSize:20.0];
    theLabel.textColor = [UIColor whiteColor];
    theLabel.backgroundColor = [UIColor blueColor];
    [self.view addSubview:theLabel];

    UIButton *theButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [theButton addTarget:self action:@selector(clicked:) forControlEvents:UIControlEventTouchUpInside];
    [theButton setTitle:@"Big Button" forState:UIControlStateNormal];
    theButton.frame = CGRectMake(100,100,200,50);
    [self.view addSubview:theButton];

-(void)clicked:(id)sender

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0),
    ^
        DataParser *data = [[DataParser alloc] init];
        data.delegate = self;
        [data loadSomething];

        dispatch_async(dispatch_get_main_queue(),
        ^
            NSLog(@"Thread done");
        );
    );

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

    theLabel.frame = CGRectMake(250,250,100,30);
    theLabel.text = @"This message displays fine";

-(void)loadMessage:(NSString *)message

    NSLog(@"Received message: %@", message);
    theLabel.frame = CGRectMake(300,300,100,30);
    theLabel.text = @"This message won't display";

@end

DataParser.h

@protocol DataParserDelegate;

@interface DataParser : NSObject
@property (weak, nonatomic) id <DataParserDelegate> delegate;
-(void)loadSomething;
@end

@protocol DataParserDelegate <NSObject>
-(void)loadMessage:(NSString *)message;
@end

DataParser.m

#import "DataParser.h"
@implementation DataParser
@synthesize delegate=_delegate;
-(void)loadSomething

    [[self delegate] loadMessage:@"ASDF"];

@end

-=-=-=-=-=-=-=-=-=-=-=-=-=-

基本上,我创建一个标签并将其添加到屏幕上。此时,您可以清楚地看到一个蓝色按钮,上面有白色文字“Bob”。当您旋转屏幕时,按钮会很好地更改文本和位置。但是,如果我单击该按钮,它会创建一个 dataParser 对象,将委托设置为 self,并调用“loadSomething”。在 dataParser 对象中,“loadSomething”只是调用了委托方法“loadMessage”。

问题是,当调用“loadMessage”时,NSLog 语句会正确打印(“Received message: ASDF”),但是,theLabel 不会移动,也不会更改其文本。为什么是这样?我该如何解决这个问题?

【问题讨论】:

他是在主线程调用的吗? (UIKit 不是线程安全的) @Ganzolo 实际上,DataParser 实际上是在后台线程中运行的......我想我应该修改我的代码以显示这一点。这真的是问题吗? 【参考方案1】:

试试这个代码:

-(void)loadMessage:(NSString *)message

    dispatch_async(dispatch_get_main_queue(), ^
        NSLog(@"Received message: %@", message);
        theLabel.frame = CGRectMake(300,300,100,30);
        theLabel.text = @"This message displays great!";
    );

它应该在主线程上运行它。

【讨论】:

这太完美了!令人惊讶的是,您甚至没有提到它就诊断出我的后台线程问题!这完全解决了问题!非常感谢!

以上是关于从后台线程中的委托方法更改 UILabel 的文本不起作用的主要内容,如果未能解决你的问题,请参考以下文章

从 UILabel 或 UITextField 更改 UIButton 的标题

如何从 Xcode 中的 AppDelegate.m 文件更新 UILabel 的文本?

UILabel 不会改变屏幕

快速更改不同类中的一个类的属性(特别是 UILabel)

文本更改后 UILabel 未正确换行

更改自定义 UIView 的 UILabel 文本不起作用