Les contrôles
Table View sont utilisés pour afficher des listes d'informations sur une colonne. Plusieurs applications fournies avec votre device utilisent un contrôle
Table View (figure suivante).
Les contrôles
Table View peuvent être composés de zéro (même si cela n'offre pas beaucoup d'intérêt), une ou plusieurs sections. Chaque section peut :
- comporter zéro, une ou plusieurs lignes ;
- être précédée d'un en-tête de section ;
- être suivie d'un pied de section.
Les sections sont identifiées par leur numéro d'index dans le tableau : première section, deuxième section, etc. Les lignes sont identifiées par leur numéro d'index dans une section : première ligne de la première section, deuxième ligne de la première section, etc.
L'utilisateur peut se déplacer verticalement dans un contrôle
Table View en utilisant une gestuelle de glisser. Lorsqu'il clique sur un des éléments listés, une vue détaillée de cet élément est affichée. La communication entre le contrôle
Table View et les différentes vues détaillées se fait
via un contrôle
Table View Controller.
Première approche
Pour faciliter l'écriture d'une application basée sur l'utilisation d'un
Table View et des vues détaillées correspondantes, le plus simple consiste à utiliser le modèle
Master-Detail Application.
Créez un nouveau projet basé sur le modèle
Master-Detail Application, cliquez sur
Next, donnez le nom « tableView » à l'application, choisissez le dossier de sauvegarde et validez en cliquant sur
Create. Une fois l'application créée, cliquez sur
MainStoryboard.storyboard dans le volet de navigation. Comme vous pouvez le voir à la figure suivante, un contrôleur de navigation, un contrôle
Table View et une vue détaillée ont été insérés dans l'application.
Exécutez l'application en cliquant sur
Run. Le contrôle
Table View est bien visible, mais il ne contient aucune donnée. Nous allons remédier à cette situation en définissant quelques données textuelles et en les reliant au contrôle
Table View.
La source de données peut provenir d'à peu près n'importe où : d'un tableau, d'un fichier XML ou d'une base de données par exemple. Pour que les choses soient aussi simples que possible, nous allons utiliser un tableau comme source de données. Cliquez sur
MasterViewController.h dans le volet de navigation et définissez l'objet
NSMutableArray *maListe :
Code : Objective-C | #import <UIKit/UIKit.h>
@interface MasterViewController : UITableViewController
{
NSMutableArray *maListe;
}
@end
|
Maintenant, cliquez sur
MasterViewController.m dans le volet de navigation. Pour que le tableau soit rempli dès le démarrage de l'application, nous allons ajouter quelques instructions dans la méthode
viewDidLoad :
Code : Objective-C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | - (void)viewDidLoad
{
[super viewDidLoad];
maListe = [NSMutableArray array];
[maListe addObject:@"Paris"];
[maListe addObject:@"Lyon"];
[maListe addObject:@"Marseille"];
[maListe addObject:@"Toulouse"];
[maListe addObject:@"Nantes"];
[maListe addObject:@"Nice"];
[maListe addObject:@"Bordeaux"];
[maListe addObject:@"Montpellier"];
[maListe addObject:@"Rennes"];
[maListe addObject:@"Lille"];
[maListe addObject:@"Le Havre"];
[maListe addObject:@"Reims"];
[maListe addObject:@"Le Mans"];
[maListe addObject:@"Dijon"];
[maListe addObject:@"Grenoble"];
[maListe addObject:@"Brest"];
self.navigationItem.title = @"Grandes villes";
}
|
L'instruction de la ligne 4 initialise l'objet
maListe :
Code : Objective-C | maListe = [NSMutableArray array];
|
Les instructions suivantes ajoutent des éléments dans
maListe en appliquant la méthode
addObject à l'objet
maListe. Par exemple :
Code : Objective-C | [maListe addObject:@"Paris"];
|
Enfin, la ligne 21 définit le titre qui sera affiché sur la première ligne du contrôle
Table View :
Code : Objective-C | self.navigationItem.title = @"Grandes villes";
|
Je sens que vous brûlez d'impatience de voir ces données affichées dans le
Table View. Allez, cliquez sur
Run.
…
Oh consternation ! Le contrôle
Table View est toujours vide !
Réfléchissez un peu. Tout ce qui a été fait jusqu'ici, c'est de créer un objet
NSMutableArray. Comment le contrôle
Table View pourrait-il supposer qu'il doit l'utiliser comme source de données ?
Pour cela, deux actions doivent être accomplies. Vous devez :
- indiquer au contrôle Table View combien de données il doit afficher ;
- relier les objets Table View et maListe.
Pour connaître le nombre d'éléments du tableau
maListe, vous utiliserez l'instruction suivante :
Code : Objective-C
La méthode prédéfinie
numberOfRowsInSection retourne un entier qui correspond au nombre d'éléments à afficher dans le
Table View. Par défaut, la valeur retournée est égale à
0 : aucune information n'est donc affichée. En remplaçant le
0 à la suite de l'instruction
return par le message
[maListe count], le contrôle
Table View sait combien d'éléments il doit afficher. Définissez la méthode suivante dans le fichier
MasterViewController.m :
Code : Objective-C | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [maListe count];
}
|
Il ne reste plus qu'à relier le
Table View au contrôle
maListe. Cette étape se fera grâce à la méthode
cellForRowAtIndexPath. Consultez la documentation Apple pour avoir une idée du contenu de cette méthode (figure suivante).
Les premières lignes (1) définissent un objet
cell de classe
UITableViewCell et le relient à une cellule du
Table View. Nous les reprendrons telles quelles.
Les dernières lignes (2) sont propres à l'exemple pris par Apple, nous allons donc les modifier. Dans le cas qui nous préoccupe, les cellules (
cell.textLabel.text) doivent être reliées aux éléments du
Table View (
[maListe objectAtIndex: …]) dont l'index correspond au numéro de ligne du
Table View (
indexPath.row). Voici le code complet de la méthode
cellForRowAtIndexPath :
Code : Objective-C 1
2
3
4
5
6
7
8
9
10
11
12
13
14 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = @"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
// Configuration de la cellule
NSString *cellValue = [maListe objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
return cell;
}
|
Les lignes 1 à 8 ainsi que la ligne 13 sont issues de l'aide Apple.
La ligne 11 définit l'objet
cellValue de classe
NSString (
NSString *cellValue) et y stocke l'élément du tableau
maListe (
[maListe …) qui se trouve à la ligne (
objectAtIndex) courante (
indexPath.row]).
Code : Objective-C | NSString *cellValue = [maListe objectAtIndex:indexPath.row];
|
La ligne 12 affecte la valeur obtenue à la ligne précédente à la cellule :
Code : Objective-C | cell.textLabel.text = cellValue;
|
Avant de cliquer sur
Run, vous devez encore dire à Xcode que les données à afficher dans le
Table View seront définies dans l'application. Comme à la figure suivante, cliquez sur
MainStoryboard.storyboard dans le volet de navigation (1), cliquez sur
Table View dans la zone d'édition (2), sur l'icône
Hide or show the Utilities (3) puis sur l'icône
Show the Attributes inspector (4). Choisissez enfin
Dynamic Prototypes dans la liste déroulante
Content (5).
Maintenant, vous pouvez cliquer sur
Run. La fenêtre du simulateur iOS devrait afficher quelque chose ressemblant à la figure suivante.
Une dernière petite chose. Avez-vous remarqué le point d'exclamation dans la partie supérieure de la fenêtre de Xcode ? Si vous cliquez dessus, un message d'erreur vous indique ce qui ne va pas. Ce dernier indique «
Prototype table cells must have reuse identifiers », soit en bon français « Le prototype des cellules du tableau doit avoir un identifiant ».
Comme indiqué à la figure suivante, cliquez sur le prototype des cellules dans la vue
Master (1), sur l'icône
Show the Attributes inspector dans le volet des utilitaires (2), puis définissez un identifiant dans la zone de texte
Identifier (3).
Utilisation de la vue détaillée
Les contrôles
Table View sont généralement utilisés avec une vue secondaire qui donne des détails sur l'élément sélectionné par l'utilisateur dans la liste. Nous allons voir comment utiliser cette vue dans l'application précédente. Rappelez-vous : lors de la création de l'application
tableView, une vue détaillée a été ajoutée au canevas (figure suivante). Reste donc à voir comment l'utiliser.
En observant cette figure, je vois que la vue Master n'est pas reliée à la vue Detail. Et pourtant, elle l'était tout à l'heure. Que s'est-il passé ?
Effectivement, ces deux vues étaient reliées, mais lorsque vous avez sélectionné
Dynamic Prototypes dans la propriété
Content de la vue
Master, le lien a été brisé.
Qu'à cela ne tienne, nous allons le recréer !
Si ce n'est pas déjà fait, affichez le canevas en cliquant sur
MainStoryboard.storyboard dans le volet de navigation. Ensuite, comme indiqué à la figure suivante, cliquez sur l'élément qui représente une cellule dans la vue
Master (1) puis contrôle-glissez-déposez cet élément sur la vue
Detail (2). Au relâchement du bouton gauche de la souris, sélectionnez
Push dans le menu (3).
La liaison entre les vues
Master et
Detail est maintenant rétablie (figure suivante).
Pour pouvoir y faire référence dans le code, vous allez lui donner un nom. Comme indiqué sur la figure suivante, cliquez sur le symbole qui identifie la liaison dans le canevas (1), sur l'icône
Hide or show the Utilities dans la barre d'outils (2), sur
Show the Attributes inspector dans le volet des utilitaires (3) puis donnez le nom « detailSegue » à la liaison (4).
Vous allez maintenant insérer un contrôle
Label dans la vue
Detail. Ce contrôle sera utilisé pour afficher des informations en relation avec l'élément sélectionné par l'utilisateur dans la vue
Master.
Une fois le contrôle
Label inséré dans la vue
Detail, associez-lui l'outlet
donneeRecue pour qu'il soit accessible dans le code.
Je pense que cette opération doit maintenant être habituelle pour vous, mais à tout hasard, je vais faire un rappel. Pour définir l'outlet
unMessage pour le contrôle
Label :
- dans la barre d'outils de Xcode, au-dessus du libellé Editor, cliquez sur l'icône Show the Assistant editor ;
- contrôle-glissez-déposez le contrôle Label dans le fichier d'en-têtes, juste au-dessus du @end final ;
- au relâchement du bouton gauche de la souris, donnez le nom « donneeRecue » à l'outlet et validez en cliquant sur Connect.
Le code du fichier d'en-têtes doit maintenant ressembler à ceci :
Code : Objective-C | #import <UIKit/UIKit.h>
@interface DetailViewController : UIViewController
@property (strong, nonatomic) id detailItem;
@property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
@property (weak, nonatomic) IBOutlet UILabel *donneeRecue;
@end
|
Lorsque l'utilisateur sélectionne un élément dans le contrôle
Table View, la vue
Detail remplace la vue
Master. Pour passer des informations de la vue
Master à la vue
Detail, Apple préconise d'utiliser la méthode
prepareForSegue. Malheureusement, il n'est pas possible d'atteindre directement le label
donneeRecue, vous devez passer par une variable intermédiaire. Cliquez sur
DetailViewController.h dans le volet de navigation et définissez la propriété
texteAAfficher comme suit :
Code : Objective-C | @property (strong, nonatomic) id texteAAfficher;
|
Le fichier
DetailViewController.h doit maintenant contenir les instructions suivantes :
Code : Objective-C | #import <UIKit/UIKit.h>
@interface DetailViewController : UIViewController
@property (strong, nonatomic) id texteAAfficher;
@property (strong, nonatomic) id detailItem;
@property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
@property (weak, nonatomic) IBOutlet UILabel *donneeRecue;
@end
|
Cliquez sur
DetailViewController.m dans le volet de navigation et ajoutez une instruction
synthesize pour pouvoir accéder à la propriété
texteAAfficher :
Code : Objective-C | @synthesize texteAAfficher = _texteAAfficher;
|
Ça y est, tout est en place pour insérer la méthode
prepareForSegue. Cliquez sur
MasterViewController.m dans le volet de navigation et insérez les instructions suivantes dans le code (peu importe l'endroit) :
Code : Objective-C | -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:@"detailSegue"])
{
NSInteger selectedIndex = [[self.tableView indexPathForSelectedRow] row];
DetailViewController *dvc = [segue destinationViewController];
dvc.texteAAfficher = [NSString stringWithFormat:@"%@", [maListe objectAtIndex:selectedIndex]];
}
}
|
Ne soyez pas impressionnés par l'apparente complexité du code : l'autocomplétion est votre amie. Ainsi par exemple, lorsque vous commencez à écrire les premières lettres de la méthode
prepareForSegue, une bulle s'affiche sur l'écran, comme à la figure suivante. Appuyez simplement sur la touche
Entrée pour recopier le texte proposé par l'autocomplétion.
La ligne 2 teste si l'identifiant de la transition entre la vue
Master et la vue
Detail a bien pour nom « detailSegue » :
Code : Objective-C | if([[segue identifier] isEqualToString:@"detailSegue"])
|
Rappelez-vous, ce nom a été défini un peu plus tôt. Et maintenant, vous l'utilisez dans le code.
La ligne 4 définit le
NSInteger selectedIndex et l'initialise avec l'index de la cellule choisie par l'utilisateur (
indexPathForSelectedRow) du contrôle
TableView de la vue
Master (
self.tableView) :
Code : Objective-C | NSInteger selectedIndex = [[self.tableView indexPathForSelectedRow] row];
|
selectedIndex vaudra 0 si l'utilisateur a choisi le premier élément. Il vaudra 1 s'il a choisi le deuxième élément. Ainsi de suite…
Maintenant, nous connaissons l'index de la cellule choisie par l'utilisateur. Encore faut-il accéder au
Label de la vue
Detail.
Pour cela, la ligne 5 définit l'objet
dvc de classe
DetailViewController (
DetailViewController *dvc) et l'initialise avec la vue qui va être affichée (
[segue destinationViewController]) :
Code : Objective-C | DetailViewController *dvc = [segue destinationViewController];
|
Il ne reste plus qu'à affecter le contenu de la cellule à la propriété
texteAAfficher. C'est précisément ce que fait la ligne 6. La propriété
texteAAfficher est initialisée avec l'élément du tableau
maListe d'index
selectedIndex. Cet objet est converti en un
NSString avant d'être stocké dans la propriété
texteAAfficher :
Code : Objective-C | dvc.texteAAfficher = [NSString stringWithFormat:@"%@", [maListe objectAtIndex:selectedIndex]];
|
Mais au fait, comment le code de la vue Master va-t-il pouvoir accéder au code de la vue Detail ?
Vous devez ajouter une instruction
import au début du fichier
MasterViewController.m, sans quoi
Master n'arrivera pas à « dialoguer » avec
Detail et plusieurs erreurs apparaîtront dans le code :
Code : Objective-C | #import "DetailViewController.h"
|
Après tous ces efforts, vous devez certainement être impatients de lancer l'application. Vous pouvez toujours le faire, mais je suis assez pessimiste quant au résultat obtenu : il est vrai que la vue
Master a indiqué à la vue
Detail quelle était la cellule sélectionnée par l'utilisateur. Mais rappelez-vous, cette indication a été fournie dans la propriété
texteAAfficher et non dans le
Label donneeRecue. Vous allez donc devoir agir sur le code de la vue
Detail. Cliquez sur
DetailViewController.m et ajoutez la ligne 6 à la méthode
viewDidLoad :
Code : Objective-C | - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
_donneeRecue.text = _texteAAfficher;
}
|
Cette ligne recopie simplement le contenu de la propriété
texteAAfficher dans le
Label.
Ça y est, vous pouvez lancer l'application et profiter du passage de données entre les vues
Master et
Detail. La figure suivante représente par exemple ce que vous devriez obtenir si vous choisissez « Toulouse » dans la vue
Master.
Les fichiers de cette application se trouvent dans le dossier
tableView2.
MasterViewController.h
Secret (cliquez pour afficher)
Code : Objective-C | #import <UIKit/UIKit.h>
@interface MasterViewController : UITableViewController
{
NSMutableArray *maListe;
}
@end
|
MasterViewController.m
Secret (cliquez pour afficher)
Code : Objective-C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142 | #import "MasterViewController.h"
#import "DetailViewController.h"
@implementation MasterViewController
- (void)awakeFromNib
{
[super awakeFromNib];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
maListe = [NSMutableArray array];
[maListe addObject:@"Paris"];
[maListe addObject:@"Lyon"];
[maListe addObject:@"Marseille"];
[maListe addObject:@"Toulouse"];
[maListe addObject:@"Nantes"];
[maListe addObject:@"Nice"];
[maListe addObject:@"Bordeaux"];
[maListe addObject:@"Montpellier"];
[maListe addObject:@"Rennes"];
[maListe addObject:@"Lille"];
[maListe addObject:@"Le Havre"];
[maListe addObject:@"Reims"];
[maListe addObject:@"Le Mans"];
[maListe addObject:@"Dijon"];
[maListe addObject:@"Grenoble"];
[maListe addObject:@"Brest"];
self.navigationItem.title = @"Grandes villes";
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [maListe count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//même que paramètre Identifier du Prototype Cells dans MainStoryboard.storyboard
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];
// Configuration de la cellule
NSString *cellValue = [maListe objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
return cell;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:@"detailSegue"])
{
NSInteger selectedIndex = [[self.tableView indexPathForSelectedRow] row];
DetailViewController *dvc = [segue destinationViewController];
dvc.texteAAfficher = [NSString stringWithFormat:@"%@", [maListe objectAtIndex:selectedIndex]];
}
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source.
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
@end
|
DetailViewController.h
Secret (cliquez pour afficher)
Code : Objective-C | #import <UIKit/UIKit.h>
@interface DetailViewController : UIViewController
@property (strong, nonatomic) id texteAAfficher;
@property (strong, nonatomic) id detailItem;
@property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
@property (weak, nonatomic) IBOutlet UILabel *donneeRecue;
@end
|
DetailViewController.m
Secret (cliquez pour afficher)
Code : Objective-C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 | #import "DetailViewController.h"
@interface DetailViewController ()
- (void)configureView;
@end
@implementation DetailViewController
@synthesize texteAAfficher = _texteAAfficher;
@synthesize detailItem = _detailItem;
@synthesize detailDescriptionLabel = _detailDescriptionLabel;
@synthesize donneeRecue = _donneeRecue;
#pragma mark - Managing the detail item
- (void)setDetailItem:(id)newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem) {
self.detailDescriptionLabel.text = [self.detailItem description];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
_donneeRecue.text = _texteAAfficher;
}
- (void)viewDidUnload
{
[self setDonneeRecue:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
@end
|