Lucrul cu CorePlot Crearea unei diagrame

Când lucrați cu aplicații cu intensitate mare de date, un dezvoltator trebuie să facă deseori mai mult decât să arate liste de înregistrări de date într-o vizualizare de tabel. Biblioteca CorePlot vă va permite să adăugați vizualizări uimitoare de date la aplicațiile dvs. Aflați cum în această serie Tuts + Premium!


Disponibile și în această serie:

  1. Lucrul cu CorePlot: configurarea proiectului
  2. Lucrul cu CorePlot: Bazele fundamentale
  3. Lucrul cu CorePlot: Styling și Adding Plots
  4. Lucrul cu CorePlot: Crearea unui grafic de bare
  5. Lucrul cu CorePlot: Crearea unei diagrame

Unde am plecat

Ultima dată când am intrat în modul de a crea o diagramă de bare, cum să personalizăm culorile barei și cum să adăugăm etichete personalizate pe axa noastră, dacă vrem să afișăm text personalizat în locul numerelor.


Ce vom acoperi astăzi

De data aceasta vom acoperi cum să rezhem logica din controlorul nostru într-un obiect de date mai reutilizabil. Odată ce am reușit acest lucru, vom trece peste modul în care vom afișa aceleași date ca și diagrama de bare, cu excepția faptului că acest lucru este afișat ca o diagrama plăcintă!


Pasul 1: Configurarea

Înainte de a ajunge la abstractizarea logicii datelor, vom crea clase de bază pentru diagrama plăcilor. Ca și ultima oară, va trebui să creăm un nou controler de vizualizare pentru grafic. Să o numim "STPieGraphViewController".


Observați că nu este nevoie să creați o vizualizare de data aceasta, deoarece vom putea utiliza "STGraphView". Înainte de a începe să setăm lucrurile, hai să intrăm în STStudentListViewController.h și să importăm STPieGraphViewController.h. De asemenea, trebuie să ne conformăm protocolului STPieGraphViewControllerDelegate (pe care îl vom crea ulterior):

 @interface STStudentListViewController: UIViewController 

Treceți la fișierul .m. Trebuie să adăugăm un buton în foaia de acțiune. Localizați metoda graphButtonWasSelected:. Vom modifica textul al doilea buton și vom adăuga un al treilea:

 - (void) graphButtonWasSelected: (id) expeditor UIActionSheet * graphSelectionActionSheet = [[UIActionSheet alocare] initWithTitle: @ "Alegeți un delegat grafic": self cancelButtonTitle: @ "Cancel" destructiveButtonTitle: "Rezumatele obiectului - Bar", "Totaluri de subiecte - Pie", nil] autorelease]; [graphSelectionActionSheet showInView: [[UIApplication sharedApplication] cheieWindow]]; 

Acum, sariți în metoda ActionSheet: clickedButtonAtIndex: și adăugați o clauză pentru buttonIndex == 2:

 altfel dacă (buttonIndex == 2) STPieGraphViewController * graphVC = [[STPieGraphViewController alloc] init]; [graphVC setModalTransitionStyle: UIModalTransitionStyleFlipHorizontal]; [graphVC setModalPresentationStyle: UIModalPresentationFullScreen]; [graphVC setDelegate: auto]; [graphVC setManagedObjectContext: [self managedObjectContext]]; [auto prezentModalViewController: graphVC animat: DA]; [release graphVC]; 

Ca și ultima oară, va afișa câteva avertismente, deoarece STPieGraphViewController nu are o proprietate delegată sau managedObjectContext.

Deci, sari in STPieGraphViewController.h. Importați "CorePlot-CocoaTouch.h" și adăugați următoarele proprietăți și declarații de protocol:

 @ protocol STPieGraphViewControllerDelegate @ cerut - (void) doneButtonWasTapped: (id) expeditor; @end @interface STPieGraphViewController: UIViewController  @property (nonatomic, puternic) CPTGraph * grafic; @property (nonatomic, atribuie) id delega; @property (nonatomic, puternic) NSManagedObjectContext * managedObjectContext; @Sfârșit

Este important să subliniem că nu respectăm CPTPieChartDataSource de data aceasta. Acest lucru se datorează faptului că vom abstracționa logica datelor grafice din STBarGraphViewController într-o clasă separată de dateSource. Înainte să facem asta, să terminăm totul. În fișierul .m, importați "STGraphView.h", sintetizați proprietățile și implementați metoda dealloc.

