Arbetar med CorePlot Plot Fundamentals

När du arbetar med dataintensiva applikationer måste en utvecklare ofta göra mer än bara visa listor med dataposter i en tabellvy. CorePlot-biblioteket låter dig lägga till fantastiska datavisualiseringar till dina applikationer. Ta reda på hur i denna Tuts + Premium-serie!


Finns även i serien:

  1. Arbeta med CorePlot: Project Setup
  2. Arbetar med CorePlot: Plot Fundamentals
  3. Arbetar med CorePlot: Styling och Add Plots
  4. Arbeta med CorePlot: Skapa en stapeldiagram
  5. Arbeta med CorePlot: Skapa en cirkeldiagram

Var vi lämnade

Förra gången introducerade vi CorePlot-ramverket och diskuterade vad det kan göra och hur vi kan använda det för att förbättra datavisualisering i våra applikationer. Vi undersökte också det provprogram vi ska skapa i serien och hur man lägger till CorePlot i vår applikation. För en kodbild av var vi slutade förra gången ladda ner källkoden för denna handledning (annars kan du inte använda din befintliga kodbas och spara dig själv nedladdningstiden!).


Steg 1. Ställ upp saker

Innan vi kan skapa en graf behöver vi en vy för att göra det. Vi ska tillåta användaren att klicka på en UIBarButtonItem på fliken Studenters sida som kommer att hämta ett handlingsblad med en lista över grafer för användaren att välja. När ett val har gjorts kommer en modalvy att visa ett diagram med relevanta data på den.

Vi ska skapa en ny grupp som heter "Graphing" under "StudentTracker" -gruppen. Skapa en "Visningar" och "Controllers" -grupp under den här som i "Studentlista" och "Ämneslista".

Skapa en ny klass som heter 'STLineGraphViewController' (underklassificering UIViewController) i gruppen 'View Controllers'. När du väljer var du vill lägga till filerna är den bästa platsen att placera dem mappen "Klasser / Grafik / Visa Controllers" (Du måste skapa katalogen "Grafik / Visa Controllers").


Vi kommer att komma tillbaka och jobba med att anpassa detta senare. Just nu ska vi implementera den koden som tillåter användaren att välja en graf för att titta på.

Öppna först STStudentListViewController.h och lägg till protokolldeklarationerna 'UIActionSheetDelegate' och 'STLineGraphViewControllerDelegate'. Detta protokoll finns inte ännu men vi kommer att skapa det senare (Se även till att du importerar filen 'STLineGraphViewController.h').

 @interface STStudentListViewController: UIViewController 

Öppna sedan .m-filen och implementera 'actionSheet: clickedButtonAtIndex:' -metoden med följande kod:

 - (void) actionSheet: (UIActionSheet *) actionSheet clickedButtonAtIndex: (NSInteger) buttonIndex if (buttonIndex == 0) STLineGraphViewController * lineGraphVC = [[STLineGraphViewController alloc] init]; [lineGraphVC setModalTransitionStyle: UIModalTransitionStyleFlipHorizontal]; [lineGraphVC setDelegate: self]; [lineGraphVC setManagedObjectContext: [self managedObjectContext]]; [self presentModalViewController: lineGraphVC animerad: JA]; [lineGraphVC release]; 

Koden behöver inte förklaras för mycket. Vi skapar helt enkelt en LineGraph View Controller och presenterar den modellt. Vi ställer oss som delegat så att vi vet när vi ska avvisa den modala vyn. Vi ger också visningscontrollern ett hanterat objektkontext för att fungera så att det kan kopplas till kärndata. Dessa två senaste metoder kommer att skapa en varning (eller ett fel om du använder ARC) eftersom egenskaperna inte existerar, men vi kommer att skapa dem senare.

Nästa skapar vi en metod för att ringa åt handlingsbladet och lägga till ett UITabBarItem för att ringa det från. Lägg till en metoddeklaration i .m-gränssnittet "GraphButtonWasSelected:":

 @interface STStudentListViewController () @property (nonatomic, strong) NSArray * studentArray; - (void) addStudent: (id) avsändare; - (void) graphButtonWasSelected: (id) avsändare; @slutet

