Bouw een iPad-lezer voor War of the Worlds

Deze tutorial gebruikt het open-sourceproject Leaves om een ​​eenvoudige iPad-reader voor te bouwen De oorlog van de werelden door H.G. Wells. Onderweg zullen we snel de code bekijken die het Leaves-project aandrijft, implementatiedetails bespreken en enkele alternatieve opties verkennen om een ​​vergelijkbaar effect te bereiken..

Over het Leaves-project

Leaves is een open-source iOS-component die een overgang van het wisselen tussen pagina's tussen inhoudweergaven simuleert, net zoals de overgang die wordt gevonden in de officiële iBooks-app van Apple. Het project is oorspronkelijk geschreven door Tom Brow en beschikbaar gemaakt op GitHub, waar het later werd gevorkt door Ole Begemann om ondersteuning toe te voegen voor layouts met meerdere pagina's.

Als u het Leaves-project in actie wilt zien, bekijkt u de volgende videodemo van het project dat in deze zelfstudie wordt beschreven:

Natuurlijk is het hierboven getoonde curlingeffect niet uniek voor deze demo of de iBooks-applicatie. Andere native iOS-applicaties (zoals de Maps-app) gebruiken ook een vergelijkbaar effect. Voor het volledige achtergrondverhaal over precies hoe Apple dit in hun toepassingen bereikt en waarom iOS SDK-ontwikkelaars hun toevlucht moeten nemen tot een component zoals Leaves, bekijk dan "App Store-Safe Page Curl Animations" van Ole Begemann en "Apple's iBooks Dynamic Page Curl" door Steven Troughton-Smith.

We komen later terug bij een deel van de theorie achter het Leaves-project, maar laten we doorgaan en ons inspannen om ons te creëren War of the Worlds lezer om een ​​idee te krijgen van hoe de code eruitziet in actie.

De WOTW PDF Reader bouwen

Stap 1: download de projectbronnen

Het downloadbestand dat is gekoppeld aan deze Mobiletuts + post bevat de Leaves-broncode en verschillende bronnen van het publieke domein (inclusief de War of the Worlds tekst) gebruikt in het project.

Stap 2: Maak een nieuw Xcode-project

Open Xcode en maak een nieuw project met behulp van de sjabloon "View-based Application". Noem het project "WOTW" en selecteer "iPad" uit de vervolgkeuzelijst apparaatfamilie.

Stap 3: voeg de projectresources toe aan Xcode

Sleep de volgende bestanden naar de groep "Ondersteunende bestanden" in Xcode:

Alle bovenstaande bestanden zijn te vinden in de map "Bronnen" van de download die bij deze zelfstudie is gevoegd.

Voeg vervolgens de daadwerkelijke componentcode van Leaves toe. Maak een nieuwe groep met de naam "Bladeren" onder de map "WOTW" in de Xcode project-navigator en sleep vervolgens de volgende bestanden naar de groep Bladeren:

  • Utilities.h
  • Utilities.m
  • LeavesCache.h
  • LeavesCache.m
  • LeavesView.h
  • LeavesView.m
  • LeavesViewController.h
  • LeavesViewController.m

OPMERKING: Zorg ervoor dat u het selectievakje "Items naar de doelmap kopiëren" aanvinkt bij het toevoegen van de bovenstaande bestanden.

Stap 4: Koppel het QuartzCore-framework

De animatie gemaakt door Leaves is afhankelijk van het QuartzCore Framework. Daarom moet u dit raamwerk koppelen aan uw project zodat Leaves kan werken. Om dit in Xcode 4 te doen, selecteert u eerst "WOTW" in de Projectnavigator. Selecteer vervolgens het doelwit "WOTW" en vervolgens het tabblad "Fasen opbouwen". Breid vervolgens het dialoogvenster "Binaire bibliotheken koppelen" uit en klik op het plusteken om een ​​nieuw kader toe te voegen. Selecteer ten slotte "QuartzCore" in de lijst met beschikbare frameworks en klik op "Toevoegen". Het resultaat van dit proces wordt hieronder visueel weergegeven:

