Lorsqu'il travaille avec des applications gourmandes en données, un développeur doit souvent faire plus que simplement afficher des listes d'enregistrements de données dans une vue sous forme de tableau. La bibliothèque CorePlot vous permettra d’ajouter de superbes visualisations de données à vos applications. Découvrez comment dans cette série Tuts + Premium!
La dernière fois, nous avons expliqué comment personnaliser l'apparence et le style d'un graphique à courbes (ou à nuage de points) à l'aide de classes telles que CPTMutableTextStyle et CPTMutableLineStyle. Nous avons appris à personnaliser les incréments et les styles de numéro des axes X et Y à l'aide des classes CPTXYAxisSet et CPTXYAxis. Nous avons également examiné comment ajouter plusieurs graphiques à votre graphique et modifier les méthodes de source de données afin de fournir les données correctes pour les graphiques correspondants à l'aide d'identificateurs de graphique..
Aujourd'hui, nous allons travailler avec un graphique complètement nouveau. Nous allons créer un graphique à barres qui indique le nombre total d'élèves dans chaque matière, chaque barre représentant une matière. Nous verrons également comment personnaliser l'apparence du graphique. Commençons!
Tout d'abord, nous devons ajouter les classes pertinentes à notre projet. Créons un ViewController appelé 'STBarGraphViewController' et un 'STGraphView'. (Assurez-vous de les mettre dans les groupes appropriés)
Remarquez l'attribution du nom de la vue à 'STGraphView' au lieu de 'STBarGraphView'. À l'avenir, nous utiliserons cette vue pour afficher les graphiques à barres et à secteurs..
Avant de commencer à utiliser un code, nous devons ajouter un bouton à la feuille Action de la vue Liste des étudiants. Ouvrez d'abord 'STStudentListViewController.h' et importez STBarGraphViewController. Ajoutez STBarGraphViewControllerDelegate à la liste des protocoles enregistrés (le protocole n'existe pas encore, mais nous le créerons plus tard):
@interface STStudentListViewController: UIViewController
Ensuite, accédez au fichier .m et localisez la méthode 'graphButtonWasSelected:'. Ajouter 'Inscription par sujet' à la liste des 'autresButtonTitles:':
UIActionSheet * graphSelectionActionSheet = [[[UIActionSheet alloc] initWithTitle: @ "Choisissez un graphique" delegate: self cancelButtonTitle: @ "Cancel" destructiveButtonTitle: nil otherButtonTitles: @ "Inscription sur le temps", @ "Enrollment over time", "enrollment by subject", enregistrez-le. ;
Recherchez maintenant la méthode 'actionSheet: clickedButtonAtIndex:' et modifiez-la pour qu'elle fonctionne avec buttonIndex == 1:
if (buttonIndex == 0) STLineGraphViewController * graphVC = [[STLineGraphViewController alloc]] init]; [graphVC setModalTransitionStyle: UIModalTransitionStyleFlipHorizontal]; [graphVC setModalPresentationStyle: UIModalPresentationFullScreen]; [graphVC setDelegate: self]; [graphVC setManagedObjectContext: [auto managedObjectContext]]; [self presentModalViewController: graphVC animated: YES]; [version graphVC]; else if (buttonIndex == 1) STBarGraphViewController * graphVC = [[STBarGraphViewController alloc] init]; [graphVC setModalTransitionStyle: UIModalTransitionStyleFlipHorizontal]; [graphVC setModalPresentationStyle: UIModalPresentationFullScreen]; [graphVC setDelegate: self]; [graphVC setManagedObjectContext: [auto managedObjectContext]]; [self presentModalViewController: graphVC animated: YES]; [version graphVC];
Encore une fois, cela affichera quelques avertissements car nous n'avons pas encore implémenté les propriétés delegate ou managedObjectContext sur STBarGraphViewController..
Maintenant, sautez dans STBarGraphViewController.h. Importez CorePlot-CocoaTouch.h et ajoutez la déclaration de propriété suivante:
@protocol STBarGraphViewControllerDelegate @required - (void) doneButtonWasTapped: (id) expéditeur; @fin
Ajoutez maintenant les propriétés suivantes:
@property (nonatomic, strong) graphique CPTGraph *; @property (nonatomic, assign) iddéléguer; @property (nonatomic, strong) NSManagedObjectContext * managedObjectContext;
Enfin, inscrivez que cette classe suivra ces protocoles:
@interface STBarGraphViewController: UIViewController
Notez que, en plus de se conformer à différents protocoles, cette classe est identique à STLineViewController. Idéalement, vous devriez avoir une classe de base qui aurait ces propriétés que vous sous-classeriez pour réduire la répétition de code. Ce tutoriel se concentre uniquement sur l'intrigue principale. Nous nous concentrons donc uniquement sur la meilleure manière de travailler avec le framework CorePlot. Si vous avez les connaissances et le temps, n'hésitez pas à créer la classe de base et à utiliser l'héritage, mais nous allons garder les choses simples dans l'exemple de code ici..
Ensuite, accédez au fichier .m, synthétisez les propriétés et libérez-les dans la méthode dealloc.
Lions maintenant la classe de vue en tant que vue du contrôleur. Importez 'STBarGraphView.h' et ajoutez la méthode suivante:
- (void) loadView [super loadView]; [self setTitle: @ "Inscription par sujet"]; [auto setView: [[[[STGraphView alloc]] initWithFrame: self.view.frame] autorelease]]; CPTTheme * defaultTheme = [CPTTheme themeNamed: kCPTPlainWhiteTheme]; [self setGraph: (CPTGraph *) [defaultTheme newGraph]];
Nous sommes maintenant prêts à travailler avec la vue. Ouvrez STGraphView.h, importez la structure de tracé principale (CorePlot-CocoaTouch.h) et ajoutez la déclaration de propriété suivante:
@property (nonatomic, strong) CPTGraphHostingView * chartHostingView;
Sautez dans le fichier .m, synthétisez la propriété et libérez-la dans la méthode dealloc. Puis créez le CPTGraphHostingView dans la méthode 'initWithFrame:':
- (id) initWithFrame: (CGRect) frame self = [super initWithFrame: frame]; if (self) [self setChartHostingView: [[[[CPTGraphHostingView alloc]] initWithFrame: CGRectZero] autorelease]]; [chartHostingView setBackgroundColor: [UIColor purpleColor]]; [auto addSubview: chartHostingView]; retourner soi-même;
Enfin, créez la méthode 'layoutSubviews' avec le code suivant:
- (void) layoutSubviews [super layoutSubviews]; float chartHeight = self.frame.size.height; float chartWidth = self.frame.size.width; [[self chartHostingView] setFrame: CGRectMake (0, 0, chartWidth, chartHeight)]]; [[self chartHostingView] setCenter: [centre auto]]];
Vous remarquerez que le code utilisé pour créer cette vue est exactement le même que STLineGraphView. Nous pouvons utiliser cette vue de base pour travailler avec toutes les vues de graphique à venir.
Retournez dans la vue 'STBarGraphViewController.m' et localisez la méthode 'viewDidLoad'. Tout d'abord, nous voulons créer un CPTBarPlot et l'ajouter à notre graphique:
[[graphView chartHostingView] setHostedGraph: [graphique auto]]; CPTBarPlot * subjectBarPlot = [[CPTBarPlot alloc] initWithFrame: [graph bounds]]; [subjectBarPlot setIdentifier: @ "subjectEnrollement"]; [subjectBarPlot setDelegate: self]; [subjectBarPlot setDataSource: self]; [[self graph]] addPlot: subjectBarPlot];
Enfin, ajoutons une barre de navigation avec un bouton Terminé pour que l’utilisateur puisse revenir:
UINavigationItem * navigationItem = [[[[UINavigationItem alloc]] initWithTitle: self.title] autorelease]; [navigationItem setHidesBackButton: YES]; UINavigationBar * navigationBar = [[[[UINavigationBar alloc]] initWithFrame: CGRectMake (0, 0, self.view.frame.size.width, 44.0f)] autorelease]; [navigationBar pushNavigationItem: navigationItem animated: NO]; [auto.view addSubview: navigationBar]; [navigationItem setRightBarButtonItem: [[[[UIBarButtonItem alloc]] initWithTitle: @ style "fait: UIBarButtonItemStyleDone target: action auto-déléguée: @secteur (doneButtonWasTapped :)] auto-animée: non];
Commençons maintenant à travailler sur les méthodes de source de données:
Le processus ressemblera à la façon dont nous avons créé le graphique linéaire, mais nous allons rendre les choses un peu plus dynamiques. Nous allons créer des méthodes personnalisées qui fourniront un espace de tracé approprié. Nous ajouterons également des méthodes de source de données supplémentaires pour fournir une couleur spécifique à chaque barre ainsi que des titres en abscisse..
Avant de fournir les données du graphique, nous devons définir l’axe et les plages visibles. Pour ce faire, nous avons besoin de deux méthodes qui calculent les valeurs x et y maximales. Déclarez les méthodes suivantes en haut du fichier .m:
[[graphView chartHostingView] setHostedGraph: [graphique auto]]; @interface STBarGraphViewController () - (float) getTotalSubjects; - (float) getMaxEnrolled; @fin
Maintenant, implémentez-les comme ci-dessous:
#pragma mark - Méthodes privées - (float) getTotalSubjects NSError * error = nil; NSFetchRequest * fetchRequest = [[[[NSFetchRequest alloc] init] autorelease]; NSEntityDescription * entity = [NSEntityDescription entityForName: @ "STSubject" inManagedObjectContext: managedObjectContext]; [fetchRequest setEntity: entité]; return [managedObjectContext countForFetchRequest: erreur fetchRequest: & error]; - (float) getMaxEnrolled float maxEnrolled = 0; NSError * error = nil; pour (int i = 0; i < [self getTotalSubjects]; i++) NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"STStudent" inManagedObjectContext:managedObjectContext]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"subjectID == %d", i]; [fetchRequest setEntity:entity]; [fetchRequest setPredicate:predicate]; float subjectMax = [managedObjectContext countForFetchRequest:fetchRequest error:&error]; NSLog(@"enrolled for Subject %d is %f", i, subjectMax); [fetchRequest release]; if (subjectMax > maxEnrolled) maxEnrolled = subjectMax; return maxEnrolled;
'getTotalSubjects' obtient simplement le nombre de sujets dans le magasin de données principal. 'getMaxEnrolled' parcourt toutes les matières, recherche le plus grand nombre d'étudiants dans chacune d'elles et renvoie la valeur la plus élevée.
Avec ces méthodes effectuées, nous pouvons revenir à notre méthode 'viewDidLoad' et ajouter le code suivant ci-dessous où nous ajoutons le graphique en barres à notre graphique:
CPTXYPlotSpace * studentPlotSpace = (CPTXYPlotSpace *) [graph defaultPlotSpace]; [studentPlotSpace setXRange: [CPTPlotRange plotRangeWithLocation: CPTDecimalFromInt (0) longueur: CPTDecimalFromInt ([self getTotalSubjects] + 1)]]; [studentPlotSpace setYRange: [CPTPlotRange plotRangeWithLocation: CPTDecimalFromInt (0) longueur: CPTDecimalFromInt ([self getMaxEnrolled] + 1)]]; [[graph plotAreaFrame] setPaddingLeft: 40.0f]; [[graph plotAreaFrame] setPaddingTop: 10.0f]; [[graph plotAreaFrame] setPaddingBottom: 120.0f]; [[graph plotAreaFrame] setPaddingRight: 0.0f]; [[graph plotAreaFrame] setBorderLineStyle: nil]; CPTMutableTextStyle * textStyle = [CPTMutableTextStyle textStyle]; [textStyle setFontSize: 12.0f]; [textStyle setColor: [CPTColor colorWithCGColor: [[UIColor greyColor] CGColor]]]; CPTXYAxisSet * axisSet = (CPTXYAxisSet *) [graph axisSet]; CPTXYAxis * xAxis = [axisSet xAxis]; [xAxis setMajorIntervalLength: CPTDecimalFromInt (1)]; [xAxis setMinorTickLineStyle: nil]; [xAxis setLabelingPolicy: CPTAxisLabelingPolicyFixedInterval]; [xAxis setLabelTextStyle: textStyle]; CPTXYAxis * yAxis = [axeSet yAxis]; [yAxis setMajorIntervalLength: CPTDecimalFromInt (1)]; [yAxis setMinorTickLineStyle: nil]; [yAxis setLabelingPolicy: CPTAxisLabelingPolicyFixedInterval];
La plupart des réponses ci-dessus devraient vous être familières depuis la dernière fois. Cependant, au lieu de définir des valeurs codées en dur pour nos longueurs de plage de tracé x et y max, nous utilisons nos nouvelles méthodes pour créer les valeurs de manière dynamique. Après cela, nous venons de définir un formatage d’axe de base et d’ajouter un remplissage à la trame pour que l’axe s’affiche correctement..
Nous devons maintenant fournir au graphique les données en utilisant les méthodes de source de données. Fournir le nombre d'enregistrements est simple:
#pragma mark - CPTBarPlotDataSourceMethods - (NSUInteger) numberOfRecordsForPlot: (CPTPlot *) plot return [self getTotalSubjects];
Maintenant, fournissons les valeurs x et y pour les enregistrements:
- (NSNumber *) numberForPlot: (CPTPlot *) champ de tracé: (NSUInteger) fieldEnum recordIndex: (NSUInteger) index int x = index + 1; int y = 0; NSError * error; NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription * entity = [NSEntityDescription entityForName: @ "STStudent" inManagedObjectContext: managedObjectContext]; NSPredicate * predicate = [NSPredicate predicateWithFormat: @ "subjectID ==% d", index]; [fetchRequest setEntity: entité]; [fetchRequest setPredicate: predicate]; y = [managedObjectContext countForFetchRequest: erreur fetchRequest: & error]; [version fetchRequest]; commutateur (fieldEnum) case CPTScatterPlotFieldX: return [NSNumber numberWithInt: x]; Pause; case CPTScatterPlotFieldY: return [NSNumber numberWithInt: y]; Pause; défaut: break; return nil;
La méthode ci-dessus est très similaire à la façon dont nous fournissons des données à un nuage de points. Nous modifions l'appel vers le magasin de données afin d'obtenir le nombre total d'étudiants inscrits dans une matière. Nous avons également défini la valeur x sur +1. Ainsi, la barre commence à '1' et fournit un peu de marge entre la première barre et la ligne de l'axe des ordonnées.
Enregistrez et exécutez le projet… vous devriez voir votre graphique à barres!
Nous pouvons faire un peu plus pour rendre cela plus facile à regarder. Nous voulons attribuer à chaque barre une couleur différente et fournir le nom du sujet sous la forme d'une étiquette représentant l'axe des x au lieu d'un nombre. Nous pouvons faire la première avec une méthode CPTBarPlotDataSource appelée 'barFillForBarPlot: recordIndex':
-(CPTFill *) barFillForBarPlot: (CPTBarPlot *) barPlot recordIndex: (NSUInteger) index CPTColor * areaColor = nil; commutateur (index) cas 0: areaColor = [CPTColor redColor]; Pause; cas 1: areaColor = [CPTColor blueColor]; Pause; cas 2: areaColor = [CPTColor orangeColor]; Pause; cas 3: areaColor = [CPTColor greenColor]; Pause; default: areaColor = [CPTColor purpleColor]; Pause; CPTFill * barFill = [CPTFill fillWithColor: areaColor]; retour barFill;
Cela retournera une couleur différente pour chaque barre de notre graphique. Si vous voulez le rendre encore plus élégant, vous pouvez en faire un dégradé. C'est également une partie de notre graphique qui n'est pas complètement dynamique, car si quelqu'un ajoute un nouveau sujet, il utilisera la couleur par défaut. Peut-être qu’un moyen de contourner cela dans une application réelle serait d’avoir une couleur lors de la création d’un nouveau sujet stocké dans le magasin de données.
Enfin, ajoutons quelques titres d’axe des x personnalisés. Pour ce faire, nous devons travailler avec l’axe des x. Localisez l'emplacement de l'axe des x et modifiez le code pour effectuer les opérations suivantes:
CPTXYAxis * xAxis = [axisSet xAxis]; [xAxis setMajorIntervalLength: CPTDecimalFromInt (1)]; [xAxis setMinorTickLineStyle: nil]; [xAxis setLabelingPolicy: CPTAxisLabelingPolicyNone]; [xAxis setLabelTextStyle: textStyle]; [xAxis setLabelRotation: M_PI / 4]; NSArray * subjectArray = [self getSubjectTitlesAsArray]; [xAxis setAxisLabels: [NSSet setWithArray: sujetsArray]];
Il y a quelques changements dans le code ci-dessus. Premièrement, nous modifions la politique en matière d’étiquetage. Cela garantira que CorePlot n'imprimera pas l'étiquette elle-même et utilisera ce que nous lui avons donné. Ensuite, nous définissons la rotation des étiquettes afin qu’elle s’aligne mieux sur le graphique. Enfin, nous définissons la propriété 'Axis labels' qui prend un ensemble NSSet de valeurs NSString. Nous créons le NSSet en utilisant un NSArray créé par la méthode 'getSubjectTitlesAsArray'. Cette méthode n'existe pas encore, alors créons-la. Ajoutez la déclaration en haut du fichier .m, puis écrivez l'implémentation suivante:
- (NSArray *) getSubjectTitlesAsArray NSError * error = nil; NSFetchRequest * request = [[NSFetchRequest alloc] init]; NSSortDescriptor * sortDescriptor = [NSSortDescriptor sortDescriptorWithKey: @ "subjectID" croissant: OUI]; NSEntityDescription * entity = [NSEntityDescription entityForName: @ "STSubject" inManagedObjectContext: managedObjectContext]; [request setEntity: entité]; [request setSortDescriptors: [NSArray arrayWithObject: sortDescriptor]]; [request setResultType: NSDictionaryResultType]; [request setReturnsDistinctResults: NO]; [request setPropertiesToFetch: [NSArray arrayWithObject: @ "subjectName"]]; NSArray * titleStrings = [managedObjectContext executeFetchRequest: erreur de demande: & erreur]; NSMutableArray * labelArray = [tableau NSMutableArray]; CPTMutableTextStyle * textStyle = [CPTMutableTextStyle textStyle]; [textStyle setFontSize: 10]; pour (int i = 0; i < [titleStrings count]; i++) NSDictionary *dict = [titleStrings objectAtIndex:i]; CPTAxisLabel *axisLabel = [[CPTAxisLabel alloc] initWithText:[dict objectForKey:@"subjectName"] textStyle:textStyle]; [axisLabel setTickLocation:CPTDecimalFromInt(i + 1)]; [axisLabel setRotation:M_PI/4]; [axisLabel setOffset:0.1]; [labelArray addObject:axisLabel]; [axisLabel release]; return [NSArray arrayWithArray:labelArray];
Il y a beaucoup de choses dans le code ci-dessus. Afin de donner à un graphe des étiquettes personnalisées, nous devons passer un NSSet contenant des objets de type 'CPTAxisLabel'. Premièrement, nous obtenons un tableau de tous les noms de sujets classés par subjectID, qui seront donc dans le même ordre que le graphique. Ensuite, pour la quantité de noms que nous récupérons, nous parcourons et créons un CPTAxisLabel avec la chaîne de nom de sujet et un style de texte prédéfini. L'emplacement de la coche est la coche pour laquelle il apparaîtra. Nous devons ajouter 1 à notre valeur car nous commençons notre première barre à 1 au lieu de 0. Nous définissons ensuite une rotation et un décalage et nous les ajoutons à un tableau. Enfin, nous retournons le tableau de axisLabels.
Si nous sauvegardons et exécutons le projet, nous avons un graphique à barres coloré complet avec des étiquettes personnalisées.!
Nous avons beaucoup appris sur CorePlot cette session. Nous avons appris à créer un graphique à barres, à modifier les couleurs de la barre et même à ajouter des étiquettes personnalisées à l'axe..
La prochaine fois, nous verrons comment créer un graphique à secteurs impressionnant qui présente les mêmes données que le graphique à barres. Vous attraper la prochaine fois!