Avec ce tutoriel nous apprendrons à programmer une application iOS qui offre à l’utilisateur la possibilité d’habiller sa photo à partir de maquettes de magazines et de pouvoir publier le résultat sur les réseaux sociaux ‘facebook’ et ‘twitter’.
Vidéo du résultat final:
[embedyt]http://www.youtube.com/watch?v=CucHHI7697g[/embedyt]
Note: Le texte en rouge indique une tâche à réaliser en laboratoire.
Action 1 – Créons un nouveau projet de type “Single View” pour le ‘iPad’.

Action 2 – Renseignons les information de création du projet

Action 3 – Ajoutons au projet un ‘groupe’ nommé ‘Mes ressources’.

Action 4 – Ajoutons les trois images précédentes au projet.
Astuce: Il faut enregistrer dans ‘download’ puis, glisser vers le projet.

Action 5 – Plaçons deux contrôles de type ‘UIButton‘ au bas de l’écran et renseignons les propriétés ‘Type‘ et ‘Image‘ pour changer leur apparence.

Action 6 – Glissons ‘ctrl+clic’ le bouton ‘facebook’ vers le le contrôleur de la scène principale.

Action 7 – Renseignons les propriétés du lien du bouton ‘facebook’

Action 8 – Ajoutons le code suivant à la fonction ‘actionFacebook:
@IBAction func actionFacebook(sender: AnyObject) {
println("actionFacebook")
}
Action 9 – Testons l’app dans le simulateur:
Action 10 – Ajoutons une connexion sur le bouton ‘twitter’
// ViewController.swift
// TIM-Magazine.swift
import UIKit
class ViewController: UIViewController {
/// Fonction exécutée suite à un clic du bouton 'facebook'
@IBAction func actionFacebook(sender: AnyObject) {
println("actionFacebook")
} // actionFacebook
/// Fonction exécutée suite à un clic du bouton 'twitter'
@IBAction func actionTwitter(sender: AnyObject) {
println("actionFacebook")
} // actionTwitter
/// Fonction exécutée suite au chargement de la scène en mémoire
override func viewDidLoad() {
super.viewDidLoad()
} // viewDidLoad
} // ViewController
Nous allons maintenant ajouter une scène supplémentaire à notre projet.
Action 11 – Ajoutons un nouveau groupe nommé ‘Les couvertures’ au projet.

Action 12 – Dans le groupe ‘Les couvertures’, ajoutons un nouveau fichier.
Explication en classe de la notion de ‘XIB’ vs ‘StoryBoard’

Action 13 – Sélectionnons un fichier de type ‘iOS – User Interface – View’

Action 14 – Nommons la nouvelle scène

Action 15 – Modifions le fond de la scène et ajoutons un titre.