Lägg sedan till metodimplementering:

 - (void) graphButtonWasSelected: (id) avsändare UIActionSheet * graphSelectionActionSheet = [[[UIActionSheet alloc] initWithTitle: @ "Välj en graf" delegat: self cancelButtonTitle: @ "Avbryt" destructiveButtonTitle: nil otherButtonTitles: @ "Inskrivning över tiden" ] autorelease]; [graphSelectionActionSheet showInView: [[UIApplication sharedApplication] keyWindow]]; 

Nästa måste vi lägga till en UIBarButtonItem för användaren att välja när de vill se grafen. Vi gör detta i viewDidLoad-metoden nedan där vi skapar den högra streckknappsobjektet:

 [[self navigationItem] setLeftBarButtonItem: [[[UIBarButtonItem alloc] initWithTitle: @ "Grafer" stil: UIBarButtonItemStylePlain mål: självåtgärd: @selector (graphButtonWasSelected :)] autorelease] animated: NO];

Slutligen måste vi implementera en STLineGraphViewController-protokollmetod som kommer att berätta för regulatorn att avvisa modalvyn när användaren är klar tittar på diagrammet:

 - (void) doneButtonWasTapped: (id) avsändare [self dismissModalViewControllerAnimated: YES]; 

Nu är vi redo att börja skapa grafen!


Steg 2. Ställ in grafens värdvy

Först måste vi skapa en anpassad visningsklass för vår LineGraphViewController. I gruppen Grafik> Visningar skapar du en ny klass som utökar UIView kallad 'STLineGraphView' (Se till att du lägger den i rätt mapp när du väljer var den är sparad på filsystemet).


Vi ska ställa in de grafiska aspekterna av vyn i visningsklassen. Gå först till .h-filen och (efter att ha importerat filen "CorePlot-CocoaTouch.h") och lägg till följande egenskapsdeklaration:

 @property (nonatomic, strong) CPTGraphHostingView * chartHostingView;

CPTGraphHostingView är helt enkelt en UIView som ansvarar för att innehålla grafen och tillåter användarinteraktion (som vi täcker i en senare handledning).

Synthesize chartHostingView och skapa diagramvärdvyn i initWithFrame-metoden:

 [self setChartHostingView: [[[CPTGraphHostingView alloc] initWithFrame: CGRectZero] autorelease]]; [self addSubview: chartHostingView];

Ovanstående bör vara ganska självförklarande. Vi skapar en CPTGraphHostingView och ställer in den som vår egenskap av chartHostingVIew. Vi lägger sedan till det som en undervy.

Nästa måste vi ange grafviews ramdimensioner i metoden "layoutundervisningar":

 [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: [self center]];

Återigen bör alla ovanstående vara enkla saker. Innan vi börjar jobba med regulatorn, se till att du släpper egenskapen 'chartHostingView' i synpunkter dealloc-metoden om du inte redan har.


Steg 3. Skapa linjediagrammet

Det mesta av det arbete vi ska göra nu kommer att vara i regulatorn. Öppna STLineGraphViewController.h och lägg till följande fastighetsdeklarationer:

 @interface STLineGraphViewController: UIViewController  @property (nonatomic, strong) CPTGraph * graph; @property (nonatomic, assign) id delegera; @property (nonatomic, strong) NSManagedObjectContext * managedObjectContext;

CPTGraph är en abstrakt klass som ansvarar för att teckna grafelementen och hantera de olika diagrammen. Det är också ansvaret för tillämpning av teman, omladdning av grafdata, och mycket mer! Vi indikerar också att vi kommer att följa CPTScatterPlotDataSource och CPTScatterPlotDelegate protokollen.

Vi behöver också lägga till ett eget protokoll så att den modella vyn kan avfärdas. Sätt följande kod ovanför gränssnittet deklarationen:

 @protocol STLineGraphViewControllerDelegate @required - (void) doneButtonWasTapped: (id) avsändare; @slutet

