1

在我的应用程序中,我NSTimer每秒更新一次 UILabel。我之前添加UIBackgroundTaskIdentifierNSTimer让它在后台运行。

__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];
    }); 
}

问题是当我们按下主页按钮应用程序进入后台时,计时器正在运行但uilabel没有更新。例如,_timeLbl显示“45”。现在,如果我按主页按钮,应用程序将进入后台。10 秒后。我单击应用程序图标以在前台获取应用程序,然后我看到“45”一段时间(秒的小数部分),然后显示 35,而不是直接显示 35。这意味着标签没有更新为NSTimer. 有什么办法可以解决这个问题吗?

谢谢 !

4

7 回答 7

1

应用代理

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

[[UIApplication sharedApplication]setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];

}



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

[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{

}];
 }

你的控制器.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. 

谢谢你

于 2016-11-28T11:46:56.733 回答
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];
于 2016-11-28T11:20:37.220 回答
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];
于 2016-11-28T10:34:26.110 回答
0

在您的方法-(void)updateTime中设置标签中的文本后写入[_timeLbl layoutIfNeeded];

例如:

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

layoutIfNeeded 检查视图是否需要更新,并在需要时更新。我一句话就让人眼前一亮。

于 2016-11-28T10:31:38.043 回答
0

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

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

并将其添加到 info.plist

<key>UIBackgroundModes</key>
<array>
    <string>location</string>
</array>
于 2016-11-28T12:04:25.630 回答
0

尝试这个

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

如果您在主队列上更改它,它将得到更新。我很早就面对它并以这种方式排序。

于 2016-11-28T10:18:06.670 回答
0

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

secondsLeft = [[NSDate date] timeIntervalSinceDate:referenceDate]
于 2016-11-28T10:22:26.667 回答