본문 바로가기
WWDC

WWDC 19 - Advance in App Background Execution

by vapor3965 2021. 6. 26.

목차

     


    • 세션보면서 정리한 내용입니다. 해석이 잘못된 경우가 있을수있으니 발견하시면 댓글로 남겨주시면 감사하겠습니다🙏🏻

     

     

     

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

     

    Advances in App Background Execution - WWDC19 - Videos - Apple Developer

    Background execution is a powerful tool your app can leverage to provide a great user experience. Learn about best practices to follow...

    developer.apple.com

     

     


     

     

    관련내용

    • 백그라운드실행을배워보자
    • 새로운 백그라운드 스케쥴링API를 배워보자

     

    application(_:performFetchWithCompletionHandler:)
    은 iOS 13 부터 depracted 되었고, 대신 BGAppRefreshTask를 사용하라고한다!

     

    요약

    • 메세지를 보내는것은, 바로정확하게 보내져야하낟. 그ㅓ므로, 앱을나가도, 백그라운드에서 실행이되도록해야한다.
      • UIApplication.beginBackgroundTask 를 이용한다.
    • 👍background refresh fetch는 새롭게 BackgroundTask 프레임워크가 등장했다. 이를이용하여 간단하게 백그라운드에서 하도록하고, 테스팅할수있게됐다. - backgroundRefreshTask를 이용한다.
    • 급박한상황이아니면서 좀 걸리는작업은 backgroundProcessTask를 이용한다.

     

    ⬇️ 백그라운드 테스트코드 

    e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.dust.refresh"]

     

     

     


     

     

     

    Background Excecution

    • backgorund에서실행되지만, 사용자에게 보이지않는것.
    • 앱의요청이나, 헬스케어, 위치등을 백그라운드에서 하기위해.
    • 이러한 background Execution을 하기위해서는Power, performance, Privacy 를 매우 신중하게고려되어진다.

    아래의 사용종류는 각 background mode 별로 나뉘어질수있다.


    4개의기능이 포함된 Messaging App에 어떤 API 를 사용해야할까?


     

    Sending message
    background task

    • 는 즉각적이여야하고,
    • 보냈으면 확실히보냈어야한다. 보내자마자 앱을나가도, 보내져야한다. 즉 completion은 보호받아야한다.
    • 그러므로 background task 를 이용해야한다.

    Sample code

    • operation만들고,
    • beginBacgroundTask - background에서 시작하고
      • identifier에 넣음으로써, background에실행되도록해지는건가…….
      • 실제로 operation을 실행하는건 마지막줄의 queue이니까…
      • 네트워크가혼잡하여 시간이충분치않으면 백그라운드여도 실패할수있다. 그러므로 실패할경우를 알려야한다
    • compeltionblock에 task가완료될경우를 써넣는다. - endBackgroundtask()

    요약

    • Background Task completion을통해 protect한다.
    • 백그라운드에 들어가서 보내지는것이아닌, 바로 유저가 클릭하면 보내지도록해야한다.

     

     

    Phone Calls

    • VoIP push notifications
      • 특별한 push 타입으로, 앱을 런칭하게해주고, 사용자는 전화가온것을 앱에서볼수있게된다.


    아래를하지않으면, 앱은 꺼질것이다?

     



    Muted Threads

    Background push

    • 알리지않고 push를 보내 앱을 실행하게해준다.
      • 실행되는시간은 시스템이 지능적으로결정한다.


    가장 중요한게, 이게 되기위해서는 5로설정하고, background로 설정해야한다.

    • 만약 watchos에서 궁금하다면 Creating Independent watch Apps wwdc 2019를 봐라.

     

     

    Download past attachment

    • 이미계정이있지만, 새로운디바이스에서접속하라경우, 이전의데이터들을 보고싶다.
      • 이를 포그라운드에서 다운받도록하지않고, 나중에 미루어서 다운받도록한다.

    Discretionary Background URL Session
    (자유재량)

    • 이는 다운로드를 더나은시간떄까지 미루도록해준다.
    • 또한 이때 개발자가 더많은정보를 줄수도있어서, 시스템이 더 효과적으로 스케쥴링할수있또록해준다.

    • 추가적인정보들 ⬇️

     

     


    Syncing
    Database cleanup
    Backups

     

    위의 3가지들은 미뤄질수있는 작업들이다.

    포그라운드user activity에영향을 안미치기 위해 백그라운드에서하면 좋겠따.

     

    그래서, 만약 이 작업들을 아마, 충전할때나 아니면 필요없는시간에 하면어떨까??

     

    고것이 바로, 새로운 background mode, framework인 BackgroundTasks이다!

     

    Background Tasks

    • 새로운 background mode뿐만아니라, background app refresh API를 refine했다.

    Background processing Tasks

    • CPU모니터는 앱이 너무과도하게 cpu를사용하면 종료시키도록하는데, 만약 플러그인되있다면 이 cpu모니터를끄게할수도있다.

     

     

    Background App Refresh Task

    • ⬇️아래는 deprecated되었다.

     

    BGTaskCheduler

    • 배터리, 네트워크, 앱사용시간 등등 모니터링하는 인터페이스다.

    사용방법

    • 앱포그라운드일떄 백그라운드할 작업을 BG Task reuqest 객체를 만든다.
    • 예를들어, background app refresh 작업을 하고싶다면, BG App Refresh Task Reuqest를 생성한다.
    • 그리고 BGTaskScheduler에 제출한다.

    • 또한, database cleanup 같은 경우, BG Processing Task Request를 만들어 똑같이 제출할수있따!
    • 또한, 키보드extension에서 사용자의 키보드습관을 learning하려고한다면, BGProcessing Task Requqest 를 만들어서 또 제출할수있다.

    즉 아래와같이 여러개의 task를 요청할수있따.


    그리고, 스케쥴러는 하나씩 task를 앱을깨워 백그라운드에서 실행하고, 앱에게 task완료결과를 전달한다. 그럼 update UI, contentg한다.


    그리고 완료되면 set task compelted 를 호출하고, 앱은 suspend된다.


    또한, BGTask 를 어떻게 설정했는지에따라, 각 task들이 동시에실행될수도있다.
    그러므로, 동시에 결과가 발생할수있으며, concurrently하게 handle할 준비가되어야한다.

     

     



    👍예제 - Background app refresh

    • 항상 최신상태가 되고싶다! -> okay, background app refresh 가 필요하다.
    • 우선, target - ccapabilities - background mode - background fetchㄹㄹ 클릭한다.

    • 그리고, Info.plist 에 추가한다.
      • Permitted background task scheduler identifiers
      • string 배열인데, 이는 앱에서 사용할 sepcific task를 유니크하게 지정하며, 유니크해야한다.
      • thrid-party 프레임워크와의 충돌을 피하기위해 DNS 표기법의 역순를 사용하는걸 추천한다.

    • 그다음에 코드를 구현해야한다.

    App Delegate 로 가서, import 한다

    • 할일은, launched됐을떄, 무엇을행할지를 시스템에게말한다
    • launching이 finish되기전에 launch handler를 등록한다.
    • didFinishLaunchingWithoption매서드안에 BGTaskScheduler등록한다 info.plist에 작성한 identifier와함께.

    • 그다음파라미터는 내핸들러가 어디에서실행될지를 정하는 큐다. 다른것과 동기화하고싶다면 특정큐를 선언할수있다.
    • nil로선엉ㄴ하면 시스템은 백그라운드serial queue를 만들어준다.
    • 그다음파라미터는 실제로 호출될것을 작성한다.

    • 보다시피, 하나의파라미터 - BGTask이다.
    • 그 파라미터를 BGAppRefreshTask로 다운캐스팅한다.

    • 그리고 마저 handleAppRefresh메서드를작성해준다.
      • 서버에서데ㅔ이터를 가져오고,
      • 내데이터베이스를 업데이트하고,
      • UI를 업데이트한다.

    • 여기서더 2가지가 남아있다.
    • 👍1. handle expiration
      • task들은 제한된시간을 받게되는데, 거의다 시간이됐을때, 경골르해준다. 더빨리끝내기위한 기회를 주도록.
      • 또는, 시스템은 task를 실행하기위해 더이상충분하지않아, task를 종료할수도있다.
    • 그러므로, task의 expirationahandler를 추가한다. 이때다 취소하도록한다.

    • 👍2. call set task completed
      • task가 완료마쳤을때.
      • expirationHandler가호출되도 이를 호출해야한다.
    • 그러므로, task의 completionBlock이 호출됐을때, setTaskCompleted 를 호출한다.
      • 🔥음, 그러니까따로, API에 compeltionBlock 클로저를 만들었네…?
      • 🔥API구현할때 온료되면 completionBlock() 을호출하도록했나보다.


    • 마지막단계가남았는데, 실제로 이 BG Task를 스케쥴하는것.
    • applicationDidEnterBackground 메소드안에서, 실제로 BGTaskReuqest를 만들고, BGTaskScheduler에 submit하는 메서드를 호출한다.

    • BGTaskRequest에👍 earliestBeginDate를 지정할 수 있다.
      • 이시간전까지는 실행하지않도록한다.

    • 🔥그리고 가장중요한것으로! 지금까지그대로하면, 백그라운드에 진입하고, task를 실행하고, 완료된다. 그러면, 사용자가 포그라운에 진입하기전까지 다시는 Launchede되지않는다.
    • 이렇게되면 항상 최신의데이터를 받지못하는 상황이된다.
    • 그러므로, 백그라운드에 진입하여 task를 실행할때 다시 scheduleAppRefresh()를 호출하도록한다!!!!
    • 그러면, 계속해서 사용자가 포그라운드진입하기전까지 계속 주기마다 백그라운드에서 실행하게된다!!!

     

     

     

     

    예제코드 BGProcessing Tasks

    • database cleaning, ..


    마찬가지로 추가한다.


    그리고 똑같이 register 한다.

    • BGPrcessingTask로 다운캐스팅한다.

    마찬가지로, Database API를 작성한다.

    • 그리고, 항상 데이터베이스를 클린하는건좋지않으므로, 분기를처리한다.

    그리고, BG Processing task에는 추갖적인 properties가 있다.

    • 기본적으로 default이다.
    • 만약 네트워크가필요하다면, 무조건 true로해라. 그렇지않으면 네트워크가없는데도불구하고 계속 실행하럿이기때문이다.

    그리고 또다른 properties가있다.

    • 디바이스타입, 다양한시스템환경등으로, 충전중일때에 런치하도록하려고한다.
    • 그러므로, 많은리소스가필요한작업이라면, 배터리를 보존하기위해 이를 true로 하기를 권장한다.
    • 또한 true하게되면 CPU모니터를 disable하게해준다? ( 과도한작업을위해. )

     

     


    테스트는어떠케?


    The debug functions work only on devices.

    실제디바이스에 두고 실제 시간을 기다리면서해도된다.ㅎ

    하지만, 디버거안에서 호출할수있는 몇가지메서드가있따!

    시뮬레이터를 실행하고, 백그라운드에 갔다가, 다시 앱에들어온다.
    그리고, pause버튼을누른다. 그러면디버거모드로 진입한다.

    그리고, 명령어를입력하는데 공식문서에나와있으니, 붙여넣기한다.



    그리고 Task_IDENTIFIER 를 원하는 task identifier로 바꿔준다.

    그리고 enter 하면, 시스템이 잘인식했고,


    다시 play 버튼을 누르면!!!!!
    계속 앱이리프레시된다!!!
    ( 실제로 시뮬레이터에서도 앱포그라운드화면에서 계속리프래싱된다!!신기방기)

    그리고 다시 pause를 누르면, expiration 이 작동하는지 확인할시간이다!!
    그리고이번에는 Expiration으로 바꾸어서 엔터한다!

    그리고 다시 play한다!

     

     


    추가적을고려할점

     

    너무 멀리설정하지않는다. 추천은 week 아래로한다.

    그리고 디바이스가 잠겨있을때도 file을 접근할수있어야한한다.

    • 그러므로 권한을얻어야한다.무조건

    UIScene에서는 UIApplication.requestSceneSessionRefresh(_:) 를 호출해야한다. 자세한것은 공식문서에서확인할수있다.

     

    그리고 BGTaskScheduler .submit은 블록킹,동기적인 콜이다.
    그러므로, 앱이시작할때 좀더 performance-sesnsitive하려면, submit 콜을 background queue에서 하도록해라. 그래야 main thread를 막지않고, 런치타임을 지연시키지않을테니까!!

    댓글