În cele din urmă, configurați metodele loadView și viewDidLoad, cum ar fi cele de mai jos:

 - (void) încărcareView [super loadView]; [self setTitle: @ "Înscriere după subiect"]; [auto setView: [[[STGraphView alocare] initWithFrame: self.view.frame] autorelease]]; CPTTheme * defaultTheme = [CPTTheme temăNamed: kCPTPlainWhiteTheme]; [auto setGraph: (CPTGraph *) [defaultTheme newGraph]];  - (void) viewDidLoad [vizualizare superDidLoad]; STGraphView * graphView = (STGraphView *) [vizualizare de sine]; [[diagramulVizualizare graficăHostingView] setHostedGraph: [auto-grafic]]; // Permite utilizatorului să se întoarcă UINavigationItem * navigationItem = [[[UINavigationItem alin] initWithTitle: self.title] autorelease]; [navigationItem setHidesBackButton: YES]; UINavigationBar * navigationBar = [[[UINavigationBar alocare] initWithFrame: CGRectMake (0, 0, auto.view.frame.size.width, 44.0f)] autorelease]; [navigationBar pushNavigationItem: navigationItem animat: NU]; [self.view addSubview: navigationBar]; [navigationItem setRightBarButtonItem: [[UIBarButtonItem alocat] initWithTitle: @ Stilul "Done": UIBarButtonItemStyleDone target: [auto delegate] acțiune: @selector (doneButtonWasTapped :)] autorelease] animat: NO; 

Cele de mai sus ar trebui să fie familiare până acum. Deci, să ne uităm la abstractizarea logicii grafice într-o clasă separată.


Pasul 2: Separarea logicii grafice

Am scris deja logica pentru obținerea datelor pentru numărul total de elevi din toate subiectele; noi nu dorim să mai scriem din nou, din fericire nu trebuie. Toate protocoalele sursă de date pentru parcelele moștenite de la 'CPTPlotDataSource' și este acest protocol care conține numereOfRecordsForPlot: și numberForPlot: fieldEnum: methods recordIndex.

Creați o clasă numită "STAbstractSubjectDataSource.h" (moștenind din NSObject) într-un nou grup numit "DataSource" din grupul de tipărire. Pentru importul fișierului de antet "CorePlot-CocoaTouch.h" și puneți următoarele proprietăți și declarații de metodă:

 @interface STAbstractSubjectEnrollementDataSource: NSObject  @property (nonatomic, puternic) NSManagedObjectContext * managedObjectContext; - (id) initWithManagedObjectContext: (NSManagedObjectContext *) aManagedObjectContext; - (float) getTotalSubjects; - (float) getMaxEnrolled; - (NSArray *) getSubjectTitlesAsArray; @Sfârșit

Ne-am abonat la protocolul "CPTPlotDataSource". Creați o metodă init particulară care trece printr-un managedObjectContext, astfel încât obiectul să poată accesa stocul de date. În cele din urmă, există trei metode de ajutor care pot ajuta cu obținerea de informații despre subiecți și înscriere. Acestea sunt aceleași metode care există în prezent în STBarGraphViewController. Vom muta aceste și în metoda sursei de date.

În afară de metoda init, fișierul .m nu conține niciun cod nou pe care nu l-ați mai văzut până acum. Este doar o chestiune de a muta tot codul existent din STBarGraphViewController în obiectul dataSource. Metodele pe care trebuie să le mutați sunt:

  • (float) getTotalSubjects
  • (Float) getMaxEnrolled
  • (NSArray *) getSubjectTitlesAsArray
  • (NSUInteger) numberOfRecordsForPlot: (CPTPlot *) grafic
  • (NSNumber *) numărForPlot: (CPTPlot *) câmp complot: (NSUInteger) câmpEnum recordIndex: (NSUInteger) index

De asemenea, asigurați-vă că adăugați metoda init personalizată:

 - (id) initWithManagedObjectContext: (NSManagedObjectContext *) aManagedObjectContext auto = [super init]; dacă (auto) [auto setManagedObjectContext: aManagedObjectContext];  întoarce-te; 

Acum avem un obiect sursă de date care poate furniza datele de bază atât pentru placinta, cât și pentru schema de bare. Sursa de date abstractă nu ne dă tot ce avem nevoie, dar barFillForBarPlot: recordIndex nu poate fi implementat deoarece face parte din CPTBarPlotDataSource. Va trebui să extindem clasa abstractă la ceva specific pentru parcelele de bar.

