3

我在stackoverflow中发现了很多关于NSTimer后台运行的帖子。

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

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

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

我怎样才能做到这一点?

4

6 回答 6

30
// 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];

这是你想要的吗?

于 2013-10-04T06:33:58.680 回答
3

你不能

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

(音频继续运行,因为它是由系统播放的,而不是由您的应用程序播放的。)

因此,您不能为此目的使用计时器。

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

于 2013-02-27T15:36:21.833 回答
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
}
于 2013-02-26T15:26:02.133 回答
2

使用斯威夫特

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)
于 2016-02-24T11:53:57.297 回答
0

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

使用定时器

使用运行循环</p>

示例代码:

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
    }
}
于 2020-06-23T18:12:49.347 回答
-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
      });
}
于 2013-02-26T15:04:51.293 回答