๊ณต๋ถ€/iOS

[iOS] BackgroundTasks Framework ๊ฐ„๋‹จ ์ •๋ฆฌ

๋ ˆ๋ชฌํ‚ด๐Ÿ‹ 2020. 2. 24. 07:55

๋ชฉ์ฐจ 

  1. BackgroundTasks Framework?
  2. ๋ฌด์—‡์„ ์ง€์›ํ•˜๋Š”๊ฐ€
  3. ์ฃผ์˜ ์‚ฌํ•ญ
  4. ๊ฐ„๋‹จํ•˜๊ฒŒ ์จ๋ณด์ž!
  5. ํ…Œ์ŠคํŠธ ํ•ด๋ณด๊ธฐ
  6. ์ฐธ๊ณ  ๊ธ€๊ณผ ๋” ๋ณด๋ฉด ์ข‹์„ ๊ฒƒ๋“ค

1. BackgroundTasks Framework?

https://developer.apple.com/documentation/backgroundtasks

 

์•ฑ์ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ์‹œ์Šคํ…œ์—๊ฒŒ ์š”์ฒญํ•˜๋Š” ๊ฑธ ๋„์™€์ฃผ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์—์š”.

๊ฐ„๋‹จํ•œ ์„œ๋ฒ„ ํ˜ธ์ถœ > ๋ฆฌํ”„๋ ˆ์‰ฌ ์ž‘์—…๋ถ€ํ„ฐ, ์—๋„ˆ์ง€๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜๊ณ  ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์„ ์š”๊ตฌํ•˜๋Š” ์ž‘์—…๋„ ์š”์ฒญํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•ด์š”.

 

iOS 13๋ถ€ํ„ฐ ์ง€์›. 13 ์ดํ›„์˜ ๋ฒ„์ „์€ ์ด ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค๊ณ  ํ•ด์š”.

setMinimumFetchInterval๋Š” deprecated ๋˜์–ด๋ฒ„๋ ธ๋„ค์š” ๐Ÿฅบ

2. ๋ฌด์—‡์„ ์ง€์›ํ•˜๋Š”๊ฐ€

์•ฑ์ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. 

์ž‘์—…์˜ ๋ณต์žก๋„์™€ ์—๋„ˆ์ง€ ์–‘์— ๋”ฐ๋ผ ๋‘ ๊ฐ€์ง€ ๋ชจ๋“œ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

 

1. App Refresh Task

๊ฐ€๋ฒผ์šด ์ž‘์—…. ๋‹จ์ˆœ API ํ˜ธ์ถœ ๋ฐ ์ €์žฅ. ์‚ฌ์šฉ์ž๊ฐ€ ํฐ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์‹œ๊ฐ„(๋ณดํ†ต ๋‚ฎ)์—๋„ ์‹คํ–‰ํ•ด์ค€๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

2. Processing Task

DB๋“ฑ ํฌ๊ณ  ๋ฌด๊ฑฐ์šด ์ž‘์—… ํ•  ๋•Œ ์‚ฌ์šฉ. ์˜ต์…˜ ์ค‘ ์ถ”๊ฐ€ ๋ฐฐํ„ฐ๋ฆฌ๋ฅผ  ์‚ฌ์šฉํ•˜๋Š”๊ฐ€, ๋„คํŠธ์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฐ€ ๋“ฑ์˜ ์š”์†Œ๋„ ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌด๊ฑฐ์šด ์ž‘์—…์ด๊ธฐ ๋–„๋ฌธ์—, ๋ณดํ†ต ์•ฑ์ด ์ถฉ์ „ ์ค‘์ด๊ณ , idle ํ•  ๋•Œ (์•” ๊ฒƒ๋„ ์•ˆ ํ•˜๊ณ  ๋†€๊ณ  ์žˆ์„ ๋•Œ) ์‹คํ–‰์‹œ์ผœ ์ค€๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

3. ์ฃผ์˜ ์‚ฌํ•ญ

