How to run NSTimer in background and sleep in iOS?

后端 未结 6 624
南笙
南笙 2021-02-04 21:56

I found a lot of post in stackoverflow about NSTimer run in background.

However I didn\'t find any solution.

In my app , I play sound in background

相关标签:
6条回答
  • 2021-02-04 22:29

    I know this post is relatively old but I recently ran into this problem and was having some trouble figuring it out. This is the solution I came up with as of Swift 5. It uses a combination of the RunLoop and Timer classes, with information about them in the provided links below.

    Using timers

    • https://developer.apple.com/documentation/foundation/timer

    Using run loops


    • https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW1

    • https://developer.apple.com/documentation/foundation/runloop

    Sample code:

    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
        }
    }
    
    0 讨论(0)
  • 2021-02-04 22:34

    When you run NSTimer, the @selector method itself will determine wether you want to run in background or main thread.

    Initial set up:

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

    Case you want to run in Background:

    -(void)manageMethod
    {
          dispatch_queue_t queue = dispatch_queue_create("com.mysite.thread1",NULL);
          dispatch_async(queue,^{ 
               //run in background
          });
    }
    
    0 讨论(0)
  • 2021-02-04 22:37

    With 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)
    
    0 讨论(0)
  • 2021-02-04 22:42
    // 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];
    

    This is what do you want?.

    0 讨论(0)
  • 2021-02-04 22:46

    Get Form [This Question] (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
    }
    
    0 讨论(0)
  • 2021-02-04 22:48

    You can’t

    Timers only exist within your application. So (except for a very small window) when your app is sent to the background, timers cannot fire anymore.

    (The audio keeps running, because it’s played by the system, and not by your app.)

    So you cannot use timers for this purpose.

    What you can do — as suggested by iPatel — is use a local notification, instead. This will briefly awake your app, allowing you to stop playing the music.

    0 讨论(0)
提交回复
热议问题