Byt till * .m-filen och syntetisera grafen och delegera egenskaper. När det här är gjort, lägg till följande kod före "viewDidLoad" -metoden:

 [self setView: [[[STLineGraphView alloc] initWithFrame: self.view.frame] autorelease]]; CPTTheme * defaultTheme = [CPTTheme themeNamed: kCPTPlainWhiteTheme]; [self setGraph: (CPTGraph *) [defaultTheme newGraph]]; [defaultTheme release];

Det finns några saker som händer i det här avsnittet. Först skapar vi och ställer in kontrollenhetens inställning som vår anpassade STLineGraphView. Därefter skapar vi ett "CPTTheme" -objekt. CPTTheme-objektet hanterar stilen på ett diagram med linjestilar, textstil och eventuella fyllningar som krävs. Ett enkelt sätt att få en CPTGraph förkonfigurerad med en bas CPTTheme är att skapa CPTTheme med ett av de fördefinierade temanamnen och sedan använda metoden "newGraph" för att ge oss en graf som är utformad med den.

Därefter kommer vi att lägga följande kod i "viewDidLoad" Metoden:

 [super viewDidLoad]; STLineGraphView * graphView = (STLineGraphView *) [självvisning]; [[självgraf] setDelegate: self]; [[graphView chartHostingView] setHostedGraph: [self graph]]; CPTScatterPlot * studentScatterPlot = [[CPTScatterPlot-allokering] initWithFrame: [graph bounds]]; [studentScatterPlot setIdentifier: @ "studentEnrollment"]; [studentScatterPlot setDelegate: self]; [studentScatterPlot setDataSource: self]; [[självgraf] addPlot: studentScatterPlot]; UINavigationItem * navigationItem = [[UINavigationItem alloc] initWithTitle: self.title]; [navigationItem setHidesBackButton: JA]; 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: @ "Klar" stil: UIBarButtonItemStyleDone mål: [self delegate] action: @selector (doneButtonWasTapped :)] autorelease] animated: NO];

I ovanstående kod får vi vår syn och ställer in det värddiagrammet för visningstabellen värdvyn till vårt grafobjekt. Vi skapar sedan en "plot" för att lägga på grafen. Vi använder "CPTScatterPlot" när vi vill skapa en linjediagram. Identifikatorn är något vi kan använda för att identifiera tomten senare. Vi ställer sedan in delegat och datakälla till kontrollerklassen eftersom det kommer att vara ansvarigt för att tillhandahålla data för grafen. Slutligen lägger vi till det nyskapade diagrammet i diagrammet.

När vi arbetar med grafen skapar vi ett navigeringsobjekt och en stapel för modalvynskontrollen för att visa en titel och en klar knapp som tar dem tillbaka till originalvyn.

Prova att köra projektet nu och gå till linjediagrammet. Du borde se något som följande:


Vi har början på ett diagram! Nu för att lägga till några data:


Steg 4. Lägga till data i grafen

Plottar i CorePlot använder två huvuddatakällor för att erhålla data, "numberOfRecordsForPlot" och "numberForPlot: field: recordIndex: '. Det liknar mycket hur bordvyer fungerar. Först vill vi ange antalet poster för diagrammet:

 - (NSUInteger) numberOfRecordsForPlot: (CPTPlot *) plot return 8; 

Vi visar hur många inskrivningar som inträffade på varje dag i veckan. Eftersom det finns 7 möjliga dagar där studenten kunde ha registrerat sig har vi 8 totala poster (eftersom vi börjar vid 0).

Nu vill vi ange vad x- och y-värdet ska vara för varje post:

 - (NSNumber *) numberForPlot: (CPTPlot *) plotfält: (NSUInteger) fältEn recordIndex: (NSUInteger) index NSUInteger x = index; NSUInteger y = 0; NSError * fel; NSFetchRequest * fetchRequest = [[NSFetchRequest tilldela] init]; NSEntityDescription * entity = [NSEntityDescription entityForName: @ "STStudent" inManagedObjectContext: managedObjectContext]; NSPredicate * predicate = [NSPredicate predicateWithFormat: @ "dayEnrolled ==% d", index]; [fetchRequest setEntity: entity]; [fetchRequest setPredicate: predicate]; y = [managedObjectContext countForFetchRequest: fetchRequest error: & error]; [fetchRequest release]; switch (fieldEnum) fall CPTScatterPlotFieldX: NSLog (@ "x -värdet för% d är% d", index, x); returnera [NSNummer nummer medIt: x]; ha sönder; fall CPTScatterPlotFieldY: NSLog (@ "y-värdet för% d är% d", index, y); returnera [NSNummernummer medIt: y]; ha sönder; standard: break;  returnera nil; 

