Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/112.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 线程完成时的Objective设置图像_Ios_Objective C_Multithreading_Uibutton_Thread Safety - Fatal编程技术网

Ios 线程完成时的Objective设置图像

Ios 线程完成时的Objective设置图像,ios,objective-c,multithreading,uibutton,thread-safety,Ios,Objective C,Multithreading,Uibutton,Thread Safety,我有一个按钮,我试图设置一个线程完成时的图像。我的代码可能看起来没有用,只是改变了图像按钮,但这是为了练习,并进入一个更大的事情 目标:将b0的图像设置为按钮_x.png(可在项目中找到) 问题:按钮图像没有改变,如果我在情节提要上找到的按钮与viewController按钮声明之间建立连接,我会在-[UIButton setImage:]:无法识别的选择器发送到实例0x8b4c270时崩溃 多谢各位 ViewController.h: @interface ViewController : U

我有一个按钮,我试图设置一个线程完成时的图像。我的代码可能看起来没有用,只是改变了图像按钮,但这是为了练习,并进入一个更大的事情

目标:将b0的图像设置为
按钮_x.png
(可在项目中找到)

问题:按钮图像没有改变,如果我在情节提要上找到的按钮与viewController按钮声明之间建立连接,我会在
-[UIButton setImage:]:无法识别的选择器发送到实例0x8b4c270
时崩溃

多谢各位

ViewController.h:

@interface ViewController : UIViewController {
    IBOutlet UIButton *b0;
    Game *instanceOfGame;
}

@property (nonatomic, strong) UIButton *b0;
@property (nonatomic, strong) Game *instanceOfGame;

@end
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize instanceOfGame;
@synthesize b0;
static NSString *postName = @"123";


- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(post:) name:postName object:nil];
    instanceOfGame = [[Game alloc] init];
    [instanceOfGame start];
}

- (void) post: (NSNotification *) result {
    NSNumber *str = [result object];
    if (str == 0) {
        [self.b0 performSelectorOnMainThread:@selector(setImage: ) withObject:[UIImage imageNamed:@"button_x.png"] waitUntilDone:NO];
    }

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
#import <Foundation/Foundation.h>

    @interface Game : NSObject
    @property (nonatomic, strong) NSNumber *choice;
    @property (nonatomic, strong) NSNotificationCenter *ns;
    -(void) start;
    @end
#import "Game.h"

@implementation Game

NSNotificationCenter *ns;
@synthesize ns;
@synthesize choice;
static NSString *postName = @"123";

-(id) init {
    if (self = [super init]) {
        ns = [NSNotificationCenter defaultCenter];
    }
    return self;
}

-(void) start {
    [self performSelectorInBackground:@selector(loadData) withObject:Nil];
}

-(void) loadData {
    choice = 0;

    [ns postNotificationName:postName object:choice];
}

@end
ViewController.m:

@interface ViewController : UIViewController {
    IBOutlet UIButton *b0;
    Game *instanceOfGame;
}

@property (nonatomic, strong) UIButton *b0;
@property (nonatomic, strong) Game *instanceOfGame;

@end
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize instanceOfGame;
@synthesize b0;
static NSString *postName = @"123";


- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(post:) name:postName object:nil];
    instanceOfGame = [[Game alloc] init];
    [instanceOfGame start];
}