Note: L’ajustement de l’alpha du fond de la scène nous permettra de voir les éléments sous la scène lorsqu’elle sera ajoutée à la scène principale.
Il nous reste maintenant à charger la scène ‘magazine01’ par programmation.
Idéalement, cette scène devrait être affichée au démarrage de l’application.
Rappelle: La scène est une instance de la classe UIViewController.
La classe ‘UIViewController’ contient un membre de type ‘UIView’ qui permet d’afficher des éléments à l’écran.
La classe ‘UIView’ propose la méthode ‘addSubview’ pour ajouter des élements visuels à son canvas d’affichage.
Donc, pour ajouter un élément à la scène principale, il suffit d’appeler la méthode ‘addSubview(un objet visuel)’ du membre ‘view’ de l’instance de la classe de la scène.
Par exemple, pour ajouter un ‘UILabel’ à l’écran il suffit de programmer: view.addSubView(UILabel()).
Note: « self.view » est valide aussi.
Action 16 – Ajoutons le code suivant à la méthode ‘viewDidLoad’ du contrôleur de la scène principale.
override func viewDidLoad() {
super.viewDidLoad()
// Début de notre code...
// Créer la vue de 'Magazine01' par prog
var ecranMagazine = UINib(nibName: "Magazine01", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as! UIView
// Ajouter la nouvelle ‘View’ à la scène principale
view.addSubview(ecranMagazine);
} //viewDidLoad
Action 17 – Exécutons le projet dans le simulateur

Solution: Insérer la maquette avant les boutons.
Action 18 – Observons la structure des éléments de la scène

Action 19 – Modifions le code, pour ajouter le magazine avant les boutons ‘facebook’ et ‘twitter’
// Insérer la nouvelle ‘View’ avant les boutons fb et twitter
println("view.subviews.count: \(view.subviews.count)")
view.insertSubview(ecranMagazine, atIndex: (view.subviews.count - 2) - 1 )
// Ou bien ceci pour ajouter au haut de la liste
view.insertSubview(ecranMagazine, atIndex: 0)
Action 20 – Exécutons le projet dans le simulateur

L’approche précédente pose un problème, il faudra modifier l’indice d’insertion à chaque fois que nous ajouterons des éléments de contrôle à la scène principale.
Par exemple, un menu pour changer de magazine.
Il est possible de regrouper des objets visuels ensemble grâce à l’objet ‘UIView’.
Action 21 – Ajoutons un objet ‘UIView’ à la scène principale.

Action 22 – Remplaçons la valeur de paramètre ‘atIndex’ pour ‘view.subviews.count – 1″

Action 23 – Renseignons le fond de la scène principale à « noir » et le fond de la maquette ‘Magazine01′ à « Clear color’ (transparent).

Action 24 – Testons avec le simulateur:

Réflexion: Nous assumons que la ‘view’ du fichier XIB sera toujours à la position [0] du XIB. Si Apple change la position de la ‘view’, notre programme ne fonctionnera plus correctemnt.
La méthode recommandée par Apple pour charger la ‘view’ du fichier XIB est la suivante:
var ecranMagazine = UIView()
// Parcourir tous les éléments du fichier
for x in UINib(nibName: "magazine01", bundle: nil).instantiateWithOwner(nil, options: nil) {
// si objet courant de type 'UIView' alors renseigner notre variable
if x.isKindOfClass(UIView) {
ecranMagazine = x as! UIView
} // if
} // for
Téléchargement du projet à cette étape.
Action 25 – Vous devez réaliser les maquettes suivantes:
Note: Pendant l’étape d’élaboration des maquettes, il est recommandé de fixer la couleur de la scène à noir. Cela va permettre de distinguer le texte blanc. Nous changerons le fond de ‘noir’ à ‘transparent : clearcolor’ à l’étape de chargement des interfaces.
Astuce: Pensez à copier/coller le fichier Magazine01.xib vers 02..04.xib.




Action 26 – Ajoutons un ‘UISegmentedControl’ dans la section interactive.


Résultat final:

Définissons un lien IBAction sur le ‘UISegmentedControl’

/// Fonction exécutée suite à une sélection dans le 'UISegmentedControl'. Note: Doit-être liée au UISC.
@IBAction func actionTournerPages(sender: AnyObject) {
let selection = (sender as! UISegmentedControl).selectedSegmentIndex
println("actionTournerPages: la sélection vaut: \(selection)")
}
@IBAction func actionTournerPages(sender: AnyObject) {
// 1 - Retirer le magazine courant de la scène
// 2 - Construire une chaine de caractères qui décrit le nom du fichier: 'Magazine0' + selectionCourante + 1
// 3 - Charger le magazine à partir d’un nom d’un fichier NIB
// 4 - Ajouter le magazine à la scène principale
}
PRÉ-REQUIS – Configuration des comptes sociaux sur l’appareil iOS.
Note: Au moment d’écrire cet exercice, le social.FrameWork n’était pas encore disponible dans la librairie iOS version 8. Assurez-vous de renseigner le version 7.x dans le paramètre de déploiement du projet.


Capture d’une Vue vers un objet UIImage
func sauvegarderEcran(){
// Description : méthode servant à capturer l’écran et au besoin,
// en faire une sauvegarde dans l’album photos.
// 1 - Préparer un contexte de dessin à partir de la taille de la scène
UIGraphicsBeginImageContext(self.view.bounds.size);
// 2 – Dessiner à partir du claque par défaut de la scène
self.view.layer.renderInContext(UIGraphicsGetCurrentContext());
// 3 – Stocker le résultat dans notre objet local
imageFinale = UIGraphicsGetImageFromCurrentImageContext();
// 5 – Fermer le contexte de dessin
UIGraphicsEndImageContext();
// 6 – Facultatif - Stocker une copie de la capture d’écran dans l’album photos
UIImageWriteToSavedPhotosAlbum(imageFinale, nil, nil, nil );
} // sauvegarderEcran
Vérifions la présence de la capture dans l’album de photos.
Envoyer un ‘post’ vers Facebook
import Social
func posterSurFacebook() {
// Les étapes pour utiliser ‘facebook’
// 1 - Tester si le service et les informations de connexion sont dispo
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeFacebook)
{
// 2 - Créer un feuille pour le 'post'
let controleur = SLComposeViewController (forServiceType: SLServiceTypeFacebook)
// 3 - Composer le message
controleur.setInitialText("Test avec Swift et Xcode");
// 4 - Ajouter une image - facultatif
controleur.addImage(imageFinale);
// 5 - Ajouter un lien - facultatif
controleur.addURL(NSURL(fileURLWithPath:"/cours/xcode/"));
// 6 - Présenter la fenêtre de confirmation à l'utilisateur
self.presentViewController(controleur, animated: true, completion: nil);
} // if Facebook
} // posterSurFacebook
Modifions la méthode ‘actionFacebook’.
@IBAction func actionFacebook(sender: AnyObject) {
println("actionFacebook")
sauvegarderEcran()
posterSurFacebook()
} // actionFacebook
Action – Testons l’application
Action – Modifiez le méthode actionTwitter
Il reste à cacher la zone menu avant de capturer l’écran.
Définissons un IBOutlet sur la View du menu.