- ์ผ์ •ํ•œ ์‹œ๊ฐ„์— ํ˜ธ์ถœ๋˜์ง€ ์•Š์Œ (์‹œ์Šคํ…œ์—์„œ ํŒ๋‹จํ–ˆ์„ ๋•Œ ๋ฐฐํ„ฐ๋ฆฌ, ๋ฉ”๋ชจ๋ฆฌ ์ƒํ™ฉ์ด ๊ดœ์ฐฎ์„ ๋•Œ, ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ์ด ์•ฑ์„ ์–ธ์ œ ๋ณดํ†ต ์ผœ๋Š”์ง€ ํ•™์Šตํ•ด ๊ทธ ์ „์— ํ˜ธ์ถœํ•จ = ์•Œ ์ˆ˜ ์—†์Œ)

- ์‚ฌ์šฉ์ž๊ฐ€ ์ผ์ฃผ์ผ ๋™์•ˆ ์•ฑ์„ ์ผœ์ง€ ์•Š์œผ๋ฉด ๋” ์ด์ƒ Background Fetch๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์Œ.

- UI ์กฐ์ž‘ ๋…ธ๋…ธ! ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ์„œ ํฌ๋ž˜์‹œ ๋‚จ. (๋„คํŠธ์›Œํฌ ์ธ๋””์ผ€์ดํ„ฐ๋„ ์•ˆ๋จ... ์–ด๋–ป๊ฒŒ ์•„๋ƒ๊ณ ์—ฌ? ์ €๋„ ์•Œ๊ณ  ์‹ถ์ง€ ์•Š์•˜์–ด์š”..)

์ด๋Ÿฐ ์ด๋ฆ„์˜ ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค :)

4. ๊ตฌํ˜„ํ•ด๋ณด์ž!

์• ํ”Œ ์˜ˆ์ œ๊ฐ€ ์ž˜ ๋˜์–ด ์žˆ์–ด์„œ ์ฝ”๋“œ์™€ ์˜ˆ์ œ๋Š” ๊ทธ๋Œ€๋กœ ๋“ค๊ณ  ์™”์Šต๋‹ˆ๋‹ค. 

 

1. ์•ฑ์—๊ฒŒ Background Fetch, Background Processing ๊ถŒํ•œ์„ ์ค๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler

 

2. Info.plist์— BGTaskSchedulerPermittedIdentifiers๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜์— ๋ณด์ด๋Š” Permitted background task scheduler Identifiers ์ž…๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด ๋ฐฐ์—ด๋กœ, ๊ฐ ์š”์†Œ์— ์‹คํ–‰ํ•  task์˜ Identifier๋ฅผ ์ž…๋ ฅํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. 

 

์ถœ์ฒ˜ : https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler

 

