Blog d'un développeur multi-support

[DIM] pour les intimes :)

deux nouveaux articles iPhone !

Bonjour,

J’ai écrit deux nouveaux articles pour le compte de l’excellent blog technique d’elao voici les liens d’accès direct :

  1. http://www.elao.org/iphone/frameworks-iphone.html : Je présente rapidement le framework Three20 et son système de par URL
  2. http://www.elao.org/iphone/three20-menu-tttabstrip.html : J’explique comment créer un menu horizontale intelligent avec Three20

Dorénavant les articles iPhone seront annoncés ici mais mis en ligne sur le blog technique.

Tags : ,

Elao sur iPhone

Elao ?

Elao est la société qui m’emploie, elle est spécialisée dans le développement d’application web (avec ) et depuis peu sur .

Afin de montrer son savoir faire, la team iphone, dont je fais partie, a crée une petite application très classique pour voir les nouveautés de la société, voir ses références, etc.

Techniquement nous avons utilisé three20, un framework iPhone qui fournie de nombreuse classe et d’utilitaire bien pratique, comme la par URL.

Je vous invite à l’essayer et à me dire ce que vous en pensez. Disponible sur iTunes : http://itunes.apple.com/fr/app/elao/id375943180?mt=8

Tags : ,

Iphone & C#, drole de mariage

Aujourd’hui je suis tombé sur l’article de PC Inpact comme quoi une société propose un kit de développement (SDK) pour développer en C# des application native , son nom MonoTouch

De ce que j’ai compris, il faut quand même un mac, on code toujours sur Xcode, mais au lieu d’apprendre l’objective-c on le fait en C#. On utilise toujours Interface builder, on a toujours besoin d’une licence Apple… bref c’est tout pareil, sauf qu’on change de langage de programmation.

Je viens de regarder un monotouch pour créer un lecteur de flux RSS (quasi un des premier tuto que l’on fait en ) à cette adresse. J’ai été bluffé, ca a l’air presque trop simple :p

Mais bon, ceux que j’oublie de dire c’est qu’il faut mettre la main au portefeuille pour avoir ce kit, les prix vont de $399 à $3,999 PAR AN :/

Ça à l’air vraiment pas mal, mais bon à titre personnel je pense qu’à ce prix là je préfèrerais re-apprendre l’objective-C. Un bon développeur ne doit il pas être capable de changer de langage de programmation comme de chemise ?

ps : Ça ressemble à un bon cheval de troie pour les développeurs Microsoft, un peu comme l’est le kit Adobe dans la suite CS5 pour développer en Flash des applications natives. Tout le monde veut sa part du gâteau de l’App Store on dirait..

Tags : ,

Retour de vacances

Me voici de retour,

Je préviens que ce blog risque de ne pas être mis à jour pendant encore un moment. J’emménage à Lyon, je change de job, et je n’aurais plus de mac pour développez sur tout de suite. Donc pour les lecteurs «  » du blog désolé mais c’est chômage technique en vue.

C’est con, j’aurais bien aimer tester la réalité augmenté sur iphone grâce à http://code.google.com/p/iphonearkit. L’avez vous tester cette libraire vous ? Mais bon, je n’ai pas d’iphone 3GS non plus. D’ailleurs si vous avez un mac, un iphone 3GS que vous voulez me donner, y a pas de souci je prend :p

Petite annonce iphone : Je suis à la recherche de dev iphone sur Lyon, débutant ou confirmé. N’hesitez pas à vous signaler par mail, je ne mord pas.

Par contre, pour ceux qui viennent pour du PHP et pour Symfony vont être content. Mon nouveau job m’en fera faire 8h par jour, je parie que je vais découvrir pleins de trucs que je posterais sur ce blog. :p

Adieu objective-c, welcome PHP. (La tendance est de faire l’inverse, mais je ne suis pas comme les autres ;p)

Tags : , ,

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

Android vs Iphone

Aujourd’hui, je dois créer une application pour un projet de cours. VDM.

En effet, Android peut faire peur :

  • tout est en java
  • un simulateur horriblement moche
  • une documentation light light
  • pas d’outil « friendly » et fun pour faire des interfaces. Aucune vidéo « qui pete sa race »
  • propulsé par le dieu de l’information Google à grand coup de millions de $

Il est vrai que c’est rebutant à première vue et l’on peut penser que c’est un peu masochiste de developper sur Android. Mais de mon expérience « Iphonesque » je dirais que ça se vaut, voyez par vous même :

me fait peur :

  • tout est en Objective-C/C/C++ OMG
  • un simulateur esthétiquement jolie mais rien sous le capot
  • une documentation étouffante, y a des guides, des vidéos, des définitions de classes .. y en a trop à mon gout.
  • pas de génération de code comme avec eclipses, l’auto-completion mollassonne et pas franchement efficaces
  • propulsé par le dieu de la manipulation Apple et son cercle « VIP/expert » de m***

Chacun ses gouts après, si l’on est plus « ça pete c’est beau ca suffit » je dirais que l’iphone est plus adaptés qu’android. A contrario on veut faire du code sympa Android c’est plus abordable.

Perso, le code ça me botte plus qu’une jolie interface. Je préfère donc Android pour la philosophie qu’il a derrière. C’est en grande partie open-source, on peut avoir accès aux codes des autres, aux milliers de librairie JAVA qui existent plus simplement.

Ces prochains jours j’essaierais de faire des billets sur des exemples de de programmes sur android. Au programme : hello world, la gestions des boutons et menus, passez d’un écran à l’autre, faire des requetes Web, parser de l’XML, jouer avec les listes et la personnalisation des cellules.

Bonne journée et à bientôt pour une session Android :)

Tags : , ,