iOS 7ã¯9æã«å ¬åŒã«ãªãªãŒã¹ãããAppleã¯éçºè ã«ãããã¯ãŒã¯ãæäœããæ°ããæ¹æ³NSURLSessionãæäŸããŸããã iOS 6以äžããµããŒãããå¿ èŠãããå Žåãã·ã¹ãã ããŒãžã§ã³ã«é¢ããã³ãŒãã®äžŠååã¯éåžžã«åé¡ã«ãªããããããã¯ããªãåºæ¬çãªããšã§ãã ããããããã§ãæéã足ããªããªããããŸããŸãªæ å ±æºã«ãããšããŠãŒã¶ãŒã®75ã85ïŒ ãææ°ã®iOSã«åãæ¿ããããã次ã®ãããžã§ã¯ãã§NSURLSessionãè©Šãããšããå§ãããŸãã
Appleã«ãããšãNSURLSessionã¯NSURLConnectionã眮ãæããå¿ èŠããããããã§æ¬åœã«çåãçããŸããããªãããããã¹ãŠå¿ èŠãªã®ã§ããïŒããããã£ãŠãããã«NSURLConnectionãšæ¯èŒããå©ç¹ïŒ
- ããã¯ã°ã©ãŠã³ãã§ããŒã¿ãããŠã³ããŒãããŠéä¿¡ãã
- ããŠã³ããŒããåæ¢ããŠç¶è¡ããæ©èœ
- ãããã¯ãšããªã²ãŒããåæã«äœ¿çšã§ããŸããããšãã°ãããŒã¿ãåä¿¡ããŠââãšã©ãŒãåŠçããããã«ãããã¯ã䜿çšããèªèšŒããããã«ããªã²ãŒãã¡ãœããã䜿çšããŸãã
- ã»ãã·ã§ã³ã«ã¯ãã»ãã·ã§ã³å ã®ãã¹ãŠã®ã¿ã¹ã¯ïŒãªã¯ãšã¹ãïŒã«å¿ èŠãªãã¹ãŠã®ããããã£ãšãããšãã°ã»ãã·ã§ã³å ã®ãã¹ãŠã®ãªã¯ãšã¹ãã®ããããŒãé 眮ã§ããç¹å¥ãªæ§æã³ã³ããããããŸãã
- Cookieããã£ãã·ã¥ãªã©ã«ãã©ã€ããŒãã¹ãã¬ãŒãžã䜿çšã§ããŸãã
- ä¹±éãªNSURLConnectionã®ã»ãããšã¯å¯Ÿç §çã«ãããå³å¯ã§æ§é åãããã³ãŒããååŸããŸã
æ°ããæ¹æ³ã¯ãŸã£ããæããªãã䜿çšãã䟡å€ãããããšã瀺ããŸãã ãã®ãããå§ããŸããããããŒã¯ã©ã¹ã¯NSURLSessionã§ããååã瀺ãããã«ãHTTPãä»ããŠããŒã¿ãããŒã/ã¢ã³ããŒãããããã®ç¹å®ã®ã»ãã·ã§ã³ãäœæããŸãã ã»ãã·ã§ã³ã«ã¯3ã€ã®ã¿ã€ãããããŸãïŒ ããã©ã«ã -ããã¯NSURLConnectionã䜿çšãããã®ã äžæçã§ã -äœããã£ãã·ã¥ãããããã¹ãŠãRAMã«ä¿åãããŸãïŒãã©ãŠã¶ã®ãã©ã€ããŒãã¢ãŒãã«äŒŒãŠããŸãïŒã ããŠã³ããŒã -çµæã¯ãã¡ã€ã«ã®åœ¢åŒã§è¡šç€ºãããŸãã
NSURLSessionConfiguration
ã»ãã·ã§ã³ã®ããããã£ã¯ãNSURLSessionConfigurationã¯ã©ã¹ã«ãã£ãŠå¶åŸ¡ãããŸãããã®ã¯ã©ã¹ã«ã¯ãã»ãã·ã§ã³ã®çš®é¡ïŒã¢ãã€ã«ãããã¯ãŒã¯çµç±ã®ããŠã³ããŒãæ©èœãCookieããã£ãã·ã¥ããããã·ãã»ãã¥ãªãã£ïŒã®éžæã«å ããŠãéåžžã«å€æ§ãªãã©ã¡ãŒã¿ãŒããããŸãã èå³æ·±ãè£éããããã£ã1ã€ãããŸããããã«ãããã·ã¹ãã ã®è£éã«ããŠã³ããŒããäžããããšãã§ããŸãïŒWi-Fiãšå€§éã®ããããªãŒé»æºãããå ŽåïŒã
NSURLSession
ã»ãã·ã§ã³æ§æãã»ããã¢ããããããã»ãã·ã§ã³èªäœãäœæããã³ã³ã¹ãã©ã¯ã¿ãŒã§æ§æãåãå ¥ããŸãã éåžžã®2ã€ã®æ¹æ³ã§ããŒã¿ãååŸããŸããããªã²ãŒããèšå®ããããå®äºãããã¯ã§ããŒã¿ããã£ããããŸãïŒãããã«ã€ããŠã¯å°ãåŸã§ïŒã
NSURLTask
æå°ã®ã¿ã¹ã¯ã¯ããã以åã¯NSURLConnectionã§ããã ã¯ã©ã¹èªäœã¯æœè±¡ã§ããã3ã€ã®ãµãã¯ã©ã¹ïŒNSURLSessionDataTaskãNSURLSessionUploadTaskïŒæåã®ãµãã¯ã©ã¹ïŒãNSURLSessionDownloadTaskããããç¬èªã®ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãããŸããã ãããã¯ãã¹ãŠãå®äºãããã¯ã®æç¡ã«ããããããã»ãã·ã§ã³èªäœã«ãã£ãŠäœæãããŸãïŒæåã®ã±ãŒã¹ã§ã¯ãã»ãã·ã§ã³ããªã²ãŒãã¯äžèŠã§ãïŒã ããã¯ãã¹ãŠãããšããŸããã¯ã«èŠããŸãïŒ
NSURLSessionDownloadTask *downloadTask = [ourSession downloadTaskWithRequest:simpleNSURLRequest];
ãããã¯ãšããªã²ãŒã
äžè¬ã«ãããŒãããã»ã¹èªäœã¯NSURLConnectionã®æäœãšéåžžã«ãã䌌ãŠããŸããã»ãã·ã§ã³ãæäœãã2ã€ã®æ¹æ³ãããã«æ€èšããŠãã ããã
ããªã²ãŒããéããŠïŒ
ã»ãã·ã§ã³ã¯ãäœææã«ããªã²ãŒããèšå®ããŸãã
[NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
ãã®åŸããã¹ãŠã®ããªã²ãŒãã¡ãœããïŒã¿ã¹ã¯ãå«ãïŒãããªã²ãŒãã§åŒã³åºãããŸãã
ãããã¯ãéããŠïŒ
ã§ã¿ã¹ã¯ãäœæããã ãã§ååã§ã
-(NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler
ç¹°ãè¿ãã«ãªããŸãããNSURLConnection -sendAsynchronousRequestïŒqueueïŒcompletionHandlerïŒ
ãã®å Žåãå¿ èŠã«å¿ããŠèªèšŒçšã®ããªã²ãŒãã¡ãœãããè¿œå ã§ããŸãã
äŸ
äžè¬çãªã¹ããŒã ãç解ããçè«ãå éãããäŸãèŠãæéãèšããŸããïŒ
ããŒããåæ¢/ç¶è¡ããŸãã
ã¹ããŒã å šäœã¯ãNSURLConnectionãä»ããäœæ¥ãšéåžžã«äŒŒãŠããŸããã圌ãšã¯ç°ãªããããŠã³ããŒãã¿ã¹ã¯ããã£ã³ã»ã«ããã ãã§ãã ãŸãããã£ã³ã»ã«ãããšãããªã²ãŒãã¡ãœããURLSessionïŒtaskïŒdidCompleteWithErrorïŒãåŒã³åºããããããUIã䜿çšããŠå¿ èŠãªãã¹ãŠã®æäœãå®è¡ã§ããŸãã ãããŠããã£ã³ã»ã«ããã ãã§ãªããåã«åæ¢ããããšãã§ããŸãã
[self.resumableTask cancelByProducingResumeData:^(NSData *resumeData) { partialDownload = resumeData; self.resumableTask = nil; }]; // if(partialDownload) { self.resumableTask = [inProcessSession downloadTaskWithResumeData:partialDownload]; } else { ... } [self.resumableTask resume];
ã¿ã¹ã¯ãåæ¢ããããšã«ãããåä¿¡ãããã¹ãŠã®ããŒã¿ãä¿åãããã®åŸæ°ããããŠã³ããŒãã¿ã¹ã¯ã«æž¡ãããšãã§ããŸãã
ãã¡ã€ã«ã«ã¢ããããŒã
ãã1ã€ç¢ºèªãããã®ã¯ãããŠã³ããŒãã¿ã¹ã¯ã§ãã ããŠã³ããŒããããã¡ã€ã«ãããã«ããŒãã§ããããšãæãåºãããŠãã ããã
ãããã¯ãéããŠïŒ
NSURLSessionConfiguration* sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig]; NSURL* downloadTaskURL = [NSURL URLWithString:@"http://upload.wikimedia.org/wikipedia/commons/1/14/Proton_Zvezda_crop.jpg"]; [[session downloadTaskWithURL: downloadTaskURL completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) { NSFileManager *fileManager = [NSFileManager defaultManager]; NSArray *urls = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; NSURL *documentsDirectory = [urls objectAtIndex:0]; NSURL *originalUrl = [NSURL URLWithString:[downloadTaskURL lastPathComponent]]; NSURL *destinationUrl = [documentsDirectory URLByAppendingPathComponent:[originalUrl lastPathComponent]]; NSError *fileManagerError; [fileManager removeItemAtURL:destinationUrl error:NULL]; // ! [fileManager copyItemAtURL:location toURL:destinationUrl error:&fileManagerError]; }] resume];
ããªã²ãŒãã¡ãœãããä»ããŠïŒ
NSURLSessionConfiguration* sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil]; NSURL* downloadTaskURL = [NSURL URLWithString:@"http://upload.wikimedia.org/wikipedia/commons/1/14/Proton_Zvezda_crop.jpg"]; [[session downloadTaskWithURL:downloadTaskURL] resume]; // - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { // }
locationå€æ°ã§ããã€ã¹ã®ã¢ãã¬ã¹ãååŸãããšèšãå¿ èŠããããŸãã
ãã¡ã€ã«ïŒ/// private / var / mobile / Applications / {appUUID} /tmp/CFNetworkDownload_fileID.tmp /Proton_Zvezda_crop.jpg
äžåºŠã«æéæ°ã®ãªã¯ãšã¹ããéä¿¡ããŸã
åæãªã¯ãšã¹ãã®æ°ãå¶éããå¿ èŠãããå ŽåããããŸã-5ããã®å Žåãæ倧æ¥ç¶æ°ãæå®ããã ãã§ãã
sessionConfig.HTTPMaximumConnectionsPerHost = 5;
ããã«ãè©ŠããŠã¿ãäŸããããŸãã倧ããªãã¡ã€ã«ãååŸããããšããå§ãããŸãã3gã§ããŠã³ããŒããã·ãã¥ã¬ãŒãããããšããå§ãããŸãïŒèšå®->éçºè ->ãããã¯ãŒã¯ãªã³ã¯ã³ã³ãã£ã·ã§ããŒ->ãããã¡ã€ã«ã®éžæ-> 3g->æå¹ïŒ
- (void) methodForNSURLSession{ NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; _tasksArray = [[NSMutableArray alloc] init]; sessionConfig.HTTPMaximumConnectionsPerHost = 5; sessionConfig.timeoutIntervalForResource = 0; sessionConfig.timeoutIntervalForRequest = 0; NSURLSession* session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil]; // download tasks // [self createDataTasksWithSession:session]; // data tasks [self createDownloadTasksWithSession:session]; } - (void) createDownloadTasksWithSession:(NSURLSession *)session{ for (int i = 0; i < 10; i++) { NSURLSessionDownloadTask *sessionDownloadTask = [session downloadTaskWithURL: [NSURL URLWithString:@"https://discussions.apple.com/servlet/JiveServlet/showImage/2-20930244-204399/iPhone%2B5%2BProblem2.jpg"]]; [_tasksArray addObject:sessionDownloadTask]; [sessionDownloadTask addObserver:self forKeyPath:@"countOfBytesReceived" options:NSKeyValueObservingOptionOld context:nil]; [sessionDownloadTask resume]; } } - (void) createDataTasksWithSession:(NSURLSession *)session{ for (int i = 0; i < 10; i++) { NSURLSessionDataTask *sessionDataTask = [session dataTaskWithURL: [NSURL URLWithString:@"https://discussions.apple.com/servlet/JiveServlet/showImage/2-20930244-204399/iPhone%2B5%2BProblem2.jpg"]]; [_tasksArray addObject:sessionDataTask]; [sessionDataTask addObserver:self forKeyPath:@"countOfBytesReceived" options:NSKeyValueObservingOptionOld context:nil]; [sessionDataTask resume]; } } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if([[change objectForKey:@"old"] integerValue] == 0){ NSLog(@"task %d: started", [_tasksArray indexOfObject: object]); } } - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{ NSLog(@"task %d: finished!", [_tasksArray indexOfObject:task]); }
ãã®äŸã¯éåžžã«ã·ã³ãã«ã§éæã§ããã1ã€ã®ç¹ã«æ³šæãåããŸãã
sessionConfig.timeoutIntervalForResource = 0; sessionConfig.timeoutIntervalForRequest = 0;
ããã¥ã¡ã³ãã«ãããšïŒ
timeoutIntervalForRequest-åã¿ã¹ã¯ã®ããŒãã«å²ãåœãŠãããæé
timeoutIntervalForResource-ãã¹ãŠã®ãªã¯ãšã¹ãã®ããŒãã«å²ãåœãŠãããæé
ããã«åé¡ããããŸããå®éãã¿ã¹ã¯ãéå§ããç¬éïŒ[task resume]ïŒã«timeoutIntervalForRequestã«ãŠã³ã¿ãŒãã«ãã«ã鳎ãå§ããŸãã100åã®ã¿ã¹ã¯ããããåæã«5ã€ããåäœã§ããªãããšã«èª°ãæ°ã«ããŸããããã®çç±ã¯ãæåŸã«åŒã³åºãããã¿ã¹ã¯ã¯å°ãã®ããŒã¿ãåä¿¡ããã«çµäºã§ããããããããã®ãã©ã¡ãŒã¿ãŒã®å€ã¯åãã§ããå¿ èŠãããããã§ãã
ãããã£ãŠãäž¡æ¹ã®å€æ°ãåãå€ã«èšå®ãã以å€ã«éžæè¢ã¯ãããŸããã0ã«èšå®ããããšãã§ããŸãããã®å Žåãã«ãŠã³ã¿ãŒã¯ç¡éã«ãªããŸãã
ã¯ãããã¡ãããèªè»¢è»ãçºæããã¿ã¹ã¯ã®æ°ãåå¥ã«ç£èŠã§ããŸããããç®±ããåºããŠããã«ããªãã·ã§ã³ãæ¬åœã«å¿ èŠã§ãã ããã§ãç§ã®æèŠã§ã¯ãAppleã®ãšã³ãžãã¢ã¯ååã«èããŠããŸããã§ããã
ããŠã³ããŒã远跡
ã¿ã¹ã¯ã®ããŠã³ããŒãã«ã¯ãç¹å¥ãªããªã²ãŒãã¡ãœããããããŸãã
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { double progress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite; NSLog(@"download: %@ progress: %f", downloadTask, progress); dispatch_async(dispatch_get_main_queue(), ^{ self.progressView.progress = progress; }); }
æ®ãã®ã¿ã¹ã¯ã§ã¯ãåã®äŸã®ããã«KVOã䜿çšã§ããŸãã
ããã¯ã°ã©ãŠã³ãã§ããŠã³ããŒããã
æåŸã«ãããã¯ã°ã©ãŠã³ãã§ã®èªã¿èŸŒã¿ã®äŸã«ã€ããŠèª¬æããŸãããã®äŸã¯wwdc'13 705ã®ãã¢ãç¹°ãè¿ããŸããå人çã«ããã¢ã¯ç§ã«è¡æãäžããŸããã ç»åã®ããŠã³ããŒããéå§ããã¢ããªã±ãŒã·ã§ã³ãçµäºããŠæ»ããŸããç»åãèªã¿èŸŒãŸããæ¢ã«ã¬ã€ã¢ãŠããããŠããŸããããã¯ããã«ãã¿ã¹ã¯ã¡ãã¥ãŒïŒããŒã ãã¿ã³ãããã«ã¯ãªãã¯ããããšã§ãïŒã§èŠãããšãã§ããŸãã ããããã以äžã«ãããŒãæã«ã¢ããªã±ãŒã·ã§ã³ããããããããšãããŠã³ããŒãã¯çµäºããäœãèµ·ãããªãã£ãããã«ãã¹ãŠãæ»ããŸãïŒ ã¯ããããŒãåŸãããã¯ã°ã©ãŠã³ãã§UIãæŽæ°ããããã«ãã¿ã¹ã¯ã¡ãã¥ãŒã®ã¹ãããã·ã§ãããå€æŽãããŸãã ããŠã³ããŒããçµäºããªãå¯äžã®ã±ãŒã¹ã¯ããŠãŒã¶ãŒãèªåã§ã¢ããªã±ãŒã·ã§ã³ã匷å¶çµäºããå Žåã§ãããäœãããå¿ èŠã¯ãããŸããããã¹ã¿ãŒã¯ãã¹ã¿ãŒã§ãã
ãªããã®ãããªãããžãã¯ããæ©èœããã®ã§ããïŒ åé¡ã¯ãã¢ããªã±ãŒã·ã§ã³ãããã¯ã°ã©ãŠã³ãããã»ã¹ãéå§ãããšãã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ã«ããŒã¿ã転éããããŒã¢ã³ãäœæããããšã§ãã ããã¯è«ççã§ãããã¢ããªã±ãŒã·ã§ã³ããç¬ç«ããŠçããäœããå¿ èŠã§ãã ãã®ãããã¢ããªã±ãŒã·ã§ã³ãåæ¢ãŸãã¯ã¯ã©ãã·ã¥ããããšãæããŠããŸããã ããŠã³ããŒããå®äºãããšãããŒã¢ã³ã¯ã¢ããªã±ãŒã·ã§ã³ããèµ·åãããŸãããã®åŸãã»ãã·ã§ã³ã埩å ãããã¹ãŠã®ããŒã¿ãååŸã§ããŸãã å€ãèå¥åã§æ°ããã»ãã·ã§ã³ãäœæãããšãæ¢åã®ããã¯ã°ã©ãŠã³ãã»ãã·ã§ã³ã«ãæ¥ç¶ããããŸãã
ããã§äž»èŠãªãã€ã³ããåæããŸã ããã¹ããããžã§ã¯ãèªäœã¯ããã§éžæã§ããŸã ã
æåã«ãã·ã³ã°ã«ãã³ã¹ã¿ã€ã«ã§ã»ãã·ã§ã³ãäœæããŸãã
- (NSURLSession *)backgroundSession{ static NSURLSession *session = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // , NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.dev.BackgroundDownloadTest.BackgroundSession"]; [config setAllowsCellularAccess:YES]; session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil]; }); return session; }
ããŠã³ããŒããéå§ããŸãïŒããã§ã¯è³ªåã¯ãããŸããïŒïŒ
self.downloadTask = [[self backgroundSession] downloadTaskWithURL:[NSURL URLWithString:@"https://discussions.apple.com/servlet/JiveServlet/showImage/2-20930244-204399/iPhone%2B5%2BProblem2.jpg"]]; [self.downloadTask resume];
ããã¯ã°ã©ãŠã³ãã¿ã¹ã¯ã®ããªã²ãŒãã¡ãœããã§ãç»åãä¿åããŠè¡šç€ºããŸãã
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { // save image // //... // set image if (success) { dispatch_async(dispatch_get_main_queue(), ^{ self.imageView.image = [UIImage imageWithContentsOfFile:[destinationPath path]]; [self.progressView setHidden:YES]; }); } }
ãã¹ãŠã®ã¿ã¹ã¯ã®çµããã®ããªã²ãŒãã¡ãœããã§ãããŠã³ããŒãã®çµããããã£ããããŸãïŒãã®å Žåãthisããã³åã®ã¡ãœãããåŒã³åºãããŸãïŒ
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { if (error) { NSLog(@"error: %@ - %@", task, error); } else { NSLog(@"success: %@", task); } self.downloadTask = nil; // , [self callCompletionHandlerIfFinished]; }
ããã§ã¯ãAppDelegate.mã«ç§»åããŸãããã
ããŠã³ããŒããçµäºããããã·ã¹ãã ããã¡ãã»ãŒãžããã£ããããå¿ èŠããããŸãã
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler { // , UILocalNotification* locNot = [[UILocalNotification alloc] init]; locNot.fireDate = [NSDate dateWithTimeIntervalSinceNow:1]; locNot.alertBody = [NSString stringWithFormat:@"still alive!"]; locNot.timeZone = [NSTimeZone defaultTimeZone]; [[UIApplication sharedApplication] scheduleLocalNotification:locNot]; // - , , // UI . // self.backgroundSessionCompletionHandler = completionHandler; }
ã¡ã€ã³ã³ã³ãããŒã©ãŒã«æ»ããŸãã
å¿ èŠã«å¿ããŠã»ãã·ã§ã³ã埩å ããŸãã
- (void)viewDidLoad { [super viewDidLoad]; [self backgroundSession]; }
æåŸã«åŒã³åºãããã¡ãœããïŒ
- (void)callCompletionHandlerIfFinished { NSLog(@"call completion handler"); [[self backgroundSession] getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) { NSUInteger count = [dataTasks count] + [uploadTasks count] + [downloadTasks count]; if (count == 0) { // // // UI NSLog(@"all tasks ended"); AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; if (appDelegate.backgroundSessionCompletionHandler == nil) return; void (^comletionHandler)() = appDelegate.backgroundSessionCompletionHandler; appDelegate.backgroundSessionCompletionHandler = nil; comletionHandler(); } }]; }
ãã®ãã³ãã©ãåŒã³åºããªãå Žåããã°ã«èŠåã衚瀺ãããããšãè¿œå ããŸãã
Warning: Application delegate received call to - application:handleEventsForBackgroundURLSession:completionHandler: but the completion handler was never called.
ãŸãããã«ãã¿ã¹ã¯ã¡ãã¥ãŒãéããå ŽåãæŽæ°ãããã€ã³ã¿ãŒãã§ã€ã¹ã¯è¡šç€ºãããŸããã å®éããã®äŸã¯ãAppleãç§ãã¡ã«èªã£ããã«ãã¿ã¹ã¯ãUIãã®åŽé¢ã®1ã€ã瀺ããŠããŸãã
ããã ãã§ãããã®èšäºã§ãä»åŸã®ãããžã§ã¯ãã§NSURLSessionã䜿çšããããšããå§ãããŸãã