3. ์œ„์— ์„ ์–ธํ•œ task์˜ Identifier๋กœ task๋ฅผ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์ œ์—์„œ์˜ ์‹œ์ ์€ didFinishLaunchingWithOptions๋„ค์š”. 

 

  //AppDelegate
  
  //์•ฑ ๋Ÿฐ์นญ
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
       
       //์˜ˆ์ œ ์„œ๋ฒ„์—์„œ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๊ฐ–๊ณ ์˜ค๊ณ  ํ•˜๋Š” ๋ถ€๋ถ„. ์ƒ๋žตํ•จ.
        
        // ์—ฌ๊ธฐ์„œ๋Š” ํƒœ์Šคํฌ๋ฅผ ๋“ฑ๋กํ•ด์ค๋‹ˆ๋‹ค. ์Šค์ผ€์ค„ํ•˜๋Š” ๊ฑด ๋ณ„๋„ ์—์š”!
        BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.apple-samplecode.ColorFeed.refresh", using: nil) { task in
    
            //์‹ค์ œ๋กœ ์ˆ˜ํ–‰ํ•  ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๋™์ž‘ ๊ตฌํ˜„
            //๋‚˜์ค‘์— ์Šค์ผ€์ฅด ํ•  ๋•Œ, ํ•ด๋‹น ํƒœ์Šคํฌ์˜ ํด๋ž˜์Šค๋ฅผ ์•Œ๊ณ  ๋“ฑ๋ก์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋‹ค์šด ์บ์ŠคํŒ…์ด ๊ฐ€๋Šฅํ•ด์š”.
            self.handleAppRefresh(task: task as! BGAppRefreshTask)
        }
    
        BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.apple-samplecode.ColorFeed.db_cleaning", using: nil) { task in
            
            // Downcast the parameter to a processing task as this identifier is used for a processing request.
            self.handleDatabaseCleaning(task: task as! BGProcessingTask)
        }

        return true
    }
   
   
   //์‹ค์ œ๋กœ ํƒœ์Šคํฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ณณ์—์„œ๋Š” ๋‘ ๊ฐ€์ง€๋ฅผ ์‹ ๊ฒฝ์จ ์ฃผ์„ธ์š”.
   // task.expirationHandler ๊ตฌํ˜„
   // ์ž‘์—…์˜ ๊ฒฐ๊ณผ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋˜์—ˆ๋“ , task.setTaskCompleted(success: ์ž‘์—… ์„ฑ๊ณต ์—ฌ๋ถ€) ํ˜ธ์ถœํ•˜๊ธฐ.
   func handleAppRefresh(task: BGAppRefreshTask) {

		//๋‹ค์Œ ๋™์ž‘์„ ๋˜ ์Šค์ผ€์ฅด ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ณต ์ˆ˜ํ–‰ ์‹œ ํ•„์š”ํ•˜๊ฒ ์ฃ ?
        //์Šค์ผ€์ฅด ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋Š” ์ด ์ฝ”๋“œ ๋ธ”๋Ÿญ ์ดํ›„์— ๋‚˜์˜ต๋‹ˆ๋‹ค!
		scheduleAppRefresh()
        
        let queue = OperationQueue()
        queue.maxConcurrentOperationCount = 1
        
        let context = PersistentContainer.shared.newBackgroundContext()
        let operations = Operations.getOperationsToFetchLatestEntries(using: context, server: server)
        let lastOperation = operations.last!
        
        
        //๋•Œ์— ๋”ฐ๋ผ์„œ๋Š” ๋„ˆ๋ฌด ์˜ค๋ž˜๊ฑธ๋ฆฐ๋‹ค๋˜๊ฐ€ ํ•ด์„œ ์ข…๋ฃŒ๋  ๋•Œ๊ฐ€ ์žˆ์ฃ . ๊ทธ ๋•Œ๋ฅผ ์œ„ํ•œ ์ •๋ฆฌ ํ•ธ๋“ค๋Ÿฌ์—์š”.
        task.expirationHandler = {
        
        	//์˜ˆ์ œ์—์„œ๋Š” OperationQueue๋ฅผ ์‚ฌ์šฉํ•˜๋‹ˆ๊นŒ, ๋ชจ๋“  ๋™์ž‘์„ ์ทจ์†Œํ–ˆ๋„ค์š”.
            queue.cancelAllOperations()
        }

		//์ด ๋ถ€๋ถ„์€ Alamofire์˜ api ressponse ์ฒ˜๋ฆฌ ๋ธ”๋ก ๋“ฑ์ด ๋  ์ˆ˜ ์žˆ๊ฒ ์ฃ ? ์˜ˆ์ œ์—์„œ๋Š” Operation Queue๋ฅผ ์‚ฌ์šฉํ–ˆ๋„ค์š”.
        lastOperation.completionBlock = {
        
        //์ž‘์—… ์™„๋ฃŒ ์‹œ, setTaskCompleted๋ฅผ ๋ฐ˜๋“œ์‹œ ํ˜ธ์ถœํ•ด์ฃผ์„ธ์š”. ๋™๊ธฐ๋กœ ํ˜ธ์ถœ๋  ํ•„์š”๋Š” ์—†์–ด์š”!
            task.setTaskCompleted(success: !lastOperation.isCancelled)
        }

        queue.addOperations(operations, waitUntilFinished: false)
    }
    