Creați un obiect nou în grupul de surse de date numit "STBarGraphSubjectEnrollementDataSource" care extinde clasa noastră abstractă. În antetul se abonează la "CPTBarPlotDataSource:

 - (id) initWithManagedObjectContext: (NSManagedObjectContext *) aManagedObjectContext @interface STBarGraphSubjectEnrollementDataSource: STAbstractSubjectEnrollementDataSource 

Și în fișierul .m, implementați metoda barFillForBarPlot:

 #pragma marcaje - CPTBarPlotDataSource Metode - (CPTFill *) barFillForBarPlot: (CPTBarPlot *) barPlot recordIndex: (NSUInteger) index CPTColor * areaColor = zero; comutator (index) caz 0: areaColor = [CPTColor redColor]; pauză; cazul 1: areaColor = [CPTColor blueColor]; pauză; cazul 2: areaColor = [CPTColor orangeColor]; pauză; cazul 3: areaColor = [CPTColor greenColor]; pauză; implicit: areaColor = [CPTColor purpleColor]; pauză;  CPTFill * barFill = [CPTFill fillWithColor: areaColor]; return barFill; 

Acum mergeți înapoi la fișierul antet STBarGraphViewControllers și importați noua sursă de date grafice. Acum puteți elimina abonamentul "CPTBarPlotDataSource". Salt în fișierul .m și ștergeți toate metodele, cu excepția loadView, viewDidLoad și dealloc. Nu mai avem nevoie de ele.

Trebuie să păstrăm un pointer la sursa de date și apoi să eliberăm pointerul când vizualizarea se face cu ea. În interfața privată, declarați proprietatea și apoi sintetizați:

 @interface STBarGraphViewController () @property (nonatomic, reține) STBarGraphSubjectEnrollementDataSource * barGraphDataSource; @end @implementation STBarGraphViewController @synthesize delegat; @synthesize managedObjectContext; @integrază grafică; @synthesize barGraphDataSource;

Asigurați-vă că îl eliberați și în metoda dealloc. Creați o instanță nouă și setați-o ca proprietate în metoda loadView:

 [auto setBarGraphDataSource: [[[STBarGraphSubjectEnrollementDataSource alocare] initWithManagedObjectContext: [self managedObjectContext]] autorelease]];

Acum, în metoda viewDidLoad, trebuie să folosim metodele ajutorului sursei de date pentru calcularea spațiului de plotare și a etichetelor personalizate:

 CPTXYPlotSpace * studentPlotSpace = (CPTXYPlotSpace *) [grafic defaultPlotSpace]; [studentPlotSpace setXRange: [CPTPlotRange plotRangeWithLocation: CPTDecimalFromInt (0) lungime: CPTDecimalFromInt ([[self barGraphDataSource] getTotalSubjects] + 1)]]; [studentPlotSpace setYRange: [CPTPlotRange plotRangeWithLocation: CPTDecimalFromInt (0) lungime: CPTDecimalFromInt ([[auto barGraphDataSource] getMaxEnrolled] + 1)]];
 NSArray * subjectsArray = [[auto barGraphDataSource] getSubjectTitlesAsArray];

Salvați, construiți și executați. Totul ar trebui să funcționeze la fel ca înainte. Dacă se întâmplă, putem începe să ne creăm graficul de plăcintă!


Pasul 3: Crearea graficului de piept

Vom dori să creăm o sursă de date specifică pentru diagrama plăcilor, la fel cum am făcut pentru diagrama barei, în cazul în care trebuie să implementăm metode specifice sursei de date de tip pieptene. Creați o clasă numită "STPieGraphSubjectEnrollementDataSource" care moștenește din "STAbstractSubjectEnrollementDataSource". În fișierul antet, abonați la protocolul "CPTPieChartDataSource". Nu vom implementa metode sursă de date cu diagrame specifice, dar vom reveni la acestea mai târziu.

Acum, că avem surse de date, crearea graficului plăcilor este simplu! Săriți în STBPieGraphViewController.m și importați obiectul sursă de date de tip pieptene. Declarăți-o drept proprietate în fișierul .m, așa cum am făcut-o ultima oară:

 @interface STPieGraphViewController () @property (nonatomic, puternic) STPieGraphSubjectEnrollementDataSource * pieChartDataSource; @end @implementation STPieGraphViewController @synthesize managedObjectContext; @ delegați sintetizați; @integrază grafică; @synthesize pieChartDataSource;

Acum creați-l și setați-l în loadView:

 [auto setPieChartDataSource: [[[STPieGraphSubjectEnrollementDataSource alocare] initWithManagedObjectContext: [self managedObjectContext]] autorelease]];

