Ios 线程完成时的Objective设置图像
我有一个按钮,我试图设置一个线程完成时的图像。我的代码可能看起来没有用,只是改变了图像按钮,但这是为了练习,并进入一个更大的事情 目标:将b0的图像设置为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
按钮_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
获得)用主线程更新用户界面。