//BGProcessingTask์—์„œ ์ˆ˜ํ–‰ํ•  ๊ฒƒ์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ์œ„์™€ ๋˜‘๊ฐ™์•„์š”!

    func handleDatabaseCleaning(task: BGProcessingTask) {
        let queue = OperationQueue()
        queue.maxConcurrentOperationCount = 1

        let context = PersistentContainer.shared.newBackgroundContext()
        let predicate = NSPredicate(format: "timestamp < %@", NSDate(timeIntervalSinceNow: -24 * 60 * 60))
        let cleanDatabaseOperation = DeleteFeedEntriesOperation(context: context, predicate: predicate)
        
        task.expirationHandler = {
            // After all operations are cancelled, the completion block below is called to set the task to complete.
            queue.cancelAllOperations()
        }

        cleanDatabaseOperation.completionBlock = {
            let success = !cleanDatabaseOperation.isCancelled
            if success {
                // Update the last clean date to the current time.
                PersistentContainer.shared.lastCleaned = Date()
            }
            
            task.setTaskCompleted(success: success)
        }
        
        queue.addOperation(cleanDatabaseOperation)
    }

 

4. ํƒœ์Šคํฌ๋ฅผ ๋“ฑ๋กํ–ˆ์œผ๋ฉด, ์Šค์ผ€์ฅด ํ•˜์ž!

์•ฑ์—์„œ์˜ ์‹œ์ ์€ AppDelegate์˜ applicationDidEnterBackground, ํ˜น์€ ์œ„์˜ ํƒœ์Šคํฌ์˜ ๊ตฌํ˜„ ๋‚ด๋ถ€๋„ค์š”. 

ํ›„์ž์˜ ๊ฒฝ์šฐ๋Š” ๋ฐ˜๋ณต ์ˆ˜ํ–‰์„ ์œ„ํ•ด ๋“ค์–ด๊ฐ€๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. (๋ฌผ๋ก  ์ฃผ๊ธฐ๋Š” ์‹œ์Šคํ…œ์ด ๋ง˜๋Œ€๋ฃจ..)

 

