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.
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.
Nedlastingsfilen som er vedlagt denne Mobiletuts + posten inneholder kildekoden Leaves og flere offentlige ressursressurser (inkludert Verdenskriget tekst) som brukes i prosjektet.
Åpne Xcode og opprett et nytt prosjekt ved hjelp av "View-based Application" -malen. Navngi prosjektet "WOTW" og velg "iPad" fra rullegardinen for enhetsfamilie.
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:
MERK: Pass på at du velger avkrysningsruten «Kopier elementer i destinasjonsgruppens mappe» når du legger til de ovennevnte filene.
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:
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.
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.
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.
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);
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
.
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
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:
Legg igjen en kommentar nedenfor hvis du vil se en veiledning på ett av prosjektene ovenfor!
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.