Особенности фоновой работы iOS-приложения на примере...

Preview:

DESCRIPTION

Особенности фоновой работы iOS-приложения на примере синхронизации Яндекс.Диска

Citation preview

Патосин Алексей, ведущий iOS разработчик Яндекс.Диска

Особенности фоновой работы iOS приложения на примере синхронизации Яндекс.Диска

Autoloading

Offline

Agenda

Agenda

〉Background on iOS Before

Agenda

〉Background on iOS Before

〉Background on iOS Now

Agenda

〉Background on iOS Before

〉Background on iOS Now

〉How we did it

Agenda

〉Background on iOS Before

〉Background on iOS Now

〉How we did it

〉Our secrets

Closed

Closed

Foreground

Closed

ForegroundSleep

Closed

ForegroundSleep

Closed

Foreground

Background

Sleep

Closed

Foreground

Background

up to 10 min

Sleep

Closed

Foreground

Background

Sleep

Closed

Foreground

Background

Sleep

Background fetch

Silent notifications

NSURLSession

Closed

Foreground

Background

Sleep

Background fetch

Silent notifications

NSURLSession

Closed

Foreground

Background

Sleep

Background fetch

Silent notifications

NSURLSession

Closed

Foreground

Background

Sleep

Background fetch

Silent notifications

NSURLSession

Closed

Foreground

Background

Sleep

Background fetch

Silent notifications

NSURLSession

Closed

Foreground

Background

Sleep

Background fetch

Silent notifications

NSURLSession

Closed

Foreground

Background

Sleep

Background fetch

Silent notifications

NSURLSession

up to 30 sec

Closed

Foreground

Background

Sleep

Background fetch

Silent notifications

NSURLSession

up to 30 sec up to 3 min (was 10)

Background Fetch

Sleep Background

Background Fetch

Sleep Background

Silent Push Notifications

Sleep Background

Silent Push Notifications

Sleep Background

NSURLSession

NSURLSession

NSURLSession

NSURLSession

NSURLSession

Connection

! Configuration

Connection

! Configuration

Connection

! Configuration

NSURLSession

NSURLSession

!

!

!

!

!

Connection

! Configuration

Connection

! Configuration

Connection

! Configuration

NSURLSession

NSURLSession

!

!

!

!

!

Connection

! Configuration

Configuration

Connection

! Configuration

Connection

! Configuration

NSURLSession

NSURLSession

!

!

!

!

!

Task

Task

Task

Connection

! Configuration

Configuration

Connection

! Configuration

Connection

! Configuration

NSURLSession Tasks

NSURLSession Tasks

Data Task

NSURLSession Tasks

Data Task Upload Task

NSURLSession Tasks

Data Task Upload Task Download Task

NSURLSession Tasks

Data Task Upload Task Download Task

background background

NSURLSession Tasks

Background transfer is supported only when WiFi is available!

Data Task Upload Task Download Task

background background

NSURLSession

class NSURLSession : NSObject { //.. init(configuration: NSURLSessionConfiguration) -> NSURLSession //.. func dataTaskWithURL(url: NSURL) -> NSURLSessionDataTask //.. func uploadTaskWithRequest(request: NSURLRequest, fromFile fileURL: NSURL) -> NSURLSessionUploadTask ! //.. func downloadTaskWithURL(url: NSURL) -> NSURLSessionDownloadTask ! //.. }

nsurlsessiond

nsurlsessiond

Task

Task

Task

nsurlsessiond nsurlsessiond

!

!

!

!

!

!

Task

Task

Task

nsurlsessiond nsurlsessiond

!

!

!

!

!

!

Task

Task

Task

nsurlsessiond nsurlsessiond

!

!

!

!

!

!

Task

Task

Task

nsurlsessiond nsurlsessiond

!

!

!

!

!

!

Task

Task

Task

nsurlsessiond nsurlsessiond

!

!

!

!

!

!

Task

Task

Task

nsurlsessiond nsurlsessiond

!

!

!

!

!

!

Task

Task

Task

completionHandler: ((UIBackgroundFetchResult) -> Void)!)

NSURLSessionDataTask

iOS Non-deterministic System

Petri Dishes Experiment

Background Fetch Alarm Experiment

Background Fetch Alarm Experiment

00:00 03:00 06:00 09:00 12:00 15:00 18:00 21:00 24:00

Background Fetch Alarm Experiment

00:00 03:00 06:00 09:00 12:00 15:00 18:00 21:00 24:00

