Blog d'un développeur multi-support

[DIM] pour les intimes :)

iPhone & AVAudioPlayer

Aujourd’hui, j’ai bataillé pour lancer un mp3 au lancement d’une application. Tellement bataillé que je vais mettre ici le code qui va bien pour que je puisse le retrouver rapidement :) Donc peu d’explication, ceci n’est pas un tutorial.

  1. Inclure le framework AudioToolBox & AVFoundation
  2. Faire les imports suivants : #import <AVFoundation/AVFoundation.h> #import <AudioToolbox/AudioToolbox.h>
  3. Inclure le fichier à jouer dans le projet dans le dossier « ressources »
  4. Déclarer une propriété de classe AVAudioPlayer * audioPlayer;

Et voici le code qui va bien :

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
	// Initialise un contexte Audio
	AudioSessionInitialize (
							NULL,                          // 'NULL' to use the default (main) run loop
							NULL,                          // 'NULL' to use the default run loop mode
							NULL,  // a reference to your interruption callback
							self                       // data to pass to your interruption listener callback
							);
 
	// Definit quel type de son on va joué
	UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
	AudioSessionSetProperty (
							 kAudioSessionProperty_AudioCategory,
							 sizeof (sessionCategory),
							 &sessionCategory
							 );
 
	// Définit quel fichier on utilise pour le son
	NSData *soundFileData;
	soundFileData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"music.mp3" ofType:NULL]]];
 
	// Initialise notre lecteur avec les données du fichiers son à jouer
	audioPlayer = [[AVAudioPlayer alloc] initWithData:soundFileData error:NULL];
 
	// Precharge le son
	if(!([audioPlayer prepareToPlay])){
		NSLog(@"myAudioPlayer:prepareToPlay returned FALSE");
	}
 
	// Définit le delegate sur la classe courante
	audioPlayer.delegate = self;
 
	// Définit le volume
	[audioPlayer setVolume:1.0];
 
	// Joue le son !
	[audioPlayer play];

Voilà, la seul différence avec les codes que l’on peut trouver un peu partout est l’ajout du Session Audio. Si je l’initialise pas le son ne fonctionne que sur le simulateur et pas sur le mobile. Je ne sais pas trop pourquoi.

Merci à fpillet du channel irc #iphonedev sur freenode pour son aide.

Tags : , , ,

Iphone & UIButton & Multilangue

Vaste programme pour ce billet :) En fait nous allons modifier un bouton en fonction de la langue du téléphone.
Et nous allons créer un état « survolé » à notre bouton par programmation. InterfaceBuilder n’étant pas très clair sur cette manipulation.

Tout d’abord il nous faut un UIButton déclaré en tant que IBOutlet UIButton dans notre classe. Puis nous relions ce bouton via InterfaceBuilder avec un bouton sur notre vue. Dans les propriétés de celui ci vous pouvez dire que c’est un « custom button ». Faites le. Et nous revenons à XCode :

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
-(void)viewDidLoad
{
	// Gestion du multilanguage
	NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
	NSArray* languages = [defs objectForKey:@"AppleLanguages"];
 
	// preferredLang vaut "fr", "en", "de", etc 
	preferredLang = [languages objectAtIndex:0];
 
	// Méthode avec deux jeux de langues : Française ou Anglaise dans les autres langues 
	if([preferredLang isEqualToString:@"fr"])
	{
		UIImage * higlight = [UIImage imageNamed:@"fr_btn_clik.png"];
		[btnTest setBackgroundImage:higlight forState:UIControlStateHighlighted];
		[higlight release];
 
		UIImage * normal = [UIImage imageNamed:@"fr_btn.png"];
		[btnTest setBackgroundImage:normal forState:UIControlStateNormal];
		[normal release];
	}
	else 
	{
		UIImage * higlight = [UIImage imageNamed:@"en_btn_clik.png"];
		[btnTest setBackgroundImage:higlight forState:UIControlStateHighlighted];
		[higlight release];
 
		UIImage * normal = [UIImage imageNamed:@"en_btn.png"];
		[btnTest setBackgroundImage:normal forState:UIControlStateNormal];
		[normal release];
	}
 
	// Mais nous pouvons aussi concaténer le code langue avec le chemin de l'image.
	// dans ce cas là il nous faut autant d'image que de langue possibles.
	NSString * pathImage = @"_btn.png";
	NSString * pathImageClik = @"_btn_clik.png";
	UIImage * higlight = [UIImage imageNamed:[pathImage stringByAppendingString:preferredLang ] ];
	[btnTest setBackgroundImage:higlight forState:UIControlStateHighlighted];
	[higlight release];
 
	UIImage * normal = [UIImage imageNamed:[pathImageClik stringByAppendingString:preferredLang ]];
	[btnTest setBackgroundImage:normal forState:UIControlStateNormal];
	[normal release];
 
}