În cele din urmă, în metoda viewDidLoad trebuie să creați diagrama plăcintă, să o adăugați la GraphView și să eliminați axa standard:

 STGraphView * graphView = (STGraphView *) [vizualizare de sine]; [[diagramulVizualizare graficăHostingView] setHostedGraph: [auto-grafic]]; CPTPieChart * pieChart = [[alocare CPTPieChart] initWithFrame: [limite de grafic]]; [pieChart setPieRadius: 100.00]; [pieChart setIdentifier: @ "Subject"]; [pieChart setStartAngle: M_PI_4]; [pieChart setSliceDirection: CPTPieDirectionCounterClockwise]; [pieChart setDataSource: pieChartDataSource]; [graf addPlot: pieChart]; [setAxisSet: graph zero]; [set setBorderLineStyle: zero];

Cele mai multe dintre cele de mai sus ar trebui să pară familiare. Observați că nu se numește în mod explicit un "complot", deoarece nu se bazează pe axa x sau axa y, dar încă o tratăm la fel. Există și niște lucruri specifice pe care le facem aici. Creăm o rază de plăcintă și un unghi de pornire. Am stabilit, de asemenea, o direcție felie. În cele din urmă am setat "axisSet" al graficului la zero, astfel încât să nu obținem liniile x și y.

Și ar trebui să fie totul. Construiți și rulați pentru a vedea diagrama plăcintă.


Acest lucru este bun, dar ar putea face cu un fel de indicație cu privire la ceea ce reprezintă fiecare culoare. O modalitate buna de a face acest lucru este de a folosi legende. Pentru a face acest lucru, vom crea un obiect "CPTLegend" pe care îl adăugăm în graficul nostru și vom implementa o metodă delegată care returnează titlul relevant pentru legenda.

Să creați mai întâi obiectul CPTLegend. În metoda noastră de vizualizareDidLoad introduceți următorul cod dedesubtul căruia creăm diagrama plăcintă:

 CPTLegend * theLegend = [Legenda CPTLegendWithGraph: [self graph]]; [Legend setNumberOfColumns: 2]; [[graful propriu] setLegend: theLegend]; [[graful propriu] setLegendAnchor: CPTRectAnchorBottom]; [[auto-graf] setLegendDisplacement: CGPointMake (0.0, 30.0)];

Aceasta creează o legendă și o adaugă obiectului nostru de grafic. Numărul de coloane determină modul în care vor fi prezentate titlurile legendelor. Apoi setăm câteva atribute pe obiectul grafic care determină locul în care va fi plasată legenda (partea de jos) și o anumită deplasare pentru a se asigura că aceasta se afișează pe deplin în vizualizare.

Totuși, trebuie să oferim legendei titluri. Există o metodă specifică pentru CPTPieChartDataSource care ne permite să facem acest lucru. Salt în sursa de date diagramă de tip pieptene și implementați următorul cod:

 Marca #pragma - CPTPieChartDataSource - (NSString *) legendTitleForPieChart: (CPTPieChart *) indexul pieChartIndex: (NSUInteger) index NSError * error = nil; NSFetchRequest * request = [[NSFetchRequest alocare] init]; NSEntityDescription * entity = [Entită NSEntityDescriptionForName: @ "STSubject" înManagedObjectContext: [self managedObjectContext]]; NSPredicate * predicate = [N predicție cu predicateWithFormat: @ "subjectID ==% d", index]; [request setEntity: entitate]; [request setResultType: NSDictionaryResultType]; [request setPredicate: predicate]; [request setReturnsDistinctResults: NU]; [cerere setPropertiesToFetch: [NSArray arrayWithObject: @ "subjectName"]]; NSArray * titleStrings = [[self managedObjectContext] executeFetchRequest: eroare cerere: & eroare]; NSDictionary * fetchedSubject = [titluStrings objectAtIndex: 0]; returnați [fetchedSubject objectForKey: @ "subjectName"]; 

Această metodă obține pur și simplu indicele legendei și primește titlul din magazinul de date ca un șir și o returnează.

Construiți și alergați și ar trebui să aveți un grafic plăcut informativ!



Învelire

Am descoperit cum să rezumăm logica datelor de la controler într-un obiect separat care este mai ușor de gestionat și extins. Am acoperit, de asemenea, elementele de bază ale creării unei scheme grafice.

Asta ne aduce la sfârșitul seriei. Sper că ați găsit aceste tutoriale utile. Există mult mai multe lucruri pe care CorePlot le poate face, dar acest lucru ar trebui să vă ofere o bază solidă pe care să o dezvoltați. Succesul adăugării de grafice la propriile proiecte!

Cod