Bygg en iPad Reader for World of War

Denne opplæringen vil bruke Leaves open source-prosjektet for å bygge en enkel iPad-leser for Verdenskriget av H.G. Wells. Underveis tar vi en rask titt på koden som driver Leaves-prosjektet, drøfter implementeringsdetaljer og undersøker noen alternative alternativer for å oppnå en lignende effekt.

Om bladprosjektet

Blader er en åpen kildekode-iOS-komponent som simulerer en side som setter overgang mellom innholdsvisninger, omtrent som overgangen funnet i Apples offisielle iBooks-program. Prosjektet ble opprinnelig skrevet av Tom Brow og ble gjort tilgjengelig på GitHub, hvor det senere ble forked av Ole Begemann for å legge til støtte for flersidede layouter.

For å se Leaves-prosjektet i gang, ta en titt på følgende videodemo av prosjektet denne opplæringen vil lære deg å lage:

Selvfølgelig er sidenkrøllingseffekten vist ovenfor ikke unik for enten denne demoen eller iBooks-applikasjonen. Andre innfødte iOS-programmer (for eksempel Maps-appen) bruker også en lignende effekt. For full backstory om nøyaktig hvordan Apple oppnår dette i deres applikasjoner, og hvorfor iOS SDK-utviklere trenger å ty til en komponent som Leaves, sjekk ut "App Store-Safe Page Curl Animations" av Ole Begemann og "Apples iBooks Dynamic Page Curl" av Steven Troughton-Smith.

Vi kommer tilbake til noen av teorien bak Leaves-prosjektet senere, men la oss gå videre og hoppe inn i å skape vår Verdenskriget leser for å få en følelse av hvordan koden ser ut i handlingen.

Bygg WOTW PDF Reader

Trinn 1: Last ned prosjektressursene

Nedlastingsfilen som er vedlagt denne Mobiletuts + posten inneholder kildekoden Leaves og flere offentlige ressursressurser (inkludert Verdenskriget tekst) som brukes i prosjektet.

Trinn 2: Opprett et nytt Xcode-prosjekt

Åpne Xcode og opprett et nytt prosjekt ved hjelp av "View-based Application" -malen. Navngi prosjektet "WOTW" og velg "iPad" fra rullegardinen for enhetsfamilie.

Trinn 3: Legg prosjektressursene til Xcode

Dra og slipp følgende filer i gruppen "Støttende filer" i Xcode:

Alle de ovennevnte filene finnes i "Ressurser" -mappen til nedlastingen som er vedlagt denne opplæringen.

Deretter legger du til den faktiske bladskomponentkoden. Opprett en ny gruppe kalt "Leaves" under "WOTW" -mappen i Xcode-prosjektnavigatoren, og dra og slipp deretter de følgende filene i gruppen Leaves:

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

MERK: Pass på at du velger avkrysningsruten «Kopier elementer i destinasjonsgruppens mappe» når du legger til de ovennevnte filene.

Trinn 4: Koble QuartzCore Framework

Animasjonen laget av Leaves er avhengig av QuartzCore Framework. Derfor må du koble denne rammen mot prosjektet ditt for at Leaves skal kunne fungere. For å gjøre dette i Xcode 4, start ved å velge "WOTW" i Project Navigator. Deretter velger du "WOTW" mål og deretter "Build Phases" -fanen. Deretter utvider du "Link Binær Med Biblioteker", og klikker plussymbolet for å legge til et nytt rammeverk. Til slutt, velg "QuartzCore" fra listen over tilgjengelige rammer og klikk "Legg til". Resultatet av denne prosessen vises visuelt nedenfor:

Trinn 5: Underklasse LeavesViewController

For vårt prosjekt vil vi at leseren skal starte umiddelbart inn i Verdenskriget tekst uten landerside. For å gjøre dette må vi gjøre WOTWViewController klasse arve fra LeavesViewController klasse i stedet for direkte fra UIViewController. Gjør dette ved å åpne WOTWViewController.h og endre grensesnittdeklarasjonen til følgende:

 @interface WOTWViewController: LeavesViewController 

Linje 1 ovenfor endrer WOTWViewController å arve fra LeavesViewController i stedet for direkte fra UIViewController. Fordi LeavesViewController selv arver fra UIViewController, du kan tenke på WOTWViewController som barnebarn av UIViewController

Så, hva får vi for våre problemer? LeavesViewController samsvarer med Leaves datakilde og delegere protokoller (diskuteres senere) og definerer egendefinert -loadView og -viewDidLoad implementeringer som legger til en spesiell type UIView kalt a LeavesView til det nåværende visningshierarkiet. De LeavesView Klassen er ansvarlig for det meste av arbeidet bak sidenkrøllen.

