• Billet écrit dans : Mobile, iPhone 18.03.2009 Aucune réponse à cet article.

    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.

    Billet écrit dans : Mobile, iPhone 18.03.2009 Aucune réponse à cet article.
  • Billet écrit dans : Mobile, iPhone 08.03.2009 3 Réactions !!

    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 ^^

    Billet écrit dans : Mobile, iPhone 08.03.2009 3 Réactions !!
  • Billet écrit dans : Mobile, iPhone 08.03.2009 Aucune réponse à cet article.

    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’iphone. 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. 
     }
    Billet écrit dans : Mobile, iPhone 08.03.2009 Aucune réponse à cet article.
CV Guillaume chave