Blog d'un développeur multi-support

[DIM] pour les intimes :)

Débuter sur le développement iPhone

Salut,
Il m’est arrivé plusieurs fois qu’on me demande ce qu’il faut pour bien débuter sur iPhone. La question est simple, la réponse un peu moins. Je vais commencer par le plus simple, le matériel.

Matériel :

  • un Mac intel. Désolé mais vos vieux mac à la cave ne marcheront pas.
  • un de test. Le simulateur ne suffit pas.
  • une licence de développeur Apple. (Pas bien cher, 70€ je crois ..). Ceux qui disent  « Mais moi je jailbreak j’envoie mes appli en SSH et fuck Apple » je leur répond « Vous vous faites bien chier. » Et les solutions pour auto signer son code pour l’envoyer « comme en vrai » c’est pas trop la joie (faut refaire les manips pour chaque projets ..)

Sinon pour développer sur PC (windows notamment) sachez qu’on peut compiler des applis et se les envoyer en SSH etc. C’est faisable, mais alors quel perte de temps et vous verrez dans la suite de l’article qu’on y gagne pas tant que ça.

Logiciels :

  • Xcode le seul et unique IDE sympathique. Il auto-complète un peu, permet de compiler directement sur le téléphone sans prise de tête, fourni un debugger pas à pas.
  • Interface Builder. Ça c’est le truc tape à l’oeil  qu’Apple met en avant. C’est pour construire les écrans et relier les éléments graphiques à leurs représentations « code ». C’est super pratique et beaucoup plus ergonomique que de le faire sur Android :
    // Lie les champs graphiques à des champs codes
    EditText login = (EditText) findViewById(R.id.login);
  • Instruments. Super pratique pour voir l’état en temps réel de l’iphone : consommation CPU, RAM, allocations d’objets etc. C’est avec ce genre d’outils que tu te dis « en fait je ne sais pas coder léger »

Donc on voit bien que même s’il existe des solutions pour compiler sur PC, les « toolchain iphone » c’est quand même dommage de se séparer de ces logiciels. Encore que pour Xcode eclipse doit pouvoir suffir, les deux autres logiciels n’ont pas l’air d’avoir d’équivalent.

Et puis la finalité de développer sur iPhone c’est bien d’avoir son quart d’heure de gloire sur l’appStore non ? Alors autant commencer bien et dans la légalité. Car si Apple découvre que vous n’avez pas utilisé ses outils, que votre appli est dispo en jailbreak etc .. ben c’est foutu après.

Langage de programmation

Je suis passé par 3 phases quand j’ai commencé à programmer en objective-c.

  • Déroutant au début (retain une variable ? Kesako ?)
  • a l’air d’avoir des mécanismes complexes (le parsage d’XML est chelou quand on vient du web php/as3 etc)
  • Pratique et puissant quand on comprend les mécanismes par delegate, que l’on joue avec les threads, que l’on crée ses propres classes outils (comme pour ma classe de requete http)

Mais comment apprendre ce langage ? la réponse est simple : dans la documentation.

Documentation et

La documentation et les guides Apple sont bien pratiques pour appréhender le langage et les mécanismes.

Cependant pour appréhender Interface Builder et sa relation avec le code c’est pas trop ça. Je conseille les tutos d‘ipup.fr qui ont pas mal d’images et surtout que c’est français.

Sinon pour plus de liens, je vous conseille toujours les liens de mon précédent article « créer des applications iphone » et mon flux delicious :

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

Tags : ,

iPhone & NSTimer

Salut,

Les NSTimers sont bien cool et en général ça ne pose aucun souci à les utiliser. J’ai bien dit en général. J’ai eu un souci avec ce matin…vraiment étrange.

Sur un projet, j’en utilise un pour déclencher une méthode dans XX secondes une fois seulement. Ça marche impeccable. Sur un nouveau projet, je réutilise le même mais en faisant varier un paramètre « repeats » à YES. Et bien sur, ça ne marchait plus.

Voici un timer qui déclenche une méthode une seule fois :

