【问题标题】:UIBackgroundTaskIdentifier running NSTimer but not updating UILabel - iOSUIBackgroundTaskIdentifier 运行 NSTimer 但不更新 UILabel - iOS
【发布时间】:2016-11-28 10:13:41
【问题描述】:

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

__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。有什么办法可以解决这个问题吗?

谢谢!

【问题讨论】:

  • 更新主队列中标签的文本
  • 如果你的意思是 dispatch_async(dispatch_get_main_queue(), ^{ ...... }); .......试过了,但没有运气
  • 试试this
  • @Nikhil 我已经检查过了,但没有全部了解。您能否提供解决方案作为此链接和我的问题的参考?

标签: ios objective-c uilabel nstimer uibackgroundtask


【解决方案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. 

谢谢

【讨论】:

    【解决方案2】:

    试试这个

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

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

    【讨论】:

    • 试试这个stackoverflow.com/questions/16261620/… 我在你的代码中看不到后台任务和更新方法之间的任何链接,所以它没有更新。您有 2 个选项: 1. 将您的代码更新为上述一个。或者 2. 使用 didEnterForeground 方法再次更新标签。
    • 感谢@Pushkraj,但我在发布我的问题之前访问了此链接并做了同样的事情。
    【解决方案3】:

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

    secondsLeft = [[NSDate date] timeIntervalSinceDate:referenceDate]
    

    【讨论】:

    • 1.我不能这样做,因为它用于客观测试并从数据库中检索 secondsLeft。 .......... 2. 这如何解决问题?
    • 据我所知,在后台更新 UI 是不可能的,我建议您在应用程序进入前台时显示一个次要加载器,直到 UI 得到更新。
    【解决方案4】:

    这对我来说很好。

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

    【讨论】:

    • 问题的代码包含 bgTask 并导致此问题。
    【解决方案5】:

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

    例如:

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

    layoutIfNeeded 检查视图是否需要更新,并在需要时更新。我一个字就刷新了视野。

    【讨论】:

    • 好的,我到家时必须检查一下,如果我有解决方案会告诉你
    【解决方案6】:

    使用此代码

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

    【讨论】:

      【解决方案7】:

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

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

      并将其添加到 info.plist 中

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-15
        • 1970-01-01
        相关资源
        最近更新 更多