NSTimer 不调用选择器或按时间间隔重复
NSTimer does not call selector or repeat in time interval
我是 objective-c 的新手,在使用 NSTimer 时遇到了问题。在通过开发游戏学习 objective-c 时,我尝试在 NSTimer 的帮助下使用左右按钮移动精灵。但是,似乎没有调用选择器。我搜索了堆栈溢出并找到了一些解决方案,但我见过的任何解决方案都不起作用。这是我的代码-
#import "GameViewController.h"
@interface GameViewController ()
@property (strong) UIImage *playerImage;
@property (strong) UIImageView *playerView;
@property (strong) NSTimer *moveTimer;
@property CGRect playerRect;
@property int count;
@end
@implementation GameViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.count=0;
self.playerImage = [UIImage imageNamed:@"ship.png"];
self.playerView = [[UIImageView alloc] initWithImage: self.
playerImage];
self.playerRect = CGRectMake(50,400, 32,32);
self.playerView.frame = self.playerRect;
[self.view addSubview: self.playerView];
// this timer calls selector
// self.moveTimer = [NSTimer scheduledTimerWithTimeInterval:.03
// target:self
// selector:@selector(movePlayerRight:)
// userInfo:nil
// repeats:YES];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)moveLeft:(id)sender {
[self releaseTouch];
NSLog(@"Left Move");
//this timer does not call selector
self.moveTimer = [NSTimer scheduledTimerWithTimeInterval:.03
target:self
selector:@selector(movePlayerLeft:)
userInfo:nil
repeats:YES];
// [[NSRunLoop mainRunLoop] addTimer:self.moveTimer forMode:NSDefaultRunLoopMode];
// [[NSRunLoop mainRunLoop] run];
//[self.moveTimer fire];
}
- (IBAction)moveRight:(id)sender {
[self releaseTouch];
NSLog(@"Right Move");
// if(![NSThread isMainThread])
// dispatch_async(dispatch_get_main_queue(), ^{
//this timer does not call selector
self.moveTimer = [NSTimer scheduledTimerWithTimeInterval:.03
target:self
selector:@selector(movePlayerRight:)
userInfo:nil
repeats:YES];
}
- (IBAction)TouchRelease:(id)sender {
[self releaseTouch];
}
-(void) movePlayerRight:(NSTimer*)timer {
NSLog(@"Right Move Selector");
if(self.playerRect.origin.x <= 320){
self.playerRect = CGRectOffset(self.playerRect, 3, 0);
self.playerView.frame = self.playerRect;
}
}
-(void) movePlayerLeft:(NSTimer*)timer {
NSLog(@"Left Move Selector");
if(self.playerRect.origin.x >= 10){
self.playerRect = CGRectOffset(self.playerRect, -3, 0);
self.playerView.frame = self.playerRect;
}
}
-(void)releaseTouch{
if(self.moveTimer != nil){
[self.moveTimer invalidate];
self.moveTimer = nil;
}
}
@end
让我解释一下我的尝试。
- 我尝试使用 scheduledTimerWithTimeInterval,如代码所示。但是不行。
- 然后我尝试了 timerWithTimeInterval 然后 NSRunloop。没有 NSRunloop [moveTimer fire] 触发但 NSRunLoop 重复,它不会。
然后,在一个解决方案中,我发现,线程可能正在创建问题;所以,我尝试了-
if(![NSThread isMainThread])
dispatch_async(dispatch_get_main_queue(), ^{
但是,线程不是这种情况,因为调试器不会进入“dispatch_async”行。
- 为了实际查看 NSTimer 的工作原理,我什至在“viewDidLoad”方法中 运行 并且它有效。
我做错了什么?
**解决方案:**
正如@Danil Valeev 和@aman.sood 所建议的那样,取消选中 Storyboard 自动布局,将 属性 更改为 'nonatomic';现在从计时器调用选择器:)
检查是否调用了 movePlayerRight: 或 movePlayerLeft:。并且视图中没有使用自动布局(我认为这是原因)。您可以在实用程序第一个选项卡的 xib/storyboard 文件中禁用自动布局。
将 [NSRunLoop mainRunLoop] 替换为 [NSRunLoop currentRunLoop] 它应该可以工作
我是 objective-c 的新手,在使用 NSTimer 时遇到了问题。在通过开发游戏学习 objective-c 时,我尝试在 NSTimer 的帮助下使用左右按钮移动精灵。但是,似乎没有调用选择器。我搜索了堆栈溢出并找到了一些解决方案,但我见过的任何解决方案都不起作用。这是我的代码-
#import "GameViewController.h"
@interface GameViewController ()
@property (strong) UIImage *playerImage;
@property (strong) UIImageView *playerView;
@property (strong) NSTimer *moveTimer;
@property CGRect playerRect;
@property int count;
@end
@implementation GameViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.count=0;
self.playerImage = [UIImage imageNamed:@"ship.png"];
self.playerView = [[UIImageView alloc] initWithImage: self.
playerImage];
self.playerRect = CGRectMake(50,400, 32,32);
self.playerView.frame = self.playerRect;
[self.view addSubview: self.playerView];
// this timer calls selector
// self.moveTimer = [NSTimer scheduledTimerWithTimeInterval:.03
// target:self
// selector:@selector(movePlayerRight:)
// userInfo:nil
// repeats:YES];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)moveLeft:(id)sender {
[self releaseTouch];
NSLog(@"Left Move");
//this timer does not call selector
self.moveTimer = [NSTimer scheduledTimerWithTimeInterval:.03
target:self
selector:@selector(movePlayerLeft:)
userInfo:nil
repeats:YES];
// [[NSRunLoop mainRunLoop] addTimer:self.moveTimer forMode:NSDefaultRunLoopMode];
// [[NSRunLoop mainRunLoop] run];
//[self.moveTimer fire];
}
- (IBAction)moveRight:(id)sender {
[self releaseTouch];
NSLog(@"Right Move");
// if(![NSThread isMainThread])
// dispatch_async(dispatch_get_main_queue(), ^{
//this timer does not call selector
self.moveTimer = [NSTimer scheduledTimerWithTimeInterval:.03
target:self
selector:@selector(movePlayerRight:)
userInfo:nil
repeats:YES];
}
- (IBAction)TouchRelease:(id)sender {
[self releaseTouch];
}
-(void) movePlayerRight:(NSTimer*)timer {
NSLog(@"Right Move Selector");
if(self.playerRect.origin.x <= 320){
self.playerRect = CGRectOffset(self.playerRect, 3, 0);
self.playerView.frame = self.playerRect;
}
}
-(void) movePlayerLeft:(NSTimer*)timer {
NSLog(@"Left Move Selector");
if(self.playerRect.origin.x >= 10){
self.playerRect = CGRectOffset(self.playerRect, -3, 0);
self.playerView.frame = self.playerRect;
}
}
-(void)releaseTouch{
if(self.moveTimer != nil){
[self.moveTimer invalidate];
self.moveTimer = nil;
}
}
@end
让我解释一下我的尝试。
- 我尝试使用 scheduledTimerWithTimeInterval,如代码所示。但是不行。
- 然后我尝试了 timerWithTimeInterval 然后 NSRunloop。没有 NSRunloop [moveTimer fire] 触发但 NSRunLoop 重复,它不会。
然后,在一个解决方案中,我发现,线程可能正在创建问题;所以,我尝试了-
if(![NSThread isMainThread]) dispatch_async(dispatch_get_main_queue(), ^{
但是,线程不是这种情况,因为调试器不会进入“dispatch_async”行。
- 为了实际查看 NSTimer 的工作原理,我什至在“viewDidLoad”方法中 运行 并且它有效。
我做错了什么?
**解决方案:** 正如@Danil Valeev 和@aman.sood 所建议的那样,取消选中 Storyboard 自动布局,将 属性 更改为 'nonatomic';现在从计时器调用选择器:)
检查是否调用了 movePlayerRight: 或 movePlayerLeft:。并且视图中没有使用自动布局(我认为这是原因)。您可以在实用程序第一个选项卡的 xib/storyboard 文件中禁用自动布局。
将 [NSRunLoop mainRunLoop] 替换为 [NSRunLoop currentRunLoop] 它应该可以工作