1
2
3
4
5
6
7
8
-(void)blabla
{
	[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(test:) userInfo:nil repeats:NO];
}
-(void)test:(NSTimer*)timer
{
	NSLog(@"je suis appelé 1 fois");
}

Un timer qui se déclenche une méthode en boucle, techniquement il faudrait juste dire « repeats:YES » mais ca n’a pas marché dans mon cas. Le timer n’était jamais « fired » :p (je m’essaie à l’anglais)

1
2
3
4
5
6
7
8
-(void)blabla
{
	[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(test:) userInfo:nil repeats:YES];
}
-(void)test:(NSTimer*)timer
{
	NSLog(@"je suis appelé en boucle c'est la fête.");
}

Donc voici ce que j’ai utilisé pour que ça marche. J’ai forcé le démarrage du timer en boucle.

1
2
3
4
5
6
7
8
9
10
-(void)blabla
{
	NSTimer * timer = [NSTimer timerWithTimeInterval: 1 target: self selector: @selector(test:) userInfo: nil repeats: YES];
 
	[[NSRunLoop mainRunLoop] addTimer: timer forMode: NSDefaultRunLoopMode];
}
-(void)test:(NSTimer*)timer
{
	NSLog(@"je suis appelé en boucle c'est la fête.");
}

Voilà voilà

Tags : ,

iPhone & Trucs et Astuces

Bonjour tout le monde, encore de l’ .. et ouais j’aime bien faire des petits exemples :p

Cette fois ci à la demande non général de Sébastien H. voici quelques éléments de que j’utilise dans mes applications.  Donc voici ce qu’il y a dans cet exemple :

  • Comment créer et utiliser les préférences utilisateurs à travers l’objet NSUserDefaults et le fichier settings.bundle :p
  • Comment créer une vue modal. Vous savez ce genre d’écrans qui arrivent par le bas de l’application et qui repartent ensuite.
  • Je refait aussi un petit rappel sur les delegate iphone pour la vue modal.
  • Comment créer et utiliser le fameux menu d’actions à la façon safari pour permettre de fournir des boutons qui arrivent aussi par le bas de l’application (UIActionSheet)
  • Comment ouvrir d’autres applications installées sur l’iphone grâce à la méthode [UIApplication sharedApplication] :p

On m’a dit qu’il manquait un peu d’images, voici des screenshoots de l’application d’exemple :

Le design est assez simple ;p

Et n’oubliez pas de télécharger le projet Xcode de cet exemple

Tags : , , , ,

iPhone & Requete HTTP

Yop all,

A la demande général de Fabrice Bernhard, voici une classe que j’ai faite pour me simplifier la vie quand je dois faire une requête HTTP. Vous me direz « pas besoin blabla », mais cette classe gère l’envoie d’images, de sons en plus de simple paramètres POST classique. Vous faites moins les malins hein :) Et si je vous dit qu’elle gère aussi si la requête doit être fait en mode synchrone ou asynchrone hein ? Ça t’en bouche un coin ?

Bah en fait elle est très simple, j’ai juste joué au légo avec les classes Apple, mais c’est un lego qui me sert pas mal.

Voici un exemple d’utilisation, ce code est tiré de l’exemple que j’ai fait pour vous, disponible en téléchargement :

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
-(IBAction) send
{
// Crée la requete en mode asynchrone
HttpRequest *masuperRequete = [[HttpRequest alloc] initHttpRequest:formUrlAsk.text isSynchronous:false];
 
// Ajoute un parametre POST['cleParam'];
[masuperRequete addParam:@"cleParam" valeurs:formParam.text];
 
// Ajoute un fichier Image. Les parametres seront sous la forme file1, file2, file3 .. etc
[masuperRequete addImage:imageTmp.image];
 
// ajoute un son
// On doit recuperer les données du son sous la forme d'un NSDATA
// Ici le son est distant .. on le recupère donc avec the super classe en mode syncrhone
HttpRequest *sousReq = [[HttpRequest alloc] initHttpRequest:formUrlSound.text isSynchronous:true];
NSData * dataSound = [sousReq send];
 
// Recupere le nom du son
NSArray * mots = [formUrlSound.text componentsSeparatedByString:@"/"];
NSString *nameoffile = [mots lastObject];
 
[masuperRequete addSound:dataSound nameoffile:nameoffile nameinform:@"mamusique"];
 
// Envoie la superRequete
masuperRequete.delegate = self;
[masuperRequete send];
}
 
