Bij het werken met gegevensintensieve toepassingen moet een ontwikkelaar vaak meer doen dan alleen lijsten met gegevensrecords weergeven in een tabelweergave. Met de CorePlot-bibliotheek kunt u verbluffende gegevensvisualisaties toevoegen aan uw toepassingen. Ontdek hoe in deze Tuts + Premium-serie!
De laatste keer hebben we het CorePlot-framework geïntroduceerd en besproken wat het kan doen en hoe we het kunnen gebruiken om datavisualisatie in onze applicaties te verbeteren. We hebben ook de voorbeeldtoepassing onderzocht die we in de serie gaan maken en hoe we CorePlot aan onze toepassing kunnen toevoegen. Download de broncode voor deze tutorial voor een code-snapshot van waar we de vorige keer waren gebleven (anders kunt u uw bestaande codebasis gebruiken en uzelf de downloadtijd besparen!).
Voordat we een grafiek kunnen maken, hebben we een weergave nodig om dit te doen. We gaan toestaan dat de gebruiker klikt op een UIBarButtonItem op het tabblad 'Leerlingen'. Hierin wordt een actielijst geopend met een lijst met grafieken voor de gebruiker om te kiezen. Nadat een selectie is gemaakt, geeft een modale weergave een grafiek weer met de relevante gegevens erop.
We gaan een nieuwe groep maken onder de naam 'Graphing' onder de groep 'StudentTracker'. Maak daaronder een 'Views' en 'Controllers' groep zoals in de 'Student Listing' en 'Subject Listing'.
Maak een nieuwe klasse met de naam 'STLineGraphViewController' (subklasse van UIViewController) in de groep 'View Controllers'. Wanneer u kiest waar u de bestanden wilt toevoegen, is de map 'Classes / Graphing / View Controllers' de beste plaats om ze te plaatsen (u moet de map 'Graphing / View Controllers' maken).
We komen terug en werken eraan dit later aan te passen. Op dit moment gaan we die code implementeren waarmee de gebruiker een grafiek kan selecteren om naar te kijken.
Open eerst STStudentListViewController.h en voeg de protocolverklaringen 'UIActionSheetDelegate' en 'STLineGraphViewControllerDelegate' toe. Dit protocol bestaat nog niet, maar we zullen het later maken (Zorg er ook voor dat u het bestand 'STLineGraphViewController.h' importeert).
@interface STStudentListViewController: UIViewController
Open vervolgens het .m-bestand en voer de methode 'actionSheet: clickedButtonAtIndex:' uit met de volgende code:
- (void) actionSheet: (UIActionSheet *) actionSheet clickedButtonAtIndex: (NSInteger) knopIndex if (buttonIndex == 0) STLineGraphViewController * lineGraphVC = [[STLineGraphViewController alloc] init]; [lineGraphVC setModalTransitionStyle: UIModalTransitionStyleFlipHorizontal]; [lineGraphVC setDelegate: self]; [lineGraphVC setManagedObjectContext: [self managedObjectContext]]; [self presentModalViewController: lineGraphVC geanimeerd: YES]; [lineGraphVC-release];
Deze code hoeft niet al te veel uitleg nodig te hebben. We zijn gewoon een LineGraph View Controller aan het maken en presenteren deze modaal. We hebben onszelf als afgevaardigde geplaatst, zodat we weten wanneer we de modale kijk moeten afwijzen. We geven de view controller ook een beheerde objectcontext om mee te werken, zodat deze kan worden gekoppeld aan kerngegevens. Deze laatste twee methoden maken een waarschuwing (of foutmelding bij gebruik van ARC) omdat de eigenschappen nog niet bestaan, maar we ze later zullen maken.
Vervolgens maken we een methode om de actielijst te bellen en een UITabBarItem toe te voegen om dit te bellen. Voeg een methode declaratie toe in de .m interface genaamd 'graphButtonWasSelected:':
@interface STStudentListViewController () @property (nonatomic, strong) NSArray * studentArray; - (void) addStudent: (id) afzender; - (void) graphButtonWasSelected: (id) afzender; @einde
Voeg vervolgens de methode-implementatie toe:
- (void) graphButtonWasSelected: (id) afzender UIActionSheet * graphSelectionActionSheet = [[[UIActionSheet alloc] initWithTitle: @ "Kies een grafiek" delegate: self cancelButtonTitle: @ "Cancel" destructiveButtonTitle: nil otherButtonTitles: @ "Enrollment in time", nihil ] autorelease]; [graphSelectionActionSheet showInView: [[UIApplication sharedApplication] keyWindow]];
Vervolgens moeten we een UIBarButtonItem toevoegen aan de gebruiker om te selecteren wanneer ze de grafiek willen bekijken. We doen dit in de viewDidLoad-methode waaronder we het juiste item in de knoppenbalk maken:
[[self navigationItem] setLeftBarButtonItem: [[[UIBarButtonItem alloc] initWithTitle: @ "Graphs" -stijl: UIBarButtonItemStylePlain-doel: zelfactie: @selector (graphButtonWasSelected :)] autorelease] geanimeerd: NO];
Ten slotte moeten we een STLineGraphViewController-protocolmethode implementeren die de controller zal vertellen de modale weergave te sluiten wanneer de gebruiker klaar is met het bekijken van de grafiek:
- (void) doneButtonWasTapped: (id) afzender [self dismissModalViewControllerAnimated: YES];
Nu zijn we klaar om te beginnen met het maken van de grafiek!
Eerst moeten we een aangepaste weergaveklasse maken voor onze LineGraphViewController. Maak in de groep Graphing> Views een nieuwe klasse die UIView uitbreidt met de naam 'STLineGraphView' (zorg ervoor dat u deze in de juiste map plaatst wanneer u kiest waar het bestand in het bestandssysteem wordt opgeslagen).
We gaan de grafische aspecten van de weergave in de viewklasse instellen. Ga eerst naar het .h-bestand en (na het importeren van het bestand "CorePlot-CocoaTouch.h") en voeg de volgende eigenschapverklaring toe:
@property (nonatomic, strong) CPTGraphHostingView * chartHostingView;
De CPTGraphHostingView is eenvoudigweg een UIView die verantwoordelijk is voor het bevatten van de grafiek en het toestaan van gebruikersinteractie (die we in een later zelfstudie bespreken).
Maak de ChartHostingView samen en maak de weergave van de charthost aan in de methode initWithFrame:
[self setChartHostingView: [[[CPTGraphHostingView alloc] initWithFrame: CGRectZero] autorelease]]; [self addSubview: chartHostingView];
Het bovenstaande moet redelijk zelfverklarend zijn. We maken een CPTGraphHostingView en stellen deze in als onze eigenschap chartHostingVIew. We voegen het vervolgens toe als een subweergave.
Vervolgens moeten we de grafiekframe-dimensies instellen in de 'layout subviews'-methode:
[super layoutSubviews]; float chartHeight = self.frame.size.height - 40; float chartWidth = self.frame.size.width; [[self chartHostingView] setFrame: CGRectMake (0, 0, chartWidth, chartHeight)]; [[self chartHostingView] setCenter: [zelfcentreren]];
Nogmaals, al het bovenstaande zou eenvoudig dingen moeten zijn. Voordat we aan de controller gaan werken, moet je de eigenschap 'chartHostingView' vrijgeven in de methode dealloc-weergaven als je dit nog niet hebt gedaan.
Het meeste werk dat we nu gaan doen, zit in de controller. Open STLineGraphViewController.h en voeg de volgende eigenschapsverklaringen toe:
@interface STLineGraphViewController: UIViewController@property (nonatomic, strong) CPTGraph * grafiek; @property (nonatomic, assign) id delegeren; @property (nonatomic, strong) NSManagedObjectContext * managedObjectContext;
De CPTGraph is een abstracte klasse die verantwoordelijk is voor het tekenen van de grafiekelementen en het beheren van de verschillende plots. Het is ook verantwoordelijk voor het toepassen van thema's, het opnieuw laden van de grafiekgegevens en nog veel meer! We geven ook aan dat we ons houden aan de protocollen CPTScatterPlotDataSource en CPTScatterPlotDelegate.
We moeten ook een eigen protocol toevoegen zodat de modale weergave kan worden verworpen. Plaats de volgende code boven de interface-aangifte:
@protocol STLineGraphViewControllerDelegate @required - (void) doneButtonWasTapped: (id) afzender; @einde
Schakel over naar het * .m-bestand en synthetiseer de grafiek en delegeer eigenschappen. Zodra dit is gebeurd, voegt u de volgende code toe vóór de methode 'viewDidLoad':
[self setView: [[[STLineGraphView alloc] initWithFrame: self.view.frame] autorelease]]; CPTTheme * defaultTheme = [CPTTheme themeNamed: kCPTPlainWhiteTheme]; [self setGraph: (CPTGraph *) [defaultTheme newGraph]]; [defaultTheme release];
Er zijn een paar dingen aan de hand in dit gedeelte. Eerst maken en stellen we de weergave van de controller in als onze aangepaste STLineGraphView. Vervolgens maken we een 'CPTTheme'-object. Het CPTTheme-object beheert de stijl van een grafiek met lijnstijlen, tekststijl en eventuele vullingen die nodig zijn. Een eenvoudige manier om een CPTGraph te krijgen die vooraf is geconfigureerd met een basis-CPTTheme, is om het CPTTheme te maken met een van de vooraf gedefinieerde themanamen en vervolgens de methode 'newGraph' te gebruiken om ons een grafiek te geven die daarmee is gestileerd.
Vervolgens gaan we de volgende code in de 'viewDidLoad'-methode plaatsen:
[super viewDidLoad]; STLineGraphView * graphView = (STLineGraphView *) [zelfweergave]; [[zelfgrafiek] setDelegate: self]; [[graphView chartHostingView] setHostedGraph: [zelfgrafiek]]; CPTScatterPlot * studentScatterPlot = [[CPTScatterPlot alloc] initWithFrame: [graph bounds]]; [studentScatterPlot setIdentifier: @ "studentEnrollment"]; [studentScatterPlot setDelegate: self]; [studentScatterPlot setDataSource: self]; [[zelfgrafiek] addPlot: studentScatterPlot]; UINavigationItem * navigationItem = [[UINavigationItem alloc] initWithTitle: self.title]; [navigationItem setHidesBackButton: YES]; UINavigationBar * navigationBar = [[[UINavigationBar alloc] initWithFrame: CGRectMake (0, 0, self.view.frame.size.width, 44.0f)] autorelease]; [navigationBar pushNavigationItem: navigationItem animated: NO]; [self.view addSubview: navigationBar]; [navigationItem setRightBarButtonItem: [[[UIBarButtonItem alloc] initWithTitle: @ "Gereed" stijl: UIBarButtonItemStyleDone target: [self delegate] actie: @selector (doneButtonWasTapped :)] autorelease] geanimeerd: NO];
In de bovenstaande code krijgen we onze weergave en stellen we de gehoste grafiek in voor de hostingweergave van de weergavenkaart voor ons grafiekobject. We maken vervolgens een 'plot' om in de grafiek te zetten. We gebruiken de 'CPTScatterPlot' wanneer we een lijngrafiek willen maken. De identifier is iets dat we later kunnen gebruiken om de plot te identificeren. Vervolgens stellen we de gedelegeerde en gegevensbron in op de controllerklasse, omdat deze verantwoordelijk is voor het leveren van de gegevens voor de grafiek. Ten slotte voegen we de nieuw gemaakte plot van de grafiek toe.
Nadat we met de grafiek hebben gewerkt, maken we een navigatie-item en -balk voor de modale weergavecontroller om een titel en een voltooide knop weer te geven waarmee ze teruggaan naar de oorspronkelijke weergave.
Probeer nu het project uit te voeren en naar de lijngrafiek te gaan. Je zou iets als het volgende moeten zien:
We hebben het begin van een grafiek! Nu om wat gegevens toe te voegen:
Percelen in CorePlot gebruiken twee belangrijke gegevensbronmethoden voor het verkrijgen van gegevens, 'numberOfRecordsForPlot' en 'numberForPlot: field: recordIndex:'. Het lijkt erg op hoe tabelweergaven werken. Eerst willen we het aantal records voor de plot specificeren:
- (NSUInteger) numberOfRecordsForPlot: (CPTPlot *) plot return 8;
We laten zien hoeveel inschrijvingen er op elke dag van de week hebben plaatsgevonden. Aangezien er 7 mogelijke dagen zijn waarop de student zich had kunnen inschrijven, hebben we 8 totale records (omdat we beginnen met 0).
Nu willen we specificeren wat de x- en y-waarde moet zijn voor elke record:
- (NSNumber *) numberForPlot: (CPTPlot *) plotveld: (NSUInteger) fieldEnum recordIndex: (NSUInteger) index NSUInteger x = index; NSUInteger y = 0; NSError * -fout; NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription * entity = [NSEntityDescription entityForName: @ "STStudent" inManagedObjectContext: managedObjectContext]; NSPredicate * predicate = [NSPredicate predicateWithFormat: @ "dayEnled ==% d", index]; [fetchRequest setEntity: entity]; [fetchRequest setPredicate: predicate]; y = [managedObjectContext countForFetchRequest: fetchRequest error: & error]; [fetchRequest-release]; switch (fieldEnum) case CPTScatterPlotFieldX: NSLog (@ "x waarde voor% d is% d", index, x); return [NSNumber numberWithInt: x]; breken; case CPTScatterPlotFieldY: NSLog (@ "y-waarde voor% d is% d", index, y); return [NSNumber numberWithInt: y]; breken; standaard: pauze; terug nul;
Er is redelijk wat te beleven hierboven. Deze methode moet een x- en y-waarde voor een gegeven index specificeren en welke waarde retourneert is gebaseerd op de 'fieldEnum'-waarde (die in ons geval ofwel CPTScatterPlotFieldX of CPTScatterPlotFieldY is). De index geeft de record aan die het gaat plotten in de grafiek en de plot verwijst naar de eigenlijke plot die de gegevens weergeeft. Wanneer we een controller hebben die meer dan één plot beheert, kunnen we naar de plot-ID kijken om te bepalen welke set gegevens moet worden geleverd (we behandelen dit proces in een later zelfstudie).
Ik vind het het gemakkelijkst om een 'x' en 'y' waarde aan het begin van de methode op te geven, beide waarden uit te werken, en vervolgens op basis van het veldentum de juiste terug te sturen in de vorm van een NSNumber (het formaat dat corePlot vereist het in).
De x-waarde is eenvoudig te achterhalen. Omdat de dagen van inschrijving worden weergegeven, is x gelijk aan de huidige index. De y-waarde wordt een telling van alle studenten die op die dag zijn ingeschreven. We kunnen dit krijgen door te bellen naar onze kerngegevensopslag en alle STStudent-records te zoeken met een 'dayEnled'-waarde van de index. Als u niet vertrouwd bent met kerngegevens en niet begrijpt wat er allemaal gebeurt, wees dan niet te bezorgd, want nu is het goed dat het werkt. Concentreer u op één ding tegelijk leren!
Als u nu uw toepassing opslaat en uitvoert, ziet u nog steeds niets in de grafiek, maar ziet u de volgende uitvoer in uw console:
Dit betekent dat de grafiek de juiste waarden krijgt voor x en y (zorg ervoor dat deze gelijk is aan of vergelijkbaar is met de uitvoer in de afbeelding.) Het wordt echter nog steeds niet in de grafiek weergegeven. Dat komt omdat als u naar de grafiek kijkt, de het weergegeven bereik is onjuist. We kijken naar -1.0 tot 0 op zowel de x- als de y-as. We moeten het bereik instellen dat we moeten bekijken voordat we de gegevenspunten kunnen zien.
De plotruimte bepaalt veel over hoe de grafiek wordt bekeken en geformatteerd. In deze tutorial behandelen we een klein beetje en in de volgende gaan we dieper in op details.
Om het x- en y-bereik in te stellen waar de gebruiker naar kijkt, moeten we werken met het object 'CPTXYPlotSpace'. Met dit object kunnen we een zichtbaar bereik voor de grafiek instellen.
Ga naar de methode viewDidLoad en voeg de onderstaande code toe onderaan waar we de plot aan onze grafiek toevoegen:
CPTXYPlotSpace * studentPlotSpace = (CPTXYPlotSpace *) [graph defaultPlotSpace]; [studentPlotSpace setXRange: [CPTPlotRange plotRangeWithLocation: CPTDecimalFromInt (0) length: CPTDecimalFromInt (7)]]; [studentPlotSpace setYRange: [CPTPlotRange plotRangeWithLocation: CPTDecimalFromInt (0) length: CPTDecimalFromInt (10)]];
Eerst krijgen we een CPTXYPlotSpace-object uit de standaard plotplot van de grafiek (wat casten vereist is). Vervolgens stellen we eenvoudig het x- en y-bereik in. Het bereik is een 'CPTPlotRange'-object dat we statisch maken met behulp van de methode' plotRangeWithLocation: length: '. Deze methode neemt NSDecimals, maar corePlot biedt ons een functie die we kunnen gebruiken om een decimaal te krijgen van een int genaamd 'CPTDecimalFromInt' (er is er ook een voor float als dat vereist is).
Sla nu op en voer de applicatie uit en u zou het begin van uw eerste grafiek moeten zien!
We hebben het begin van een grafiek, maar het heeft nog wat meer werk nodig voordat het erg nuttig kan zijn. De volgende keer zullen we bespreken hoe aslabels moeten worden ingesteld en opgemaakt, door lijnen en verhogingen aan te kruisen. We gaan ook bespreken hoe het uiterlijk van de grafiek kan worden aangepast en, ten slotte, hoe meerdere plots in één grafiek kunnen worden toegevoegd en beheerd. Tot de volgende keer!