Simple non ?

Après c’est sur cette méthode est un peu lourde. Il faut autant d’images que de langage et on n’utilise pas les techniques Apple pour le multilangue (avec leurs histoire de Bundle par langue, un dictionnaire de traductions etc).

Cependant, si comme vous avez affaire à des boutons très personnalisés (typo exotique, disposition du texte particuliere), il est peut être plus rapide de tout passer en image comme ici.

Chacun fait comme il le sent après ^^

Tags : , , , ,

iPhone & UIView

Connaissez vous l’attribut « tag » d’une UIView ?

Cette propriété sert à différencier les vues les unes des autres. Il s’agit d’un entier qui, par défaut, est géré par l’. Mais on peut la fixer à la main et cela permet quelque liberté. En voici une utilisation :

Admettons que vous avez une vue centrale qui sert de menu en « footer » et que vous n’utilisez pas les composants de navigations par défaut du téléphone.

Lors d’un clic sur un bouton du menu « footer », vous allez ajouter une nouvelle vue par dessus votre écran principal en laissant le footer de la vue principal visible. Seulement voilà, à chaque clic sur un bouton du menu, vous allez superposer une vue à chaque fois. Question performance c’est pas tip top.

Alors une première approche est déjà de faire un bouton retour dans la nouvelle vue comme ceci :

1
2
3
4
5
- (IBAction)back {
 
NSLog(@"back");
[self.view removeFromSuperview];
}

Mais bon rien n’empêche l’utilisateur de clicker sur les éléments du footer au lieu de faire retour. Notez que même si cette nouvelle vue est ajouté par dessus la principale et la masque complètement, les autres boutons de la vue principale sont encore actifs. Sauf si on les désactive lors du click sur le bouton et qu’on les réactives lors de l’action « back » précédemment crée, via une méthode delegate.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
// Dans la vue qui se superpose
- (IBAction)back {
	NSLog(@"back");
	[self.delegate RetourMenu];
	[self.view removeFromSuperview];
}
 
// Dans la vue principale
-(void)RetourMenu
{
	NSLog(@"Réactivation des boutons "cachés" par la nouvelle superposés");
	btnVue1.enabled = YES;
	btnVue2.enabled = YES;
	btnVue3.enabled = YES;
 
}

Il faut maintenant gérer les vues afin d’éviter les superposements inutiles. Ceci se fait via la propriété tag. Personnellement j’ai définit le tag de ma vue principal à 100 via Interface Builder. Mais je pense qu’un self.tag = 100 dans le viewDidLoad marche aussi.

Puis voici comment je change de vue :

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
- (IBAction)ClickMenu{
	// Vide l'écran de toutes vues, sauf celle de l'écran principale
	NSArray *subviews = [[self.view superview] subviews];
	UIView *view;
	for (view in subviews)
	{
		// Le tag 100 correspond à la vue "Menu Principale"
		if(view.tag != 100)
		{
			[view removeFromSuperview];
		}
	}
	// Définit la vue courante et le gestionnaire d'évènement de MaVueSuivante
	MaVueSuivante*myView = [[MaVueSuivantealloc] initWithNibName:@"MaVueSuivanteNib" bundle:[NSBundle mainBundle]];
	myView.delegate = self;
 
	// Recupère le singleton de l'application courante
	MonProjetAppDelegate *app = (Lacoste_0_MonProjetAppDelegate *)[[UIApplication sharedApplication] delegate];
	[app.window addSubview:myView.view];
 
	// Désactivation des boutons "cachés" par la nouvelle vue
	btnVue1.enabled = NO;
	btnVue2.enabled = NO;
	btnVue3.enabled = NO;
 
}

