如何在后台运行NSTimer并在iOS中睡觉?

时间:2013-02-26 14:47:48

标签: ios cocoa-touch nstimer

我在stackoverflow中发现了大量关于NSTimer在后​​台运行的帖子。

但是我没有找到任何解决方案。

在我的应用程序中,我在后台播放声音,并设置计时器以在达到该时间时停止音乐。

所以我需要运行我的NSTimer背景(意味着当主页按钮点击并睡眠iPhone时)。

我该怎么做?

6 个答案:

答案 0 :(得分:29)

// NSTimer run when app in background <br>

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

这就是你想要的?。

答案 1 :(得分:3)

你不能

计时器仅存在于您的应用程序中。所以(除了一个非常小的窗口)当你的应用程序被发送到后台时,计时器就不能再发射了。

(音频一直在运行,因为它由系统播放,而不是由您的应用播放。)

所以你不能为此目的使用计时器。

您可以做的事情 - 正如iPatel建议的那样 - 使用本地通知。这将暂时唤醒您的应用,让您停止播放音乐。

答案 2 :(得分:2)

获取表格[本课题](http://iphonedevsdk.com/forum/iphone-sdk-development/58643-keep-nstimer-running-when-app-is-in-background-multitasking.html

- (void)btnSetupNotificationClicked:(id)sender
{
    UILocalNotification* pOrderCompletedNotification=[[UILocalNotification alloc] init];
    if(pOrderCompletedNotification!=nil)
    {
        [pOrderCompletedNotification setFireDate:[[NSDate alloc] initWithTimeIntervalSinceNow:5.00]];
//      [pOrderCompletedNotification setApplicationIconBadgeNumber:1];
        [pOrderCompletedNotification setTimeZone:[NSTimeZone systemTimeZone]];
        [pOrderCompletedNotification setSoundName:@\"OrderCompleted.m4a\"];
        [pOrderCompletedNotification setAlertBody:@\"Order Completed\"];
        [pOrderCompletedNotification setAlertAction:nil];
        [pOrderCompletedNotification setHasAction:NO];

        UIApplication* pApplication=[UIApplication sharedApplication];
        if(pApplication!=nil)
        {
            [pApplication scheduleLocalNotification:pOrderCompletedNotification];
        }
        else
        {
            NSLog(@\"Application singleton allocation error.\");
        }

        [pOrderCompletedNotification release];
        [pApplication release];
    }
    else
    {
        NSLog(@\"Local notification creation error.\");
    }   // if
}

答案 3 :(得分:2)

使用Swift

let app = UIApplication.sharedApplication()
app.beginBackgroundTaskWithExpirationHandler(nil)
let timer = NSTimer.scheduledTimerWithTimeInterval(1,
            target: self,
            selector:"DoSomethingFunctions",
            userInfo: nil,
            repeats: true)
NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)

答案 4 :(得分:0)

我知道这篇文章比较老,但是最近我遇到了这个问题,在弄清楚这个问题时遇到了一些麻烦。这是我从Swift 5开始提出的解决方案。它结合了RunLoop和Timer类,并在下面的链接中提供了有关它们的信息。

使用计时器

使用运行循环

示例代码:

class AMSleepTimerUtil: NSObject {
    static let shared = AMSleepTimerUtil()
    fileprivate var sleepTimer: Timer?
    
    /// Initialize the timer to trigger a function to execute after a duration of time
    /// - Parameter seconds: the time delay until the selector function executes
    /// - Returns: true if sleep timer were successfully initialized
    func createTimerToStopMusic(at seconds: TimeInterval) -> Bool {
        let fireAtDate = Date(timeIntervalSinceNow: seconds)
        stopSleepTimer()
        
        self.sleepTimer = Timer(fireAt: fireAtDate,
                                interval: 0,
                                target: self,
                                selector: #selector(pauseMusic),
                                userInfo: nil,
                                repeats: false)
        guard let sleepTimer = sleepTimer else { return false }
        RunLoop.main.add(sleepTimer, forMode: .common)
        
        return true
    }
    
    func pauseMusic() {
        guard let audioPlayer = AMNowPlayingViewController.sharedInstance()?.audioPlayer else { return }
        
        audioPlayer.pause()
    }
    
    /// Used to reset the sleep timer before initializing a new timer if the user clicks the "Set Timer" multiple times
    func stopSleepTimer() {
        if sleepTimer != nil {
            sleepTimer?.invalidate()
            sleepTimer = nil
        }
    }
    
    func sleepTimerIsActive() -> Bool {
        return self.sleepTimer != nil
    }
}

答案 5 :(得分:-2)

当您运行NSTimer时,@selector方法本身将确定您想要在后台或主线程中运行。

初始设置:

self.scanTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(manageMethod) userInfo:nil repeats:YES]; //@property (nonatomic, strong) NSTimer *scanTimer

您希望在后台运行的案例:

-(void)manageMethod
{
      dispatch_queue_t queue = dispatch_queue_create("com.mysite.thread1",NULL);
      dispatch_async(queue,^{ 
           //run in background
      });
}