Ajoutons le code suivant à la méthode capturerEcran.
func sauvegarderEcran(){
// Cacher le menu
leMenu.hidden = true
// 1 ...
// 6
leMenu.hidden = false
} // sauvegarderEcran
Note: Cette étape est facultative. Il n’y aura pas d’explication en classe, Si vous la réalisez, la correction du projet se fera sur 12/10.
Le contrôle ‘UIScrollView’ permet d’afficher un contenu plus grand que sa zone d’affichage.
Une gestuelle sur l’écran donne accès au contenu non visible.
Méthode d’utilisation du contrôle:
1 – Placer le ‘UIScrollView’ sur une scène,
2 – Par programmation, ajouter des objets dans le ‘UIScrollView’ en renseignant correctement les positions x/y,
3 – Renseigner la propriété ‘UIScrollView’.contentSize
func chargerLesMagazines() {
// Renseigner la largeur de la zone de contenu du scrollView en fn du nb de pages.
let pagesScrollViewSize = zoneAffichageDesElements.frame.size
zoneAffichageDesElements.contentSize = CGSizeMake(pagesScrollViewSize.width * Float(nbMagazines), pagesScrollViewSize.height)
for page in 0..<nbMagazines {
// Placer les Views un à la suite de l'autre sur le plan des 'x'
var frame:CGRect = zoneAffichageDesElements.bounds
frame.origin.x = frame.size.width * Float(page) // la première page (0) sera à x = 0
frame.origin.y = 0
// Charger le 'xib' courant
var nomNIB = "Magazine0\(page+1)"
println(nomNIB)
if var newPageView = UINib(nibName: nomNIB, bundle: nil).instantiateWithOwner(nil, options: nil)[0] as? UIView {
newPageView.frame = frame;
// Ajouter au scrollView
zoneAffichageDesElements.addSubview(newPageView)
} // if newPageView
} // for page
} // chargerLesMagazines()
Testons
Activons le ‘paging enable’
Ajoutons un UIPageControl (indicateur de la page courante/nbPages)
Expliquer Délégation
// Une des Méthodes de délégation de UIScrollView
func scrollViewDidEndDecelerating(scrollView: UIScrollView){
println("scrollViewDidEndDecelerating")
let positionPage = Int(zoneAffichageDesElements.contentOffset.x / zoneAffichageDesElements.frame.size.width)
indicateurDePages.currentPage = positionPage
} // scrollViewDidEndDecelerating
Remplaçons le code de la méthode ‘viewDidLoad.
override func viewDidLoad() {
super.viewDidLoad()
// Début de notre code...
// L'ancien code de chargement du magazine01 doit-être supprimé.
chargerLesMagazines()
} // viewDidLoad
FIN du laboratoire