์ด๋•Œ, submit์€ synchronousํ•œ ๋ฉ”์†Œ๋“œ์ด๋ฏ€๋กœ, launch ์‹œ์ ์—์„œ submit์„ ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ๋‹ค๋ฅธ concurrent queue์—์„œ ๋“ฑ๋ก ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๊ธธ ๊ถŒ์žฅํ•œ๋‹ค๊ณ  ํ•˜๋„ค์š”!

 

    //AppDelegate
    
    //์•ฑ์ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ์— ๋“ค์–ด๊ฐ”์„ ๋•Œ ํ˜ธ์ถœ ๋จ.
    func applicationDidEnterBackground(_ application: UIApplication) 
    {
        scheduleAppRefresh()
        scheduleDatabaseCleaningIfNeeded()
    }
    

	// ์‹ค์ œ๋กœ ํƒœ์Šคํฌ๋ฅผ ์Šค์ผ€์ค„ ํ•˜๋Š” ๋ถ€๋ถ„.
    
    //BGAppRefreshTaskRequest๋ฅผ ๋งŒ๋“ค์–ด ๋ด…๋‹ˆ๋‹ค
    func scheduleAppRefresh() {
    
  		  //1. ์›ํ•˜๋Š” ํ˜•ํƒœ์˜ TaskRequest๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ด ๋•Œ, ์‚ฌ์šฉ๋˜๋Š” identifier๋Š” ์œ„์˜ 1, 2๊ณผ์ •์—์„œ ๋“ฑ๋กํ•œ info.plist์˜ identifier์—ฌ์•ผ ํ•ด์š”!
        let request = BGAppRefreshTaskRequest(identifier: "com.example.apple-samplecode.ColorFeed.refresh")
        
        //2. ๋ฆฌํ€˜์ŠคํŠธ๊ฐ€ ์–ธ์ œ ์‹คํ–‰๋˜๋ฉด ์ข‹๊ฒ ๋Š”์ง€ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด์˜ setMinimumFetchInterval๊ณผ ๋™์ผํ•˜๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 
        //์—ฌ์ „ํžˆ, ์–ธ์ œ ์‹คํ–‰๋ ์ง€๋Š” ์‹œ์Šคํ…œ์˜ ๋งˆ์Œ์ž…๋‹ˆ๋‹ค...
        request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60)
        
        
        //3. ์‹ค์ œ๋กœ task๋ฅผ submit ํ•ฉ๋‹ˆ๋‹ค.
        //์ด ๋•Œ ์ฃผ์˜์‚ฌํ•ญ์€, submit์€ synchronousํ•œ ํ•จ์ˆ˜๋ผ, launching ๋•Œ ์‹คํ–‰ํ•˜๋ฉด ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ธ”๋ฝ ๋  ์ˆ˜ ์žˆ์œผ๋‹ˆ 
        //OperationQueue, GCD๋“ฑ์„ ์ด์šฉํ•ด ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค๊ณ  ํ•˜๋„ค์š”.
        do {
            try BGTaskScheduler.shared.submit(request)
        } catch {
            print("Could not schedule app refresh: \(error)")
        }
    }
    
    
    //BGProcessingTaskRequest๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ต์…˜์ด ์žˆ๋Š” ๊ฑธ ์ œ์™ธํ•˜๋ฉด ์œ„์™€ ๋™์ผํ•ด์š”.
    func scheduleDatabaseCleaningIfNeeded() {
        let lastCleanDate = PersistentContainer.shared.lastCleaned ?? .distantPast

        let now = Date()
        let oneWeek = TimeInterval(7 * 24 * 60 * 60)

        // Clean the database at most once per week.
        guard now > (lastCleanDate + oneWeek) else { return }
        
        
        //์ด๋ฒˆ์—” ๋ฌด๊ฑฐ์šด DB ์ž‘์—…์ด๋‹ˆ๊นŒ, BGProcessingTaskRequest๋ฅผ ์Šค์ผ€์ฅด ํ•ด์ค๋‹ˆ๋‹ค.
        let request = BGProcessingTaskRequest(identifier: "com.example.apple-samplecode.ColorFeed.db_cleaning")
        
        //๋„คํŠธ์›Œํฌ ์‚ฌ์šฉ์—ฌ๋ถ€, ์—๋„ˆ์ง€ ์†Œ๋ชจ๋Ÿ‰ ์˜ต์…˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
        request.requiresNetworkConnectivity = false
        request.requiresExternalPower = true
        
        do {
            try BGTaskScheduler.shared.submit(request)
        } catch {
            print("Could not schedule database cleaning: \(error)")
        }
    }

 

5. ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํƒœ์Šคํฌ ์‹คํ–‰ ํ…Œ์ŠคํŠธ ํ•ด๋ณด๊ธฐ

๊ธฐ์กด์˜ Simulate Background Fetch๋กœ๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค ใ… ใ… ใ…  ์•„๋ž˜ ์ฒ˜๋Ÿผ, ์ง์ ‘ ์ฝ˜์†”์— ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•ด์ค˜์•ผ ํ•ด์š”.

 

2020/02/24 - [๊ฐœ๋ฐœ ์‚ฝ์งˆ๊ธฐ/iOS] - [iOS]BackgroundTasks ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, task ์‹คํ–‰, ์ค‘๋‹จ ํ…Œ์ŠคํŠธํ•˜๊ธฐ.

 

1. BGTaskScheduler์—๊ฒŒ task๋ฅผ submitํ•˜๋Š” ์ฝ”๋“œ ์‹คํ–‰.

2. ๊ทธ ๋‹ค์Œ ์‹œ์ ์— break point ์žก๊ธฐ

3. break ํฌ์ธํŠธ๊ฐ€ ๊ฑธ๋ฆฌ๋ฉด ์•„๋ž˜ ๋ช…๋ น์–ด ์ž…๋ ฅํ•˜๊ธฐ.

4. ๋ฐฑ ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰์‹œ (์œ„ ๊ฐ™์ด didEnterBackground ์‹œ์ ) ์•„๋ž˜ ๋ช…๋ น์–ด ์ž…๋ ฅ ํ›„, ๋‹ค์‹œ ์•ฑ์„ foreground์—์„œ ์‹คํ–‰์‹œ์ผœ ์ฃผ์–ด์•ผ ์ œ๋Œ€๋กœ ๋ช…๋ น์–ด๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

 