Trinn 6: Legg til nødvendige importerklæringer

For å kunne WOTWViewController klasse for å kunne arve fra LeavesViewController klasse, må vi importere LeavesViewController kode. Legg til følgende to #importere linjer til WOTWViewController.h:

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

Lurer på hva det Utilities.h import erklæring er for? Som vi ser senere, er Leaves-prosjektet avhengig av en smart funksjon som er deklarert i den filen som heter aspectFit. Mange Kakao-Touch-prosjekter opprettholder en Utilities-klasse for å deklarere og definere hjelpekode som brukes i hele applikasjonen.

Trinn 7: Erklære WOTW-datamedlemmene

For nå trenger vi bare å erklære et enkelt datalid for vårt prosjekt. I WOTWViewController.h fil, legg til følgende linje med kode:

 CGPDFDocumentRef bookPDF;

Vi vil bruke "bookPDF" som en referanse til WOTW.pdf filen senere. De CGPDFDocumentRef variabel type vil bli brukt mye i denne opplæringen og er verdt ytterligere leting i den offisielle Apple-dokumentasjonen.

Trinn 8: Initialiser bladene

Når WOTWViewController er opprettet må vi initialisere bookPDF data medlem erklært ovenfor. Som vist i Leaves prøveprosjektet, kan du gjøre dette med følgende kodelinjer:

 - (id) init hvis (selv = [super init]) CFURLRef pdfURL = CFBundleCopyResourceURL (CFBundleGetMainBundle (), CFSTR ("WOTW.pdf"), NULL, NULL); bookPDF = CGPDFDocumentCreateWithURL ((CFURLRef) pdfURL); CFRelease (pdfURL);  returner selv; 

Ser du et problem med tilnærmingen ovenfor? Husk at vi skal laste inn visningskontrollen vår fra Interface Builder.

The Leaves-prøveprosjektet antar at du vil opprette en manuelt LeavesViewController eksempelvis programmert ved å ringe -(Id) init metode, slik som:

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

Men i prosjektet ønsker vi å unarchive the WOTWViewController fra vår Interface Builder NIB, så tilpasset -(Id) init funksjonen vi nettopp har implementert, vil aldri bli kalt. I stedet må vi gi en tilpasset implementering for -(Id) initWithCoder: metode for å plugge inn i NIB unarchive prosessen og utføre tilpasset initialisering. Det er godt å forlate i det på plass slik at du har muligheten til å opprette denne visningscontrolleren manuelt, men vi bør opprette en ny metode for PDF-initialisering og ringe den metoden fra begge -(Id) init og -(Id) initWithCoder:.

Legg til følgende linje med kode til WOTWViewController.h fil:

 -(Void) loadPDF;

Neste, bytt til WOTWViewController.m og implementer metoden som følger:

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

Til slutt, ring til loadPDF metode fra klassen initialiserer:

 - (id) init self = [super init]; hvis (selv) [self loadPDF];  returner selv;  - (id) initWithCoder: (NSCoder *) aDecoder self = [super initWithCoder: aDecoder]; hvis (selv) [self loadPDF];  returner selv; 

Når vår tilpassede visningskontroller ikke er arkivert, vil -(Id) initWithCoder: Metoden vil bli kalt og vil da ringe loadPDF metode.

Det er bare en ting til. Har tildelt minne for bookPDF referanse, vi bør også gi ut det minnet når vi er ferdige med det. Vi kan gjøre dette ved å legge til følgende linje med kode til -(Void) dealloc: metode:

 CGPDFDocumentRelease (bookPDF);

Trinn 9: Implement Leaves DataSource

Husk fra trinn 5 at LeavesViewController klassen legger automatisk til en forekomst av LeavesView klasse til visningshierarkiet. De LeavesView klassen må på en eller annen måte finne ut hvilket innhold som skal vises i visningen, og dette oppnås ved å ringe to tilpassede datakilde metoder: -(NSUInteger) numberOfPagesInLeavesView: og -(Void) renderPageAtIndex:.

For å gi en tilpasset implementering for disse, åpne WOTWViewController.m og legg til følgende kodelinjer:

 #pragma mark LeavesViewDataSource metoder - (NSUInteger) numberOfPagesInLeavesView: (LeavesView *) leavesView return CGPDFDocumentGetNumberOfPages (bookPDF);  - (void) renderPageAtIndex: (NSUInteger) indeks inContext: (CGContextRef) ctx CGPDFPageRef side = CGPDFDocumentGetPage (bookPDF, indeks + 1); CGAffineTransform transform = aspektFit (CGPDFPageGetBoxRect (side, kCGPDFMediaBox), CGContextGetClipBoundingBox (ctx)); CGContextConcatCTM (ctx, transform); CGContextDrawPDFPage (ctx, side); 