- (void) post: (NSNotification *) result {
    NSNumber *str = [result object];
    if (str == 0) {
        [self.b0 performSelectorOnMainThread:@selector(setImage: ) withObject:[UIImage imageNamed:@"button_x.png"] waitUntilDone:NO];
    }

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
#import <Foundation/Foundation.h>

    @interface Game : NSObject
    @property (nonatomic, strong) NSNumber *choice;
    @property (nonatomic, strong) NSNotificationCenter *ns;
    -(void) start;
    @end
#import "Game.h"

@implementation Game

NSNotificationCenter *ns;
@synthesize ns;
@synthesize choice;
static NSString *postName = @"123";

-(id) init {
    if (self = [super init]) {
        ns = [NSNotificationCenter defaultCenter];
    }
    return self;
}

-(void) start {
    [self performSelectorInBackground:@selector(loadData) withObject:Nil];
}

-(void) loadData {
    choice = 0;

    [ns postNotificationName:postName object:choice];
}

@end
游戏。h:

@interface ViewController : UIViewController {
    IBOutlet UIButton *b0;
    Game *instanceOfGame;
}

@property (nonatomic, strong) UIButton *b0;
@property (nonatomic, strong) Game *instanceOfGame;

@end
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize instanceOfGame;
@synthesize b0;
static NSString *postName = @"123";


- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(post:) name:postName object:nil];
    instanceOfGame = [[Game alloc] init];
    [instanceOfGame start];
}

- (void) post: (NSNotification *) result {
    NSNumber *str = [result object];
    if (str == 0) {
        [self.b0 performSelectorOnMainThread:@selector(setImage: ) withObject:[UIImage imageNamed:@"button_x.png"] waitUntilDone:NO];
    }

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
#import <Foundation/Foundation.h>

    @interface Game : NSObject
    @property (nonatomic, strong) NSNumber *choice;
    @property (nonatomic, strong) NSNotificationCenter *ns;
    -(void) start;
    @end
#import "Game.h"

@implementation Game

NSNotificationCenter *ns;
@synthesize ns;
@synthesize choice;
static NSString *postName = @"123";

-(id) init {
    if (self = [super init]) {
        ns = [NSNotificationCenter defaultCenter];
    }
    return self;
}

-(void) start {
    [self performSelectorInBackground:@selector(loadData) withObject:Nil];
}

-(void) loadData {
    choice = 0;

    [ns postNotificationName:postName object:choice];
}

@end

UIButton没有setImage:函数,因此引发异常

但它确实具有以下功能:

- (void)setImage:(UIImage *)image forState:(UIControlState)state
尝试替换:

[self.b0 performSelectorOnMainThread:@selector(setImage: ) withObject:[UIImage imageNamed:@"button_x.png"] waitUntilDone:NO];
使用GCD调用正确的函数完成类似的实现:

dispatch_async(dispatch_get_main_queue(), ^{
   [self.b0 setImage:[UIImage imageNamed:@"button_x.png"] forState:UIControlStateNormal];
});
试试这个

if (str == 0) {
    dispatch_sync(dispatch_get_main_queue(), ^{
        [self.b0 setImage:[UIImage imageNamed:@"button_x.png"] forState:UIControlStateNormal];       
    });
}

@科林·科纳比说写吧

UIButton没有setImage方法

也可以使用相同的现有代码。只需在下一行更新

[self.b0 performSelectorOnMainThread:@selector(setImage: ) withObject:[UIImage imageNamed:@"button_x.png"] waitUntilDone:NO];
作为

然后定义方法setImage:

-(void)setImage:(UIImage *)img
{
    [self.bo setImage:img forState:UIControlStateNormal];
}

我希望它对你有用

哇,太棒了,谢谢!如果不太麻烦的话,你介意解释一下dispatch_async和我的区别吗?当然!dispatch\u async和dispatch\u sync是两个命令,允许您将其中的代码发送到另一个线程。在上面的示例中,我将块中的代码(在^{}中的部分,块是Obj-C的另一个特性)发送到主线程(dispatch_get_main_queue())。我在这里使用了dispatch_async,但是sync和async之间的区别是sync将等待内部的代码完成,async不会。它基本上相当于waitUntilDone。最近一个版本的objc.io包含了两个好的部分。对于长时间运行的操作,通常使用
dispatch\u queue\u create
创建队列,并使用
dispatch\u async
在该队列中提交任务。当结果可用时,您应该使用
dispatch\u async
并使用主队列(通过
dispatch\u get\u main\u queue
获得)用主线程更新用户界面。