๋ฐ˜๋“œ์‹œ ์‹ค ๊ธฐ๊ธฐ์—์„œ ์‹คํ–‰์‹œ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋””๋ฒ„๊ทธ ์šฉ๋„๋กœ๋งŒ ์‚ฌ์šฉํ•ด๋‹ฌ๋ผ๊ณ  ๊ฒฝ๊ณ ๊ฐ€ ์žˆ๋„ค์š”.

 

e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"Info.plist์— ๋“ฑ๋กํ•œ ํƒœ์Šคํฌ Identifier"]

 

์œ„ ๋ช…๋ น์–ด๊ฐ€ ์ œ๋Œ€๋กœ ์‹คํ–‰๋˜๋ฉด ์ฝ˜์†”์— ์•„๋ž˜ ๋ฌธ๊ตฌ๊ฐ€ ์ถœ๋ ฅ๋˜๊ณ , ํƒœ์Šคํฌ ๋‚ด์—์„œ์˜ BP๋„ ์žกํž™๋‹ˆ๋‹ค.

 

Simulating launch for task with identifier ์•„๊นŒ ์‹คํ–‰ ์‹œํ‚จ ํƒœ์ŠคํŠธ Identifier

Starting simulated task: <BGAppRefreshTask: ์•„๊นŒ ์‹คํ–‰ ์‹œํ‚จ ํƒœ์ŠคํŠธ Identifier>

 

๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์  ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

 

์š”๋Ÿฐ ์ด๋ฆ„์˜ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

6. ์ฐธ๊ณ  ์ž๋ฃŒ์™€ ๋” ๋ณด๋ฉด ์ข‹์„ ๊ฒƒ๋“ค

์‚ฌ์šฉ ์˜ˆ์ œ๊ฐ€ ์ž˜ ๋“œ๋Ÿฌ๋‚œ ๊ธ€

https://medium.com/snowdog-labs/managing-background-tasks-with-new-task-scheduler-in-ios-13-aaabdac0d95b

 

WWDC 2019 ์˜ Background Execution ์˜์ƒ

https://developer.apple.com/videos/play/wwdc2019/707/

์ƒ˜ํ”Œ ํ”„๋กœ์ ํŠธ๋Š” ๋ฐ˜๋“œ์‹œ ์‹ค ๊ธฐ๊ธฐ์—์„œ ๋Œ์•„๊ฐ€์•ผ ํ•œ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค!

 

์• ํ”Œ ๋ฌธ์„œ

Background Tasks Framework ์„ค๋ช…

https://developer.apple.com/documentation/backgroundtasks

 

Background Task ํ…Œ์ŠคํŠธ ํ•˜๊ธฐ

https://developer.apple.com/documentation/backgroundtasks/starting_and_terminating_tasks_during_development

 

+ ๋จผ์ € ๊ณต๋ถ€ํ•˜๋ฉด ์ข‹์„ ๊ฒƒ

OperationQueue. task๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฐœ๋… ๋“ฑ์€ Operation Queue์—์„œ ์˜จ ๊ฒƒ์ด ๋งŽ์•„ ๋ณด์ž…๋‹ˆ๋‹ค. ์ €๋„ ์ด ๋ถ€๋ถ„ ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ ์• ๋จน์–ด์„œ... ๊ณต๋ถ€๋ฅผ ์ข€ ๋” ํ•ด์•ผ๊ฒ ๋„ค์š”!

 

+ ์‚ฌ๋‹ด

์˜ˆ์ œ ์ฝ”๋“œ์—์„œ ๋ชฉ ์„œ๋ฒ„๋ฅผ ๋งŒ๋“  ๋ฐฉ์‹์ด ๊ฝค๋‚˜ ๋งˆ์Œ์— ๋“ค์–ด์š”. ๋‚˜์ค‘์— ํ…Œ์ŠคํŠธ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค ๋–„ ํ•œ ๋ฒˆ ๋”ฐ๋ผํ•ด๋ณผ๊นŒ ํ•ฉ๋‹ˆ๋‹ค.