In deze zelfstudie wordt uitgelegd hoe u de achtergrondoverdrachtsdienst gebruikt, een multitasking-API die wordt aangeboden door iOS 7. Ik zal u leren hoe u een app kunt maken die een bestand downloadt zonder dat de toepassing op de voorgrond staat. Zodra het bestand volledig is gedownload, verschijnt er een bericht. Ga door met lezen om deze service te maken!
Achtergrondoverdrachtsdienst afkomstig van iOS 6. Met deze functie konden apps bestanden overdragen in zowel de voorgrond- als de achtergrondmodus, maar de minuten beperken. Het grootste probleem was toen de "beperkte minuten" de gebruiker niet toestaat om grote bestanden te downloaden of te uploaden. Dit is de reden waarom Apple het framework verbeterde in iOS 7.
Met iOS 7 onderging deze functie grote veranderingen, waaronder:
Background Transfer Service kan worden gebruikt voor verschillende afzonderlijke en handige taken, zoals: het uploaden van foto's of video's, het combineren van achtergrondophalen en externe meldingen, en voor het up-to-date houden van de app, zoals met aankopen voor boeken, tv-programma's, podcasts, game-inhoud, kaarten en meer.
Voor het maken van deze service hebben we één weergave nodig met de volgende eigenschappen:
UIDocumentInterationController
(om de download van het PDF-document te openen)Start eerst een nieuw Xcode-iPhone-project. Maak vervolgens een Toepassing enkele weergave. Ga vervolgens naar de Main.Storyboard
en voeg wat objecten toe aan onze Uitzicht. Om de. Toe te voegen NavigationController selecteer de Default View Controller. Selecteer in het Xcode-menu Editor> Insluiten> Navigatiecontroller. U moet het bestand slepen en neerzetten Baritem en de Voortgangsweergave naar uw View Controller. Als u klaar bent, ziet de View Controller er ongeveer zo uit als de volgende afbeelding:
Laten we nu de eigenschappen toevoegen die nodig zijn om te communiceren met de objecten die we hebben toegevoegd. In ViewController.h
, voeg de volgende regels toe:
@property (weak, nonatomic) IBOutlet UIProgressView * progressView; - (IBAction) start: (id) afzender;
Verander nu de weergave voor de ViewController.m
. Er verschijnt een waarschuwing, maar maak je daar geen zorgen over; we lossen het later op. Ga terug naar de Main.Storyboard
en verbind de objecten met de eigenschappen en acties.
Deze stap is triviaal, maar als u zich zorgen maakt, kunt u het gedeelte met opmerkingen hieronder gebruiken.
De NSURLSession
klassen en gerelateerde klassen bieden een API om content via te downloaden of te uploaden HTTP. Deze API is verantwoordelijk voor het beheer van een reeks overdrachtstaken. U moet drie objecten maken die rechtstreeks verband houden met die klasse: één NSURLSession
, NSURLSessionDownloadTask
, en UIDocumentInteractionController
.
Jouw ViewController.h
zal zoiets zijn als dit:
@property (nonatomic) sessie NSURLSession *; @property (nonatomic) NSURLSessionDownloadTask * downloadTask; @property (strong, nonatomic) UIDocumentInteractionController * documentInteractionController;
Bovendien verklaart u ook vier protocollen: NSURLSessionDelegate
, NSURLSessionTaskDelegate
, NSURLSessionDownloadDelegate
, en UIDocumentInteractionControllerDelegate
. Jouw @interface
zou moeten lijken op:
@interface ViewController: UIViewController < NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate,UIDocumentInteractionControllerDelegate>
De eigenschappen die we zullen toevoegen zijn nuttig om onze sessie en het downloadproces te instantiëren en te manipuleren, waardoor u de status kunt hervatten, opschorten, annuleren of terughalen. De laatste eigenschap, UIDocumentInterationController
wordt gebruikt om het PDF-document te presenteren dat is gedownload in deze zelfstudie.
Ga nu naar ViewController.m
.
De eerste taak die moet worden voltooid, is om een tekenreeks toe te voegen aan de locatie van het bestand dat moet worden gedownload. Gebruik een standaard Apple PDF.
static NSString * DownloadURLString = @ "https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/ObjC_classic/FoundationObjC.pdf";
Op de viewDidLoad
methode, laten we instantiëren en stel zowel de sessie als de voortgangsaanzichten in:
self.session = [self backgroundSession]; self.progressView.progress = 0; self.progressView.hidden = YES;
Omdat je de backgroundSession
methode, en het bestaat niet, je moet het nu declareren. Deze methode is verantwoordelijk voor het verzenden van één actie die de achtergrondsessie zal zijn. De backgroundSession
door het dispatch_once
voert een blok een keer uit gedurende de volledige levensduur van de applicatie. De NSString ontvangen door de NSURLSessionConfiguration
vertegenwoordigt de ID van onze sessie. Deze ID moet uniek zijn voor elke NSURLSession-instantie.
De volledige methode is als volgt:
- (NSURLSession *) backgroundSession static NSURLSession * session = nil; static dispatch_once_t onceToken; dispatch_once (& onceToken, ^ NSURLSessionConfiguration * configuration = [NSURLSessionConfiguration backgroundSessionConfiguration: @ "com.example.apple-samplecode.SimpleBackgroundTransfer.BackgroundSession"]; session = [NSURLSession sessionWithConfiguration: configuration delegate: self delegateQueue: nil];); terugkomst sessie;
De (IBAction) start: (id) verzender
methode start het downloaden van het document. U start dan een NSURL
en een NSURLRequest
en gebruik de downloadTask
eigenschap om het aanvraagobject door te geven aan de downloadTaskWithRequest
methode. De volledige methode is hieronder.
- (IBAction) start: (id) afzender if (self.downloadTask) retour; NSURL * downloadURL = [NSURL URLWithString: DownloadURLString]; NSURLRequest * request = [NSURLRequest requestWithURL: downloadURL]; self.downloadTask = [self.session downloadTaskWithRequest: request]; [self.downloadTask CV]; self.progressView.hidden = NO;
Op dit punt merk je dat er drie waarschuwingen aanwezig zijn. Ze stellen dat de protocolmethode moet worden geïmplementeerd. De NSURLSessionDownloadDelegate
protocol definieert de methoden om de downloadtaak af te handelen. Om de download uit te voeren, moet u de drie deelnemersmethoden gebruiken.
Voeg dus de volgende drie methoden toe:
(void) URLSession: (NSURLSession *) sessie downloadTask: (NSURLSessionDownloadTask *) downloadTask didWriteData: (int64_t) byteswritte totalBytesWritten: (int64_t) totalByteswritte totalBytesExpectedToWrite: (int64_t) totalBytesExpectedToWrite
(void) URLSession: (NSURLSession *) sessie downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) downloadURL
(void) URLSession: (NSURLSession *) sessie downloadTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset expectedTotalBytes: (int64_t) expectedTotalBytes
De (void) URLSession: (NSURLSession *) sessie downloadTask: (NSURLSessionDownloadTask *) downloadTask didWriteData: (int64_t) byteswritte totalByteswritte: (int64_t) totalByteswritte totalBytesExpectedToWrite: (int64_t) totalBytesExpectedToWrite
methode is verantwoordelijk om het algehele downloadproces bij te houden. Het werkt ook het progressView
overeenkomstig. De volledige methode is hieronder.
- (void) URLSession: (NSURLSession *) sessie downloadTask: (NSURLSessionDownloadTask *) downloadTask didWriteData: (int64_t) byteswritte totalBytesWritten: (int64_t) totalByteswritte totalBytesExpectedToWrite: (int64_t) totalBytesExpectedToWrite if (downloadTask == self.downloadTask) double progress = ( double) totalByteswritten / (double) totalBytesExpectedToWrite; NSLog (@ "DownloadTask:% @ progress:% lf", downloadTask, progress); dispatch_async (dispatch_get_main_queue (), ^ self.progressView.progress = progress;);
De (void) URLSession: (NSURLSession *) sessie downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) downloadURL
methode behandelt de gegevens zelf (oorsprong en bestemming). Het bestuurt het bestand alleen als het volledig is gedownload. Simpel gezegd, het vertelt de afgevaardigde dat een downloadtaak klaar is met downloaden. Het bevat de sessie-taak die is voltooid, de downloadtaak die is voltooid en een bestands-URL waar het tijdelijke bestand kan worden gevonden. Het zou er zo uit moeten zien:
- (void) URLSession: (NSURLSession *) sessie downloadTask: (NSURLSessionDownloadTask *) downloadTask didFinishDownloadingToURL: (NSURL *) downloadURL NSFileManager * fileManager = [NSFileManager defaultManager]; NSArray * URL's = [fileManager URL's ForDirectory: NSDocumentDirectory inDomains: NSUserDomainMask]; NSURL * documentsDirectory = [URL's objectAtIndex: 0]; NSURL * originalURL = [[downloadTask originalRequest] URL]; NSURL * destinationURL = [documentationDirectory URLByAppendingPathComponent: [oorspronkelijkeURL lastPathComponent]]; NSError * errorCopy; // Verwijder voor het testen alle bestaande bestanden op de bestemming. [fileManager removeItemAtURL: destinationURL error: NULL]; BOOL-succes = [fileManager copyItemAtURL: downloadURL toURL: destinationURL-fout: & errorCopy]; if (succes) dispatch_async (dispatch_get_main_queue (), ^ // download finished - open de pdf self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL: destinationURL]; // Configureer Document Interaction Controller [self.documentInteractionController setDelegate: self]; // Voorbeeld PDF [self.documentInteractionController presentPreviewAnimated: YES]; self.progressView.hidden = YES;); else NSLog (@ "Fout tijdens de kopie:% @", [errorCopy localizedDescription]);
eindelijk, de (void) URLSession: (NSURLSession *) sessie downloadTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset expectedTotalBytes: (int64_t) expectedTotalBytes
moet ook worden aangegeven. Maar wees ervan bewust dat we het niet verder zullen gebruiken.
-(void) URLSession: (NSURLSession *) sessie downloadTask: (NSURLSessionDownloadTask *) downloadTask didResumeAtOffset: (int64_t) fileOffset expectedTotalBytes: (int64_t) expectedTotalBytes
Je bent bijna klaar met deze les, er zijn nog maar twee methoden: (void) URLSession: (NSURLSession *) sessietaak: (NSURLSessionTask *) task didCompleteWithError: (NSError *) fout
, en - (ongeldig) URLSessionDidFinishEventsForBackgroundURLSession: sessie (NSURLSession *)
.
De eerste methode informeert de gedelegeerde dat de taak klaar is met het overdragen van gegevens. Je moet het ook gebruiken om elke fout die optreedt te volgen.
- (void) URLSession: (NSURLSession *) sessietaak: (NSURLSessionTask *) task didCompleteWithError: (NSError *) error if (error == nil) NSLog (@ "Taak:% @ succesvol voltooid", taak); else NSLog (@ "Taak:% @ voltooid met fout:% @", taak, [error localizedDescription]); double progress = (double) task.countOfBytesReceived / (double) task.countOfBytesExpectedToReceive; dispatch_async (dispatch_get_main_queue (), ^ self.progressView.progress = progress;); self.downloadTask = nihil;
Ten slotte moet u de (ongeldig) URLSessionDidFinishEventsForBackgroundURLSession: sessie (NSURLSession *)
methode. Het vertelt de afgevaardigde dat alle berichten die in de wachtrij zijn geplaatst voor een sessie zijn afgeleverd. Het maakt uw AppDelegate
om een te lanceren UILocalNotification
. De methode die u moet gebruiken is:
- (void) URLSessionDidFinishEventsForBackgroundURLSession: (NSURLSession *) sessie AppDelegate * appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate]; if (appDelegate.backgroundSessionCompletionHandler) void (^ completionHandler) () = appDelegate.backgroundSessionCompletionHandler; appDelegate.backgroundSessionCompletionHandler = nil; completionHandler (); NSLog (@ "Alle taken zijn voltooid");
Er verschijnen verschillende fouten omdat u het AppDelegate.h nog niet in uw klas hebt geïmporteerd.
#import "AppDelegate.h"
Ga naar de AppDelegate.h
en voeg de twee volgende objecten toe:
@property (sterk, niet-atomisch) UIWindow * -venster; @property (kopie) void (^ backgroundSessionCompletionHandler) ();
In de AppDelegate.m
je zou de gedelegeerde methode moeten implementeren (ongeldige) toepassing: (UIApplication *) toepassing handleEventsForBackgroundURLSession: (NSString *) identifier completionHandler: (void (^) ()) completionHandler
. Het vertelt de deelnemer dat gebeurtenissen met betrekking tot een URL-sessie wachten om te worden verwerkt en roept een aangepaste methode op (presentNotification
) om de gebruiker op de hoogte te stellen wanneer het bestand volledig wordt gedownload. De volledige methode is:
- (ongeldige) toepassing: (UIApplication *) toepassing handleEventsForBackgroundURLSession: (NSString *) identifier completionHandler: (void (^) ()) completionHandler self.backgroundSessionCompletionHandler = completionHandler; // melding toevoegen [self presentNotification];
De presentNotification
methode gebruikt de UILocalNotification
klasse om een lokale melding te maken. Het creëert een geluid en gebruikt het badgesysteem voor die melding. Dit is de volledige methode:
-(void) presentNotification UILocalNotification * localNotification = [[UILocalNotification alloc] init]; localNotification.alertBody = @ "Download voltooid!"; localNotification.alertAction = @ "Download van achtergrondoverdracht!"; // Over geluid localNotification.soundName = UILocalNotificationDefaultSoundName; // verhoog het badgenummer van de toepassing plus 1 localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1; [[UIApplication sharedApplication] presentLocalNotificationNow: localNotification];
Trouwens, om de teller linksboven bij het App-pictogram opnieuw te starten, moet je de volgende regel toevoegen aan de (ongeldig) applicationDidBecomeActive: (UIApplication *) applicatie
methode in de AppDelegate
.
application.applicationIconBadgeNumber = 0;
De melding moet vergelijkbaar zijn met de volgende afbeelding:
Het is nu tijd voor Rennen
de app en test de achtergronddownload.
Aan het einde van deze zelfstudie zou je je achtergrondoverdrachtsdienst in iOS 7 moeten hebben voltooid. Je moet de achtergrondoverdrachtsdienst begrijpen en begrijpen hoe je deze kunt implementeren. Als je vragen hebt, laat ze dan achter in de commentaarsectie hieronder.