Background Fetch Alarm Experiment

00:00 03:00 06:00 09:00 12:00 15:00 18:00 21:00 24:00

Background Fetch Alarm Experiment

00:00 03:00 06:00 09:00 12:00 15:00 18:00 21:00 24:00

Background Fetch Alarm Experiment

00:00 03:00 06:00 09:00 12:00 15:00 18:00 21:00 24:00

Background Fetch Alarm Experiment

00:00 03:00 06:00 09:00 12:00 15:00 18:00 21:00 24:00

Non-deterministic NSURLSession

nsurlsessiond

!

!

!

!

!

!

Task

Task

Task

Delivery of remote notifications is not guaranteed!

Delivery of remote notifications is not guaranteed!

Delivery of remote notifications is not guaranteed!

Delivery of remote notifications is not guaranteed!

Delivery of remote notifications is not guaranteed!

Best Practices

Divide and Conquer

Divide and Conquer

NSURLSession

(background)

Upload

NSURLSession

(background)

Download

NSURLSession

!

Data

Logic Restoration

successBlock(…);

failureBlock(…);

progressBlock(…); nsurlsessiond

!

!

Logic Restoration

successBlock(…);

failureBlock(…);

progressBlock(…); nsurlsessiond

!

!

Logic Restoration

successBlock(…);

failureBlock(…);

progressBlock(…); nsurlsessiond

!

!

Logic Restoration

successBlock(…);

failureBlock(…);

progressBlock(…); nsurlsessiond

!

!

Logic Restoration

successBlock(…);

failureBlock(…);

progressBlock(…); nsurlsessiond

!

!

Logic Restoration

successBlock(…);

failureBlock(…);

progressBlock(…); nsurlsessiond

!

!

Logic Restoration

successBlock(…);

failureBlock(…);

progressBlock(…); nsurlsessiond

!

!

Logic Restoration

successBlock(…);

failureBlock(…);

progressBlock(…); nsurlsessiond

!

!

var taskDescription: String

Logic Restoration

successBlock(…);

failureBlock(…);

progressBlock(…); nsurlsessiond

!

!

func getTasksWithCompletionHandler(_ completionHandler: ([AnyObject]!, [AnyObject]!, [AnyObject]!) -> Void)

var taskDescription: String

CompletionHandler

CompletionHandler

optional func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler handler: (UIBackgroundFetchResult) -> Void)

optional func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void)

optional func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler completionHandler: () -> Void)

How to support long-running operations in background

How to support long-running operations in background

Parsing

How to support long-running operations in background

30 sec

Parsing

parsingOffset = 12 424 523

How to support long-running operations in background

30 sec

Parsing

parsingOffset = 12 424 523

30 sec

parsingOffset = 25 992 012

How to support long-running operations in background

30 sec

Parsing

parsingOffset = 12 424 523

30 sec 30 sec

parsingOffset = 25 992 012parsingOffset = 34 436 001

How to support long-running operations in background

30 sec

Parsing

parsingOffset = 12 424 523

30 sec 30 sec 30 sec

parsingOffset = 25 992 012parsingOffset = 34 436 001parsingOffset = 41 928 528

How to support long-running operations in background

30 sec

Parsing

parsingOffset = 12 424 523

30 sec 30 sec 30 sec 12 sec

parsingOffset = 25 992 012parsingOffset = 34 436 001parsingOffset = 41 928 528

How to support long-running operations in background

url type was_processed

1

1

0

0

How to support long-running operations in background

url type was_processed

1

1

0

0

How to support long-running operations in background

url type was_processed

1

1

0

0

ALAssetsLibrary

NSURLSessionTask Bug

nsurlsessiond

!

!

!

!

!

!

Task

Task

Task

var discretionary: Bool

Redirect in background

Redirect in background

Authorization

Redirect in background

Authorization

User-Agent

Redirect in background

Authorization

User-Agent

Yandex-Authorization

How to test activity in background?

Logs

