UIBackgroundTaskIdentifier运行NSTimer但不更新UILabel - iOS

时间:2016-11-28 10:13:41

标签: ios objective-c uilabel nstimer uibackgroundtask

在我的应用中,我NSTimer每秒都会更新UILabel。我在UIBackgroundTaskIdentifier之前添加了NSTimer,让它在后台运行。

__block UIBackgroundTaskIdentifier bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
                    [[UIApplication sharedApplication] endBackgroundTask:bgTask];
                    bgTask = UIBackgroundTaskInvalid;
                }];


timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime) userInfo:nil repeats:YES];

[[NSRunLoop mainRunLoop] addTimer:updateTimer forMode:NSRunLoopCommonModes];

。 。

-(void)updateTime
{
    secondsLeft -= 1;
    //NSLog(@"Update time : %d ......",secondsLeft);
    dispatch_async(dispatch_get_main_queue(), ^{
         _timeLbl.text = [NSString stringWithFormat:@"%d",secondsLeft];
    }); 
}

问题是当我们按下主页按钮app进入后台时,计时器正在运行,但uilabel没有更新。例如。说,_timeLbl显示' 45'。现在,如果我按下主页按钮,应用程序将进入后台。 10秒后我点击应用程序图标让应用程序进入前台,在那里我看到' 45' 暂时(小数秒)然后显示35,而不是直接显示35.这意味着标签未使用NSTimer进行更新。有没有解决方法可以解决这个问题?

谢谢!

7 个答案:

答案 0 :(得分:1)

应用代表

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{

[[UIApplication sharedApplication]setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];

}



- (void)applicationWillResignActive:(UIApplication *)application {

[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{

}];
 }

你的CONTROLLER.M

- (void)viewDidLoad {

[super viewDidLoad];
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerTick:) userInfo:nil repeats:YES];

}

-(void) timerTick:(NSTimer *)timer1 {

int seconds = pauseTaskTime % 60;
int minutes = (pauseTaskTime - seconds) / 60;

lblTimer.text = [NSString stringWithFormat:@"%d:%.2d", minutes, seconds]
 }

完成代码后,请执行以下步骤:

1. Go to your project name.

2. Click Capabilities

3. On your Background Modes. 

谢谢

答案 1 :(得分:0)

试试这个

-(void)updateTime {
    secondsLeft -= 1;
    //NSLog(@"Update time : %d ......",secondsLeft);
    dispatch_async(dispatch_get_main_queue(), ^{
        timeLbl.text = [NSString stringWithFormat:@"%d",secondsLeft];
    });
}

如果在主队列中更改它,它将会更新。我很久以前就面对它,并以这种方式排序。

答案 2 :(得分:0)

尝试使用引用日期而不是实例变量secondsLeft更新标签。

secondsLeft = [[NSDate date] timeIntervalSinceDate:referenceDate]

答案 3 :(得分:0)

在设置标签中的文字后,在方法-(void)updateTime中写下[_timeLbl layoutIfNeeded];

E.g:

-(void)updateTime
{
    secondsLeft -= 1;
    //NSLog(@"Update time : %d ......",secondsLeft);
    _timeLbl.text = [NSString stringWithFormat:@"%d",secondsLeft]; 
   [_timeLbl layoutIfNeeded];
}

layoutIfNeeded检查是否需要更新视图,并在需要时进行更新。我用一个词来刷新视图。

答案 4 :(得分:0)

这对我来说很好。

 [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
    countDown = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeLeftSinceDate) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:countDown forMode:NSRunLoopCommonModes];

答案 5 :(得分:0)

使用此代码

[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
loop = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(Update) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:loop forMode:NSRunLoopCommonModes];

答案 6 :(得分:0)

您需要使用CLLocation Manager的api进行后台计时器更新,否则NSTimer允许在后台执行10分钟。

试试这个:https://stackoverflow.com/a/38472381/3901620

并将其添加到info.plist

<key>UIBackgroundModes</key>
<array>
    <string>location</string>
</array>