Det finns en rättvis bit på ovanstående. Denna metod måste ange ett x- och y-värde för ett givet index och vilket värde det returnerar baseras på "fieldEnum" -värdet (vilket i vårt fall är antingen CPTScatterPlotFieldX eller CPTScatterPlotFieldY). Indexet indikerar den post som det handlar om att plotta på grafen och diagrammet refererar till själva diagrammet som visar data. När vi har en kontroller som hanterar mer än 1 plot, kan vi titta på plotidentifieraren för att bestämma vilken uppsättning data som ska tillhandahållas (vi täcker denna process i en senare handledning).

Jag finner det enklaste att ange ett "x" och "y" -värde vid början av metoden, utarbeta båda värdena och sedan baserat på fältet som returnerar den rätta i form av en NSNumber (vilken är det format som corePlot kräver det).

X-värdet är lätt att räkna ut. Eftersom det visar inskrivningsdagarna är x lika med det aktuella indexet. Y-värdet kommer att vara ett räkna av alla elever inskrivna på den dagen. Vi kan få det genom att ringa till vår kärndatabutik och leta efter alla STStudent-poster med ett "dayEnrolled" -värde i indexet. Om du inte är känd med kärndata och inte förstår allt som händer, var inte alltför bekymrad, för nu är det ok att det fungerar. Fokusera på att lära sig en sak i taget!

Om du sparar och kör din ansökan nu ser du fortfarande ingenting som visas på grafen, men du bör se följande utmatning i konsolen:


Detta betyder att grafen får de korrekta värdena för x och y (se till att det är detsamma eller liknar utmatningen i bilden. Det visas emellertid fortfarande inte på grafen. Det beror på att om du tittar på grafen Det visade intervallet är felaktigt. Vi tittar på -1,0 till 0 på både x- och y-axeln. Vi måste ställa in intervallet för att titta på innan vi kan se datapunkterna.

Plotutrymmet bestämmer mycket om hur grafen ska ses och formateras. Vi kommer att täcka lite i denna handledning och kommer att gå in i mycket större detalj i nästa.

För att ställa in det x och y-område som användaren tittar på behöver vi arbeta med objektet "CPTXYPlotSpace". Med det här objektet kan vi ange ett visningsområde för grafen.

Gå till ViewDidLoad-metoden och lägg till följande kod precis nedanför där vi lägger till diagrammet i vårt diagram:

 CPTXYPlotSpace * studentPlotSpace = (CPTXYPlotSpace *) [graph defaultPlotSpace]; [studentPlotSpace setXRange: [CPTPlotRange plotRangeWithLocation: CPTDecimalFromInt (0) längd: CPTDecimalFromInt (7)]]; [studentPlotSpace setYRange: [CPTPlotRange plotRangeWithLocation: CPTDecimalFromInt (0) längd: CPTDecimalFromInt (10)]];

Först får vi ett CPTXYPlotSpace-objekt från diagrammets standardplottutrymme (vissa gjutningar krävs). Då ställer vi helt enkelt x och y-intervallet. Sortimentet är ett "CPTPlotRange" -objekt som vi skapar statiskt med hjälp av "plotRangeWithLocation: length:" -metoden. Denna metod tar NSDecimals men corePlot ger oss en funktion som vi kan använda för att få ett decimaltal från en int kallad "CPTDecimalFromInt" (Det finns också en för float om det behövs).

Spara och kör nu programmet och du bör se början av din första graf!



Nästa gång

Vi har startat ett diagram men det behöver lite mer arbete innan det kan vara mycket användbart. Nästa gång kommer vi att diskutera hur man ställer in och formaterar axelmärkning, kryssrutor och steg. Vi kommer också att diskutera hur man anpassar utseendet på grafen, och slutligen hur man lägger till och hanterar flera diagram i en enda graf. Vi ses nästa gång!