Logs #upload_queue_manager Upload next file in queue. (0 left) #upload_queue_manager nextFileInQueue #upload_queue_manager nextFileInQueueForForegroundUpload #upload_queue_manager nextFileInQueue, was selected (null) file #upload_queue_manager There are no more files in upload queue. #upload_queue_manager nextFileInQueue #upload_queue_manager nextFileInQueueForForegroundUpload #upload_queue_manager nextFileInQueue, was selected (null) file #upload_queue_manager endBackgroundTask invoked #completion_handlers_manager endedWithoutAnyData Failed to download thumbnail for https://webdav.yandex.ru/disk/2014-07-02%2018-17-31.jpg, resend request in 1.000 #offline_updater update root offline status 1 for file <YOFile: 0x7fadde15e440> https://webdav.yandex.ru/disk/_test/_DSC2502%20copy%202.ARW #download_queue_manager download offline files {( <YOFile: 0x7fadde15e440> https://webdav.yandex.ru/disk/_test/_DSC2502%20copy%202.ARW )} #download_queue_manager looking for next offline file.. #download_queue_manager Found file for download https://webdav.yandex.ru/disk/_test/_DSC2502%20copy%202.ARW (mask: 4) #connection_manager Start download https://webdav.yandex.ru/disk/_test/_DSC2502%20copy%202.ARW #task_description description now contains: {"kURLSessionTaskDescriptionWasCreatedInBackground":0,"kURLSessionTaskDescriptionURLString":"https:\/\/webdav.yandex.ru\/disk\/_test\/_DSC2502%20copy%202.ARW"} #connection_manager NSURLSessionDownloadTask <__NSCFBackgroundDownloadTask: 0x7faddbc40750>{ taskIdentifier: 1 } started, invoking completionHandler if it has now #completion_handlers_manager urlSessionTaskStarted: #completion_handlers_manager current properties state: sessionCompletionHandlers { } backgroundFetchCompletionHandler (null) remoteNotificationCompletionHandler (null) backgroundFetchCompletionHandlerCreationDate (null) processIdentifiers {( )} !#completion_handlers_manager there's no URLSession completionHandler right now #offline_updater update root offline status 1 for file <YOFile: 0x7fadde1926a0> https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW #download_queue_manager download offline files {(

Logs

#download_queue_manager looking for next offline file.. #download_queue_manager Found file for download https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (mask: 4) #connection_manager Start download https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW #session_manager completed task <__NSCFBackgroundDownloadTask: 0x7faddbc4e700>{ taskIdentifier: 4 } with URL https://webdav.yandex.ru/disk/_test/101@2x~iphone.png error (null) #task_description description now contains: {"kURLSessionTaskDescriptionWasCreatedInBackground":0,"kURLSessionTaskDescriptionURLString":"https:\/\/webdav.yandex.ru\/disk\/_test\/_DSC2502%20copy.ARW"} #connection_manager NSURLSessionDownloadTask <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } started, invoking completionHandler if it has now #completion_handlers_manager urlSessionTaskStarted: #completion_handlers_manager current properties state: sessionCompletionHandlers { } backgroundFetchCompletionHandler (null) remoteNotificationCompletionHandler (null) backgroundFetchCompletionHandlerCreationDate (null) processIdentifiers {( )} #completion_handlers_manager there's no URLSession completionHandler right now #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (15711916/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (15761068/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (15793836/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (15859372/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (15924908/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16006828/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16072364/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16137900/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16203436/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16285356/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16350892/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16416428/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16498348/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16563884/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16645804/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16711340/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16776876/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16809644/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16858796/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16924332/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (16989868/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (17071788/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (17137324/24936448) #session_manager data written for task <__NSCFBackgroundDownloadTask: 0x7fadde03e140>{ taskIdentifier: 5 } with URL https://webdav.yandex.ru/disk/_test/_DSC2502%20copy.ARW (17219244/24936448)

Logs

Logs

Sniffer

Sniffer

Wireshark

Sniffer

Wireshark Charles

Local Notifications

One more secret…

How to prolong Background activity

How to prolong Background activity

How to prolong Background activity

30 sec

How to prolong Background activity

30 sec

How to prolong Background activity

30 sec

30 sec

How to prolong Background activity

30 sec

30 sec

func beginBackgroundTaskWithExpirationHandler(_ handler: () -> Void) -> UIBackgroundTaskIdentifier

How to prolong Background activity

30 sec

30 sec

func beginBackgroundTaskWithExpirationHandler(_ handler: () -> Void) -> UIBackgroundTaskIdentifier

up to 3 min

Results

!Up to 2M !

files are being uploaded each day from iOS client

70% files are uploaded in background

Uploading in background

Uploading in background

Background

Foreground

1M Background Fetches per day

less than 5%

Итак

Thanks!

Теперь питание компьютера можно отключить

Alexey Patosin

Senior iOS Software Engineer – Yandex

Contacts

@gn0meavpalexey@patosin.ru

Recommended