Simple non ?

Enfin pour rendre une vue par dessus une autre tout en gardant la vue principal visible j’utilise la propriété « bounds » de la vue à afficher comme ceci :

1
2
3
4
- (void)viewDidLoad
{
	view.bounds = CGRectMake(0, 0, 320, 450); // Une hauteur de -30 pixels par rapport à la normal. 
 }
Tags : , , ,

iPhone & TableView

Coupé depuis 1 mois d’internet à domicile, je n’ai pas trop le temps de blogger au boulot… Ne faisans pas trop de veille technologique et ne pouvant parler des projets d’entreprises je n’ai pas grand chose à raconter sous forme de long .

J’entame donc une nouvelle façon de blogger mes découvertes : à travers de brêves. Aujourd’hui, pour renouer avec le lectorat «  », il sera question de TableView !

TableView

Avez vous déjà essayé de rendre une ligne sur deux d’une couleur différente (le background, les textes des labels et leurs états « survolés » ? Hey bien c’est la merde ! Voici la solution que j’ai pu trouver ici et là.

  • Avoir une classe qui gère une cellule.
  • Avoir une méthode de colorisation efficace pour la cellule
  • Détecter si la cellule courante est pair ou impair.

Lire la Suite

Tags : , , , ,

Tutoriel Iphone

Bonjour,

Connaissez vous Weecast.fr ? Mais si voyons, le tout nouveau  service d’earling d’emob !

Je parcourais un peu le site pour voir si il y avait des tutoriaux vidéos pour programmeur, et hormis les vidéos de video2brain sur Flex qui sont intéressante il y a peu de choses qui m’interpellait. Et c’est là que je voix « Xcode » dans leurs menu avec trois tutoriaux d’objective-c dont un parlais directement de l’iphone.

Il est disponible à cette adresse et vous apprendrez autant que sur le sur developpez.com à savoir :

  • Cliquer sur un bouton pour déclencher une méthode classe

A la différence d’un énième hello world pour l’. Il y a cependant un petit truc d’interessant c’est la gestion du clavier virtuel. Au final on passe 15 mn pour apprendre à gérer correctement le clavier, c’est bon à prendre.

Je regrette simplement que sur la le commentateur ne commente pas les choses vraiment utile. On s’en fou qu’il faut mettre un point virgule ou qu’il est en train d’ouvrir une accolade non ?

Je pense qu’il aurait mieux fait de dire, par exemple, pourquoi il doit écrire du @property (retain, nonatomic) UILabel *monChamp dans l’entete de la classe (fichier .h) et @synthesize monChamp; dans l’implémentation effective de la classe (fichier .m). Enfin bon rien ne remplace de la bonne documentation pour ce genre de question. Et pendant que j’y suis il aurait pu dire deux mots sur les delagate qu’il utilise pour le clavier. Là on dirait que tout sort d’un chapeau de magicien.

Donc oui les tutoriaux vidéos c’est cool, c’est mode, et ca fait gagné du temps mais quitte à en faire un soyez le plus explicites possibles !

En tout ca, merci apple pour la documentation textuels dg vidéos de qualité.

ps : Si vous voulez suivre mes « découvertes » iphone,  mon flux delicious est constamment mis à jour ! http://delicious.com/onishinji/iphone

Tags : , , ,

Créer des applications Iphone

Mise à jour 29/07/09 : Cet article date d’un peu .. sa version raccourci et plus clair est disponible sur Débuter sur le développement iPhone ! Have Fun :p

Cet article a pour but de vous expliquer comment créer une application .
Afin d’éviter un abus de langage, nous différencions deux types d’applications potentiels :

•    Les applications web : ouvert via Safari et qui ne sont ni plus ni moins un site dédié au format de l’iphone.
•    Les applications embarqués : Application directement téléchargé sur le iphone store (gratuitement ou pas) pour lequel l’utilisateur doit donner son mot de passe pour l’installer.

Cet article traitera principalement du 2e type d’application.

Lire la Suite

Tags : , , ,