Stap 5: Subklasse LeavesViewController

Voor ons project willen we dat de lezer meteen in de War of the Worlds tekst zonder lander-pagina. Om dit te doen, moeten we het WOTWViewController klasse erven van de LeavesViewController klasse in plaats van direct van UIViewController. Doe dit door te openen WOTWViewController.h en het aanpassen van de interface-verklaring aan het volgende:

 @interface WOTWViewController: LeavesViewController 

Lijn 1 hierboven wijzigt WOTWViewController erven van LeavesViewController in plaats van direct van UIViewController. Omdat LeavesViewController zelf erft van UIViewController, je kunt denken aan de WOTWViewController als het kleinkind van UIViewController

Wat krijgen we voor onze problemen?? LeavesViewController conformeert aan de Leaves-gegevensbron en delegatieprotocollen (later besproken) en definieert gebruikelijk -loadView en -viewDidLoad implementaties die een speciaal soort toevoegen UIView genaamd a LeavesView naar de huidige weergavehiërarchie. De LeavesView klas is verantwoordelijk voor het grootste deel van het werk achter de pagina curl-animatie.

Stap 6: voeg de noodzakelijke importstatements toe

Om voor de WOTWViewController klasse om van de te erven LeavesViewController klasse, we moeten het importeren LeavesViewController code. Voeg de volgende twee toe #importeren lijnen naar WOTWViewController.h:

 #import "Utilities.h" #import "LeavesViewController.h"

Vraagt ​​u zich af wat dat is Utilities.h import statement is voor? Zoals we later zullen zien, vertrouwt het Leaves-project op een slimme functie die in dat bestand wordt genoemd aspectFit. Veel Cocoa-Touch-projecten onderhouden een Utilities-klasse om helpercode te declareren en te definiëren die in de hele applicatie wordt gebruikt.

Stap 7: Declareer de WOTW-gegevensleden

Voor nu hoeven we slechts één lid van de gegevens voor ons project te verklaren. In de WOTWViewController.h bestand, voeg de volgende regel code toe:

 CGPDFDocumentRef bookPDF;

We zullen "bookPDF" gebruiken als een verwijzing naar de WOTW.pdf bestand later. De CGPDFDocumentRef variabele type zal in deze tutorial uitgebreid worden gebruikt en is de moeite waard om verder te verkennen in de officiële Apple-documentatie.

Stap 8: Bladeren initialiseren

Wanneer de WOTWViewController is gemaakt, we moeten de bookPDF gegevenslid hierboven verklaard. Zoals aangetoond in het voorbeeldproject Bladeren, kunt u dit doen met de volgende coderegels:

 - (id) init if (self = [super init]) CFURLRef pdfURL = CFBundleCopyResourceURL (CFBundleGetMainBundle (), CFSTR ("WOTW.pdf"), NULL, NULL); bookPDF = CGPDFDocumentCreateWithURL ((CFURLRef) pdfURL); CFRelease (pdfURL);  terugkeer zelf; 

Zie je een probleem met de bovenstaande aanpak? Vergeet niet dat we onze view-controller vanuit Interface Builder gaan laden.