// y a un delegate pour recup le retour de la requete en mode asynchrone
-(void)downloadFinish:(NSMutableData *)data
{
NSLog(@"telechargement termine");
}

Maintenant voici le code source complet de l’exemple

Exemple de la classe HTTPRequest

Pour récupérer les données par la suite, rien de plus simple tout est dans $_POST et $_FILES.

maj : voilà le code source du fichier php que j’ai utilisé :

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
 
<?php
 
$content_dir = 'upload/';
 
if(count($_POST) > 0 || count($_FILES) > 0)
{
 
 
 
 
	if(count($_POST) > 0)
	{
		echo "variable POST : \n";
		foreach($_POST as $cle=>$val)
			echo $cle . ' => ' . $val ."\n";
 
		if(isset($_POST['monson']))
		{
			$test = base64_decode($_POST['monson']);
 
			$file = fopen("upload/son.caf","w+");
 
			fwrite($file,$test);
 
			fclode($file);
		}
 
	}
 
	if(count($_FILES) > 0)
	{
		echo "variable FILES : \n";
		foreach($_FILES as $cle=>$image)
		{
 
			$tmp_file = $image['tmp_name'];
 
			if(!empty($tmp_file))
			{
 
 
				if( !is_uploaded_file($tmp_file) )
				{
					exit("Le fichier est introuvable");
				}
 
				// on vérifie maintenant l'extension
				$type_file = $image['type'];
 
				if( !strstr($type_file, 'jpg') &#038;&#038; !strstr($type_file, 'jpeg') &#038;&#038; !strstr($type_file, 'bmp') &#038;&#038; !strstr($type_file, 'png') &#038;&#038; !strstr($type_file, 'gif') )
				{
					//exit("Le fichier n'est pas une image");
				}
 
				// on copie le fichier dans le dossier de destination
				$name_file = $image['name'];
 
				echo $cle. " => " .$name_file ." reçu \n";
 
				if( !move_uploaded_file($tmp_file, $content_dir . $name_file) )
				{
					exit("Impossible de copier le fichier dans $content_dir");
				}
 
			}
	}
}
}
else
{
	 $rep = "upload/";
	$dir = opendir($rep);
 
	while ($f = readdir($dir)) {
  	 if(is_file($rep.$f)) {
    		echo "<li>Nom : ".$f;
		echo '<a href="upload/'.$f.'"> DL </a>';
      		echo "<li>Taille : ".filesize($rep.$f)." octets";
      		echo "<br /><br />";
   		}
	}
}
 
 ?>

Précisons quand même que ma classe est en alpha, certaines fonctionnalités ne sont pas implémentés. Je pense notamment à la gestion des erreurs, le qui donne le taux de progression de l’upload etc. Je vous laisse le faire :p

Enjoy !

Image representing Apple as depicted in CrunchBase

Image via CrunchBase

Tags : , , , ,

iPhone & Delegate

Bonjour,

Voici juste un petit « How to » pour comprendre et jour avec les sur cocoa.

Admettons vous avez une classe « ListingController » qui hérite d’une UIViewController qui gère une liste d’élément et que vous avez une classe « DetailController » qui hérite aussi d’une UIViewController mais qui donne le detail de l’élément cliqué.

Vous voulez que lorsqu’on click sur un bouton posé sur la vue Détail revenir à la liste principal, puis la recharger. Revenir à la vue principal est assez simple il suffit de crée une méthode « IBAction » dans le controller Detail, liée le bouton à cette méthode via Interface builder puis écrire  :

1
2
3
-(IBAction)goHome {
[self.view removeFromSuperview];
}

Et le tour est joué mais bon, la liste n’est pas rechargé pour autant et il n’y a pas eu la levé d’un évènement pour la classe « Liste ». C’est là que les delegate peuvent nous être utile.

Le principe est de définir des méthodes sur la classe de Detail puis les appeller/utiliser lors du click mais c’est la classe Liste qui les implémentera effectivement.

Voici la marche à suivre :

  1. Dans la classe Detail : Définir une ou plusieurs méthodes dite « delegate » qui devront être implémenter. On appelle ce genre de déclaration un « protocole ».
  2. Dans la classe Detail : Définir une propriété de classe de type « id » qui utilise le protocole. Cette propriété représente un lien vers la classe « parente » qui implémentera effectivement notre protocole.
  3. Dans la classe Detail : Appeller lors du click les méthodes « delegate » sur notre protocole.
  4. Dans la classe Liste : Implémenter les méthodes delegate dans notre classe « parente ».

Etape 1 :

Dans le fichier « DetailController.h », juste après les #import et avant @interface DetailController : UIViewController { } :

1
2
3
4
@protocol DetailControllerDelegate
@required
-(void)RetourListe;
@end

Etape 2 :

Toujours dans le fichier « DetailController.h », après « @interface DetailController : UIViewController { » nous définissons une propriété que nous appellerons « delegate » :

1
id delegate;

puis après l’accolade définissant l’interface :

1
2
3
@property (nonatomic,assign) id < DetailControllerDelegate > delegate;
 
@end

Notre propriété « delegate » est de type « id » mais « implémente » le protocole précédement utilisé.

Etape 3 :

Nous avons définit une propriété dans le fichier « .h », il faut maintenant s’en servir dans notre fichier « DetailController.m » :

1
2
3
4
5
6
7
8
9
#import "DetailController.h"
@implementation DetailController
@synthesize delegate; //synthetisé une propriété signifie que le sdk créera les getters/setters pour nous
-(IBAction)goHome
{
	NSLog(@"Go home Liste");
	[self.delegate RetourListe]; // dispatch l'évènement à la classe parente.
	[self.view removeFromSuperview]; // supprime la vue courante
}

C’est fini pour notre classe Detail  ! Vous remarquerez qu’à aucun moment il n’y a de lien vers la classe « Liste ». Le couplage est donc très faible entre ces classes. Ce principe de couplage faible est assez puissant si on y réfléchi à deux fois vu que nos classes sont, de fait, totalement indépendantes vis à vis de leur « parent » (ou du contexte d’execution pour être plus bien parlant). Bon bref ça c’était le coup de pub raté pour la puissance du modèle objet.

Etape 4

Implémentons les méthodes ! Dans le fichier « ListingController.h » nous déclarons notre interface comme ceci :

1
2
3
@interface ListingController : UIViewController < DetailControllerDelegate > {
// some code
}

Et dans notre fichier « ListingController.m » il suffit d’implémenter la méthode « RetourListe ». Surtout, ne pas la déclarer dans l’interface (le fichier .h) sinon le programme se mélangera les pinceaux ! (Oui, vous utilisez deux méthodes avec le même nom ayant des portés différentes ..)

1
2
3
4
5
-(void)RetourListe
{
    NSLog("coucou");
    // some code
}

Edit : Oups, erreur. On crée la méthode mais à un aucun moment on dit que notre classe Listing va implémenter les méthodes de detail hormis dans la déclaration (fichier.h). Il faut donc qu’à notre objet « DetailController », juste après qu’il soit instanciée, au moment du click par exemple faire un :

1
2
DetailController*myView = [[DetailControlleralloc] initWithNibName:@"DetailView" bundle:[NSBundle mainBundle]];
myView.delegate = self;

On définit que c’est la classe Listing (self) va implémenter les méthodes delegate de détail.

Et voilà, normallement ça doit marcher.

Ce « How to » a été écrit à partir d’un projet personnel, je ne pourrais donc pas donnée des sources qui utilisent ce concept. A l’heure où j’écrit ce billet je n’ai pas de Mac à ma disposition.

Tags : , , , ,

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 &lt;AVFoundation/AVFoundation.h&gt; #import &lt;AudioToolbox/AudioToolbox.h&gt;
  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),
							 &#038;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 .

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 : , , ,