Mit CorePlot arbeiten Kreisdiagramm erstellen

Wenn Sie mit datenintensiven Anwendungen arbeiten, muss ein Entwickler oft mehr als nur Listen von Datensätzen in einer Tabellensicht anzeigen. Mit der CorePlot-Bibliothek können Sie Ihren Anwendungen beeindruckende Datenvisualisierungen hinzufügen. In dieser Tuts + Premium-Serie erfahren Sie, wie es geht!


Auch in dieser Serie erhältlich:

  1. Arbeiten mit CorePlot: Projekteinrichtung
  2. Arbeiten mit CorePlot: Plot-Grundlagen
  3. Arbeiten mit CorePlot: Gestaltung und Hinzufügen von Plots
  4. Arbeiten mit CorePlot: Erstellen eines Balkendiagramms
  5. Mit CorePlot arbeiten: Kreisdiagramm erstellen

Wo wir aufgehört haben

Letztes Mal haben wir uns mit dem Erstellen eines Balkendiagramms beschäftigt, wie Sie die Balkenfarben anpassen und wie Sie unserer Achse benutzerdefinierte Beschriftungen hinzufügen, wenn Sie anstelle von Zahlen benutzerdefinierten Text anzeigen möchten.


Was wir heute abdecken werden

Dieses Mal behandeln wir, wie Sie die Logik aus unserem Controller in ein wiederverwendbares Datenquellenobjekt extrahieren. Nachdem wir dies beherrscht haben, werden wir die gleichen Daten wie das Balkendiagramm anzeigen, mit Ausnahme dieser Zeit als Kreisdiagramm!


Schritt 1: Einrichten

Bevor wir die Datenlogik abstrahieren, erstellen wir unsere Basisklassen für das Kreisdiagramm. Genau wie beim letzten Mal müssen wir einen neuen View-Controller für das Diagramm erstellen. Nennen wir es 'STPieGraphViewController'..


Beachten Sie, dass wir diesmal keine Ansicht erstellen müssen, da wir 'STGraphView' verwenden können. Bevor wir mit dem Einrichten beginnen, springen wir in STStudentListViewController.h und importieren STPieGraphViewController.h. Wir müssen auch das Protokoll STPieGraphViewControllerDelegate (das wir später erstellen werden) einhalten:

 @Interface STStudentListViewController: UIViewController 