De -(NSUInteger) numberOfPagesInLeavesView: Metode angir bare hvor mange sider innholdet er LeavesViewController er ansvarlig for visning. Hvis du genererte innholdet for bladene manuelt, eller hvis du visste nøyaktig hvor mange sider som var i PDF-filen, kan du returnere dette nummeret manuelt her. Selvfølgelig er det alltid bedre å bestemme dette nummeret dynamisk, og det er akkurat det som CGPDFDocumentGetNumberOfPages () funksjon gjør.

De -(Void) renderPageAtIndex: incontext: Metoden er ansvarlig for å tegne en CGContextRef etter at du først har lagt inn PDF-innholdet i konteksten som er sendt inn som CTX.

Teste koden

Bygg og kjør prosjektet. Hvis alt går bra, bør du nå kunne se Verdenskriget bokomslag og kunne bla gjennom sidene med sidekranse animasjonen!

Finalen WOTWViewController.h filen skal se slik ut:

 #importere  #importere  #import "Utilities.h" #import "LeavesViewController.h" @interface WOTWViewController: LeavesViewController CGPDFDocumentRef bookPDF;  - (tom) loadPDF; @slutt

Og den endelige WOTWViewController.m filen skal leses som følger:

 #import "WOTWViewController.h" @implementation WOTWViewController #pragma mark - Initialisering / Memory Management - (id) init self = [super init]; hvis (selv) [self loadPDF];  returner selv;  - (id) initWithCoder: (NSCoder *) aDecoder self = [super initWithCoder: aDecoder]; hvis (selv) [self loadPDF];  returner selv;  - (ugyldig) 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 metoder - (NSUInteger) numberOfPagesInLeavesView: (LeavesView *) leavesView return CGPDFDocumentGetNumberOfPages (bookPDF);  - (void) renderPageAtIndex: (NSUInteger) indeks inContext: (CGContextRef) ctx CGPDFPageRef side = CGPDFDocumentGetPage (bookPDF, indeks + 1); CGAffineTransform transform = aspektFit (CGPDFPageGetBoxRect (side, kCGPDFMediaBox), CGContextGetClipBoundingBox (ctx)); CGContextConcatCTM (ctx, transform); CGContextDrawPDFPage (ctx, side);  @slutt

Alternativer til bladene

I min forskning på Leaves kom jeg over flere flere open source-prosjekter som legger til sideaktige overgangs animasjoner. Hvis du fant dette prosjektet interessant, bør du også sjekke ut:

  • FlipView - FlipBook som Animasjoner
  • HMGLTransitions - OpenGL Page Turns
  • Paperstack - OpenGL (Unreleased fra 8/30/2011 - Forhåpentligvis kommer snart!)

Legg igjen en kommentar nedenfor hvis du vil se en veiledning på ett av prosjektene ovenfor!

Vil du se mer?

Vi har gjort noen gode fremskritt i denne opplæringen. Vi kan nå samhandle med Verdenskriget PDF og siden curling animasjon legger til en stor estetisk følelse for eBok. Det er imidlertid fortsatt mye arbeid å gjøre før denne appen er klar for utgivelse på App Store. For eksempel ville det være bra om brukeren automatisk ble returnert til den siste siden de åpnet da appen lanseres, og det ville også være veldig hyggelig å ha en UISlider eller lignende grensesnittkomponent for raskt å hoppe over mellom deler av boken. Andre nyttige funksjoner kan omfatte søk, tekstutheving, innholdsfortegnelse eller bokmerker.

Jeg vil sørge for at mine iOS SDK-veiledninger dekker emner som Mobiletuts + -samfunnet er interessert i. Tror du at jeg skal bygge ut en fullverdig eReader og dele kildekoden min? Eller kanskje du vil se en opplæring om noe helt annet? Svar følgende meningsmåling og gi meg beskjed!

OPPDATERING 9/7/2011: Meningsmåling er nå stengt. Over 60% av respondentene uttrykte interesse for å se flere innlegg om å legge til en innholdsfortegnelse og / eller en UISlider og en opplæring med en UISlider har blitt publisert (Link Below).

Du kan også sende tilbakemelding til min Twitter-konto (@markhammonds), selv om jeg innrømmer at jeg vanligvis bare bruker Twitter når jeg ikke jobber med frilanseprosjekter eller skriver opplæringsprogrammer, så du vil kanskje bare kontakte meg via e-post i stedet.

Klikk her for å lese den andre delen av denne serien