Het Leaves-voorbeeldproject gaat ervan uit dat u handmatig een LeavesViewController bijvoorbeeld programmatisch door de -(Id) init methode, zoals zo:

 WOTWViewController * viewController = [[[WOTWViewController alloc] init];

In ons project willen we echter de archivering ongedaan maken WOTWViewController van onze Interface Builder NIB, dus de gewoonte -(Id) init functie die we zojuist geïmplementeerd hebben, zal nooit worden gebeld. In plaats daarvan moeten we een aangepaste implementatie voor de -(Id) initWithCoder: methode om in te pluggen in het NIB-unarchive-proces en aangepaste initialisatie uit te voeren. Het is goed om de in het op zijn plaats, zodat je de mogelijkheid hebt om deze view controller handmatig aan te maken, maar we zouden een nieuwe methode voor PDF-initialisatie moeten maken en die methode vanuit beide -(Id) init en -(Id) initWithCoder:.

Voeg de volgende regel code toe aan de WOTWViewController.h het dossier:

 -(Void) loadPDF;

Ga vervolgens naar WOTWViewController.m en implementeer de methode als volgt:

 -(void) loadPDF CFURLRef pdfURL = CFBundleCopyResourceURL (CFBundleGetMainBundle (), CFSTR ("WOTW.pdf"), NULL, NULL); bookPDF = CGPDFDocumentCreateWithURL ((CFURLRef) pdfURL); CFRelease (pdfURL); 

Tot slot belt u de loadPDF methode van de klasse-initializers:

 - (id) init self = [super init]; if (self) [self loadPDF];  terugkeer zelf;  - (id) initWithCoder: (NSCoder *) aDecoder self = [super initWithCoder: aDecoder]; if (self) [self loadPDF];  terugkeer zelf; 

Wanneer onze aangepaste weergavecontroller uit archief wordt verwijderd, wordt de -(Id) initWithCoder: methode zal worden aangeroepen en zal dan de loadPDF methode.

Er is nog één ding. Geheugen toegewezen hebben voor de bookPDF referentie, we moeten die herinnering ook vrijgeven als we er klaar mee zijn. We kunnen dit doen door de volgende regel code toe te voegen aan de -(Void) dealloc: methode:

 CGPDFDocumentRelease (bookPDF);

Stap 9: Implementeer de Leaves DataSource

Herinner uit Stap 5 dat de LeavesViewController klasse voegt automatisch een exemplaar van de LeavesView klasse aan de weergavehiërarchie. De LeavesView Klasse moet op de een of andere manier achterhalen welke inhoud in de weergave moet worden weergegeven, en dit wordt bereikt door twee aangepaste gegevensbronmethoden aan te roepen: -(NSUInteger) numberOfPagesInLeavesView: en -(Void) renderPageAtIndex:.

Om een ​​aangepaste implementatie voor deze te bieden, open WOTWViewController.m en voeg de volgende regels toe:

 #pragma mark LeavesViewDataSource-methoden - (NSUInteger) numberOfPagesInLeavesView: (LeavesView *) leavesView return CGPDFDocumentGetNumberOfPages (bookPDF);  - (void) renderPageAtIndex: (NSUInteger) index inContext: (CGContextRef) ctx CGPDFPageRef page = CGPDFDocumentGetPage (bookPDF, index + 1); CGAffineTransform transform = aspectFit (CGPDFPageGetBoxRect (pagina, kCGPDFMediaBox), CGContextGetClipBoundingBox (ctx)); CGContextConcatCTM (ctx, transform); CGContextDrawPDFPage (ctx, pagina); 

De -(NSUInteger) numberOfPagesInLeavesView: methode geeft eenvoudig aan hoeveel pagina's inhoud de LeavesViewController is verantwoordelijk voor de weergave. Als u de inhoud voor Leaves handmatig aan het genereren was of als u precies wist hoeveel pagina's in de PDF stonden, kunt u dat nummer hier handmatig teruggeven. Het is natuurlijk altijd beter om dat aantal dynamisch te bepalen, en dat is precies wat de CGPDFDocumentGetNumberOfPages () functie doet.

De -(Void) renderPageAtIndex: InContext: methode is verantwoordelijk voor het daadwerkelijk tekenen van een CGContextRef na het eerst toevoegen van de PDF-inhoud in de context die is doorgegeven als ctx.

De code testen

Bouw en run het project. Als alles goed gaat, zou je nu het. Moeten kunnen zien War of the Worlds boekomslag en blader door de pagina's met de pagina curl-animatie!

De laatste WOTWViewController.h bestand zou er als volgt uit moeten zien:

 #importeren  #importeren  #import "Utilities.h" #import "LeavesViewController.h" @interface WOTWViewController: LeavesViewController CGPDFDocumentRef bookPDF;  - (void) loadPDF; @einde

En de finale WOTWViewController.m bestand moet als volgt gelezen worden:

 #import "WOTWViewController.h" @implementation WOTWViewController #pragma-markering - Initialisatie / Geheugenbeheer - (id) init self = [super init]; if (self) [self loadPDF];  terugkeer zelf;  - (id) initWithCoder: (NSCoder *) aDecoder self = [super initWithCoder: aDecoder]; if (self) [self loadPDF];  terugkeer zelf;  - (void) loadPDF CFURLRef pdfURL = CFBundleCopyResourceURL (CFBundleGetMainBundle (), CFSTR ("WOTW.pdf"), NULL, NULL); bookPDF = CGPDFDocumentCreateWithURL ((CFURLRef) pdfURL); CFRelease (pdfURL);  - (void) dealloc CGPDFDocumentRelease (bookPDF); [super dealloc];  #pragma mark - LeavesViewDataSource-methoden - (NSUInteger) numberOfPagesInLeavesView: (LeavesView *) leavesView return CGPDFDocumentGetNumberOfPages (bookPDF);  - (void) renderPageAtIndex: (NSUInteger) index inContext: (CGContextRef) ctx CGPDFPageRef page = CGPDFDocumentGetPage (bookPDF, index + 1); CGAffineTransform transform = aspectFit (CGPDFPageGetBoxRect (pagina, kCGPDFMediaBox), CGContextGetClipBoundingBox (ctx)); CGContextConcatCTM (ctx, transform); CGContextDrawPDFPage (ctx, pagina);  @end

Alternatieven voor bladeren

In mijn onderzoek naar Leaves kwam ik verschillende extra open-sourceprojecten tegen die pagina-achtige overgangsanimaties toevoegen. Als u dit project interessant vond, kijk dan ook eens naar:

  • FlipView - FlipBook-achtige animaties
  • HMGLTransitions - OpenGL Page Turns
  • Paperstack - OpenGL (onuitgegeven per 30-08-2011 - hopelijk binnenkort verkrijgbaar!)

Laat hieronder een opmerking achter als je een tutorial over een van de bovenstaande projecten wilt bekijken!

Wil je meer zien?

We hebben goede vooruitgang geboekt in deze zelfstudie. We kunnen nu communiceren met de War of the Worlds PDF en de pagina-curling-animatie voegen een fantastisch esthetisch gevoel toe aan het eBook. Er is echter nog veel werk aan de winkel voordat deze app klaar zou zijn voor uitgave in de App Store. Het zou bijvoorbeeld geweldig zijn als de gebruiker automatisch terugkeert naar de laatste pagina die ze hebben geopend toen de app werd gestart en het zou ook heel leuk zijn om een UISlider of een vergelijkbare interfacecomponent om snel tussen de secties van het boek te springen. Andere handige functies kunnen zoeken, tekstmarkering, een inhoudsopgave of bladwijzers zijn.

Ik wil ervoor zorgen dat mijn iOS SDK-zelfstudies onderwerpen behandelen waar de Mobiletuts + -community in geïnteresseerd is. Denk je dat ik een volwaardige eReader moet uitbouwen en mijn broncode moet delen? Of wil je misschien een tutorial over iets heel anders? Beantwoord de volgende poll en laat het me weten!

UPDATE 9/7/2011: de peiling is nu gesloten. Meer dan 60% van de respondenten heeft aangegeven geïnteresseerd te zijn in het zien van meer berichten over het toevoegen van een inhoudsopgave en / of een UISlider en een tutorial met een UISlider is gepubliceerd (Link Below).

Je kunt ook je feedback naar mijn Twitter (@markhammonds) -account verzenden, hoewel ik toegeef dat ik normaal gesproken alleen Twitter gebruik wanneer ik niet aan freelance-projecten of zelfstudielessen werk, dus misschien wil je gewoon contact met me opnemen via e-mail.

Klik hier om het tweede deel van deze serie te lezen