Wechseln Sie zur .m-Datei. Wir müssen dem Aktionsblatt eine Schaltfläche hinzufügen. Suchen Sie die Methode graphButtonWasSelected:. Wir bearbeiten den zweiten Schaltflächentext und fügen einen dritten hinzu:

 - (void) graphButtonWasSelected: (id) sender UIActionSheet * graphSelectionActionSheet = [[[[UIActionSheet-Zuordnung] initWithTitle: @ "Wählen Sie einen Graphen aus" delegate: self cancelButtonTitle: @ "Cancel" destructiveButtonTitle: "; "Subjektsummen - Balken", @ "Subjektsummen - Torte", Null] Autorelease]; [graphSelectionActionSheet showInView: [[UIApplication sharedApplication] keyWindow]]; 

Springen Sie nun in das actionSheet: clickedButtonAtIndex: -Methode und fügen Sie eine Klausel für buttonIndex == 2 hinzu:

 else if (buttonIndex == 2) STPieGraphViewController * graphVC = [[STPieGraphViewController-Zuordnung] init]; [graphVC setModalTransitionStyle: UIModalTransitionStyleFlipHorizontal]; [graphVC setModalPresentationStyle: UIModalPresentationFullScreen]; [graphVC setDelegate: self]; [graphVC setManagedObjectContext: [self managedObjectContext]]; [self presentModalViewController: graphVC animiert: JA]; [graphVC release]; 

Genau wie beim letzten Mal werden einige Warnungen angezeigt, da STPieGraphViewController keine Delegat- oder managedObjectContext-Eigenschaft besitzt.

Also, springen Sie in STPieGraphViewController.h. Importieren Sie 'CorePlot-CocoaTouch.h' und fügen Sie die folgenden Eigenschaften und Protokolldeklarationen hinzu:

 @protocol STPieGraphViewControllerDelegate @required - (void) doneButtonWasTapped: (ID) Absender; @end @interface STPieGraphViewController: UIViewController  @ Eigenschaft (nichtatomisch, stark) CPTGraph * Graph; @ property (nichtatomisch, zuweisen) id delegieren; @ property (nicht atomar, stark) NSManagedObjectContext * managedObjectContext; @Ende

Es ist wichtig zu erwähnen, dass wir diesmal CPTPieChartDataSource nicht einhalten. Dies liegt daran, dass wir die Graphikdatenlogik von STBarGraphViewController in eine separate dataSource-Klasse abstrahieren. Bevor wir das tun, beenden wir die Einrichtung. Importieren Sie in der .m-Datei 'STGraphView.h', synthetisieren Sie die Eigenschaften und implementieren Sie die Dealloc-Methode.

Richten Sie schließlich die loadView- und viewDidLoad-Methoden wie folgt ein:

 - (void) loadView [super loadView]; [self setTitle: @ "Einschreibung nach Betreff"]; [self-setView: [[[STGraphView-Zuordnung] initWithFrame: self.view.frame] Autorelease]]; CPTTheme * defaultTheme = [CPTTheme themeName: kCPTPlainWhiteTheme]; [self setGraph: (CPTGraph *) [defaultTheme newGraph]];  - (void) viewDidLoad [super viewDidLoad]; STGraphView * graphView = (STGraphView *) [Selbstansicht]; [[graphView chartHostingView] setHostedGraph: [Selbstdiagramm]]; // Benutzer dürfen zurückgehen UINavigationItem * navigationItem = [[[UINavigationItem Allocation] initWithTitle: self.title] autorelease]; [navigationItem setHidesBackButton: YES]; UINavigationBar * navigationBar = [[[UINavigationBar Allocation] initWithFrame: CGRectMake (0, 0, self.view.frame.size.width, 44.0f)] Autorelease]; [navigationBar pushNavigationItem: navigationItem animated: NO]; [self.view addSubview: navigationBar]; [navigationItem setRightBarButtonItem: [[[UIBarButtonItem-Zuordnung] initWithTitle: @ "Done" -Stil: UIBButtonItemStyleDone-Ziel: [Selbstdelegierter] Aktion: @selector (doneButtonWasTapped :)] autorelease] animated: NO]; 

Das Obige sollte mittlerweile bekannt sein. Sehen wir uns also die Graphiklogik in eine separate Klasse an.


Schritt 2: Trennen der Graphiklogik

Wir haben bereits die Logik für das Abrufen von Daten für die Gesamtzahl der Schüler in allen Fächern geschrieben. Wir wollen es nicht noch einmal schreiben, zum Glück müssen wir es nicht. Alle Datenquellenprotokolle für die Diagramme erben von 'CPTPlotDataSource'. Dieses Protokoll enthält die Methoden numberOfRecordsForPlot: und numberForPlot: fieldEnum: recordIndex.

Erstellen Sie eine Klasse mit dem Namen 'STAbstractSubjectDataSource.h' (erbt von NSObject) in einer neuen Gruppe mit dem Namen 'DataSource' in der Diagrammgruppe. Für die Headerdatei importieren Sie 'CorePlot-CocoaTouch.h' und geben Sie die folgenden Eigenschaften und Methodendeklarationen ein:

 @interface STAbstractSubjectEnrollementDataSource: NSObject  @ property (nicht atomar, stark) NSManagedObjectContext * managedObjectContext; - (id) initWithManagedObjectContext: (NSManagedObjectContext *) aManagedObjectContext; - (Float) getTotalSubjects; - (Float) getMaxEnrolled; - (NSArray *) getSubjectTitlesAsArray; @Ende

Wir abonnieren das Protokoll 'CPTPlotDataSource'. Wir erstellen eine benutzerdefinierte Init-Methode, die einen managedObjectContext durchläuft, damit das Objekt auf den Datenspeicher zugreifen kann. Schließlich gibt es drei Hilfsmethoden, die helfen können, Informationen über die Fächer und die Einschreibung zu erhalten. Dies sind die gleichen Methoden, die derzeit in STBarGraphViewController vorhanden sind. Diese werden wir in die Datenquellenmethode verschieben.

Abgesehen von der init-Methode enthält die .m-Datei keinen neuen Code, den Sie noch nicht gesehen haben. Es ist nur eine Frage des Verschiebens des gesamten vorhandenen Codes von STBarGraphViewController in das DataSource-Objekt. Die Methoden, die Sie verschieben sollten, sind:

  • (Float) getTotalSubjects
  • (Float) getMaxEnrolled
  • (NSArray *) getSubjectTitlesAsArray
  • (NSUInteger) numberOfRecordsForPlot: (CPTPlot *) - Diagramm
  • (NSNumber *) numberForPlot: (CPTPlot *) Diagrammfeld: (NSUInteger) FeldEnum RecordIndex: (NSUInteger) Index

Stellen Sie außerdem sicher, dass Sie die benutzerdefinierte Init-Methode hinzufügen:

 - (id) initWithManagedObjectContext: (NSManagedObjectContext *) aManagedObjectContext self = [super init]; if (self) [self setManagedObjectContext: aManagedObjectContext];  return self; 

Jetzt haben wir ein Datenquellenobjekt, das die Basisdaten für den Kreis und das Balkendiagramm bereitstellen kann. Die abstrakte Datenquelle liefert uns nicht alles, was wir brauchen, der barFillForBarPlot: recordIndex kann jedoch nicht implementiert werden, da er Teil von CPTBarPlotDataSource ist. Wir müssen unseren abstrakten Kurs auf etwas Spezifisches für Balkendiagramme erweitern.

Erstellen Sie ein neues Objekt in der Datenquellengruppe mit dem Namen 'STBarGraphSubjectEnrollementDataSource', das unsere abstrakte Klasse erweitert. Abonnieren Sie im Header 'CPTBarPlotDataSource:

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

Implementieren Sie in der .m-Datei die barFillForBarPlot-Methode:

 #pragma mark - CPTBarPlotDataSource Methods - (CPTFill *) barFillForBarPlot: (CPTBarPlot *) barPlot recordIndex: (NSUInteger) index CPTColor * areaColor = nil; Schalter (Index) Fall 0: areaColor = [CPTColor redColor]; brechen; Fall 1: areaColor = [CPTColor blueColor]; brechen; Fall 2: areaColor = [CPTColor orangeColor]; brechen; Fall 3: areaColor = [CPTColor greenColor]; brechen; Voreinstellung: areaColor = [CPTColor purpleColor]; brechen;  CPTFill * barFill = [CPTFill fillWithColor: areaColor]; return barFill; 

Gehen Sie jetzt zurück zu Ihrer STBarGraphViewControllers-Header-Datei und importieren Sie die neue Bargraph-Datenquelle. Sie können jetzt die Subskription "CPTBarPlotDataSource" entfernen. Wechseln Sie in die .m-Datei und löschen Sie alle Methoden außer loadView, viewDidLoad und dealloc. Wir brauchen sie nicht mehr.

Wir müssen einen Zeiger auf die Datenquelle beibehalten und den Zeiger freigeben, wenn die Ansicht fertig ist. Deklarieren Sie in der privaten Schnittstelle die Eigenschaft und synthetisieren Sie dann:

 @interface STBarGraphViewController () @property (nicht atomar, beibehalten) STBarGraphSubjectEnrollementDataSource * barGraphDataSource; @end @implementation STBarGraphViewController @synthesize delegate; @synthesize managedObjectContext; @synthetisieren Sie den Graph; @synthesize barGraphDataSource;

Stellen Sie sicher, dass Sie es auch in der Dealloc-Methode freigeben. Erstellen Sie eine neue Instanz und legen Sie sie in der loadView-Methode als unsere Eigenschaft fest:

 [self-setBarGraphDataSource: [[[STBarGraphSubjectEnrollementDataSource-Zuordnung] initWithManagedObjectContext: [self managedObjectContext]] autorelease];

In der viewDidLoad-Methode müssen wir nun die Hilfsmethoden unserer Datenquelle verwenden, um den Plotraum und die benutzerdefinierten Beschriftungen zu berechnen:

 CPTXYPlotSpace * studentPlotSpace = (CPTXYPlotSpace *) [Graph defaultPlotSpace]; [studentPlotSpace setXRange: [CPTPlotRange plotRangeWithLocation: CPTDecimalFromInt (0) Länge: CPTDecimalFromInt ([[self barGraphDataSource] getTotalSubjects] + 1)]]; [studentPlotSpace setYRange: [CPTPlotRange plotRangeWithLocation: CPTDecimalFromInt (0) Länge: CPTDecimalFromInt ([[self barGraphDataSource] getMaxEnrolled] + 1)]];
 NSArray * subjectsArray = [[self barGraphDataSource] getSubjectTitlesAsArray];

Speichern, erstellen und ausführen. Alles sollte wie bisher funktionieren. Wenn dies der Fall ist, können wir mit der Erstellung unseres Kreisdiagramms beginnen!


Schritt 3: Erstellen des Kuchendiagramms

Wir möchten eine spezifische Datenquelle für das Kreisdiagramm erstellen, genauso wie wir es für das Balkendiagramm getan haben, falls wir irgendwelche Kreisdiagramm-spezifischen Datenquellenmethoden implementieren müssen. Erstellen Sie eine Klasse mit dem Namen 'STPieGraphSubjectEnrollementDataSource', die von 'STAbstractSubjectEnrollementDataSource' erbt. Abonnieren Sie in der Headerdatei das Protokoll 'CPTPieChartDataSource'. Wir werden noch keine speziellen Datenquellenmethoden für Kreisdiagramme implementieren, wir werden später darauf zurückkommen.

Jetzt, da wir Datenquellen haben, ist das Erstellen des Kreisdiagramms einfach! Springen Sie in die Datei STBPieGraphViewController.m und importieren Sie das Kreisdiagramm-Datenquellenobjekt. Deklarieren Sie es als Eigenschaft in der .m-Datei, wie wir es beim letzten Mal getan haben:

 @interface STPieGraphViewController () @property (nicht atomar, stark) STPieGraphSubjectEnrollementDataSource * pieChartDataSource; @end @implementation STPieGraphViewController @synthesize managedObjectContext; @synthesize delegate; @synthetisieren Sie den Graph; @synthesize pieChartDataSource;

Jetzt erstellen und in der loadView setzen:

 [self-setPieChartDataSource: [[[STPieGraphSubjectEnrollementDataSource-Zuordnung] initWithManagedObjectContext: [self managedObjectContext]] autorelease]];

Schließlich müssen wir in der viewDidLoad-Methode unser Kreisdiagramm erstellen, es unserer GraphView hinzufügen und die Standardachse entfernen:

 STGraphView * graphView = (STGraphView *) [Selbstansicht]; [[graphView chartHostingView] setHostedGraph: [Selbstdiagramm]]; CPTPieChart * pieChart = [[CPTPieChart-Zuordnung] initWithFrame: [Diagrammgrenzen]]; [pieChart setPieRadius: 100.00]; [pieChart setIdentifier: @ "Betreff"]; [pieChart setStartAngle: M_PI_4]; [pieChart setSliceDirection: CPTPieDirectionCounterClockwise]; [pieChart setDataSource: pieChartDataSource]; [graph addPlot: pieChart]; [graph setAxisSet: nil]; [graph setBorderLineStyle: nil];

Die meisten der oben genannten sollten bekannt aussehen. Beachten Sie, dass es nicht explizit als "Plot" bezeichnet wird, da es nicht auf einer X-Achse oder Y-Achse basiert, aber wir behandeln es immer noch genauso. Es gibt auch einige spezifische Diagramme, die wir hier machen. Wir erstellen einen Kreisradius und einen Startwinkel. Wir legen auch eine Slice-Richtung fest. Zum Schluss setzen wir das 'axisSet' des Diagramms auf null, damit wir die x- und y-Linien nicht erhalten.

Und das sollte alles sein. Erstellen und ausführen, um das Kreisdiagramm anzuzeigen.


Das ist gut, aber es könnte eine Art Hinweis darauf geben, was jede Farbe darstellt. Eine gute Möglichkeit, dies zu tun, ist die Verwendung von Legenden. Dazu erstellen wir ein 'CPTLegend'-Objekt, das wir unserem Diagramm hinzufügen, und implementieren eine Delegat-Methode, die den relevanten Titel für die Legende zurückgibt.

Erstellen wir zuerst das CPTLegend-Objekt. Geben Sie in unserer Methode viewDidLoad den folgenden Code ein, unter dem wir unser Kreisdiagramm erstellen:

 CPTLegend * theLegend = [CPTLegend legendWithGraph: [Selbstdiagramm]]; [theLegend setNumberOfColumns: 2]; [[self graph] setLegend: theLegend]; [[self graph] setLegendAnchor: CPTRectAnchorBottom]; [[self graph] setLegendDisplacement: CGPointMake (0.0, 30.0)];

Dies erstellt eine Legende und fügt sie unserem Diagrammobjekt hinzu. Die Anzahl der Spalten bestimmt, wie die Legendentitel angeordnet werden. Wir legen dann einige Attribute für das Diagrammobjekt fest, die bestimmen, wo die Legende platziert wird (die unterste), und einige Verschiebungen, um sicherzustellen, dass sie vollständig in der Ansicht angezeigt werden.

Wir müssen der Legende jedoch noch Titel geben. Es gibt eine spezifische Methode für CPTPieChartDataSource, mit der wir dies tun können. Springen Sie in die Datenquelle des Kreisdiagramms und implementieren Sie den folgenden Code:

 #pragma mark - CPTPieChartDataSource - (NSString *) legendTitleForPieChart: (CPTPieChart *) pieChart recordIndex: (NSUInteger) index NSError * error = nil; NSFetchRequest * request = [[NSFetchRequest-Zuordnung] init]; NSEntityDescription * entity = [NSEntityDescription entityForName: @ "STSubject" inManagedObjectContext: [self managedObjectContext]]; NSPredicate * predicate = [NSPredicate predicateWithFormat: @ "subjectID ==% d", index]; [request setEntity: entity]; [request setResultType: NSDictionaryResultType]; [request setPredicate: prädikat]; [request setReturnsDistinctResults: NO]; [request setPropertiesToFetch: [NSArray arrayWithObject: @ "subjectName"]]; NSArray * titleStrings = [[self managedObjectContext] executeFetchRequest: Anforderungsfehler: & Fehler]; NSDictionary * fetchedSubject = [titleStrings objectAtIndex: 0]; return [abgerufenesSubjekt objectForKey: @ "subjectName"]; 

Diese Methode ruft einfach den Index der Legende ab und ruft den Titel als Zeichenfolge aus dem Datenspeicher ab und gibt ihn zurück.

Erstellen und ausführen, und Sie sollten ein informatives Tortendiagramm haben!



Einpacken

Wir haben behandelt, wie die Datenlogik aus der Steuerung in ein separates Objekt zerlegt wird, das einfacher zu verwalten und zu erweitern ist. Wir haben auch die Grundlagen zum Erstellen eines Kreisdiagramms behandelt.

Damit sind wir am Ende der Serie. Ich hoffe, Sie fanden diese Tutorials hilfreich. CorePlot bietet noch viel mehr Möglichkeiten, aber dies sollte Ihnen eine solide Grundlage geben, auf der Sie aufbauen können. Viel Glück beim Hinzufügen von Grafiken zu Ihren eigenen Projekten!