Après le grand ménage sur le blog, plein d’enthousiasme, j’ai entrepris de rédiger un tutoriel détaillé à propos du développement d’un ImageViewer pour iPhone, avec une interface la plus proche possible de l’application Photos
. Au cours de l’écriture de ce billet, j’ai constaté 2 choses:
- Tout d’abord, ça fait un billet sacrément long, à l’écriture comme à la lecture.
- Ensuite et surtout, j’ai constaté que l’intérêt était assez limité car l’exercice s’est révélé relativement simple.
En revanche, lors du développement de mon ImageViewer, il y a un aspect qui a attiré mon attention: l’extension d’un protocole. Ce point précis peut présenter une certaine difficulté pour peu qu’on n’y ai jamais été confronté et il m’a été assez difficile de trouver des exemples clair sur le web.
J’ai donc décidé de rédiger un billet plus court, qui détaille la façon de dériver la classe UIScrollView
tout en étendant le protocole UIScrollViewDelegate
associé.
Si vous souhaitez, comme moi, reproduire l’interface de l’application Photos
de votre iPhone, vous allez sans doute créer un UIScrollView
afin de permettre à l’utilisateur de naviguer d’une image à l’autre. Pour ce faire, le projet “Scrolling“ fourni en exemple dans la documentation d’Apple constitue un bon point de départ. La logique du scroll est contenue dans les méthodes viewDidLoad
et layoutScrollImages
du fichier MyViewController.m
mais il vous faudra l’adapter un peu à votre cas d’utilisation.
En revanche, j’ai constaté que les événements de Touch
n’étaient pas transmis par la UIScrollView
. Gênant lorsque l’on veut ajouter des interactions en plus du scroll.
Pour capturer ces événements, qui ne sont pas transmis par la UIScrollView
, la logique voudrait que l’on créé une classe qui étends la scrollView.
En surchargeant la méthode qui transmet les événements, on obtient ce qui suit:
1 | // TapScrollView.h |
À ce stade, il faut ajouter la méthode tap
au protocole qui défini le delegate
de notre TapScrollView
. On procède en ajoutant la définition d’un nouveau protocole dans le fichier TapScrollView.h
.
Ce protocole va étendre UIScrollViewDelegate
afin que l’on puisse encore recevoir les événements de touch, comme suit:
1 | // TapScrollView.h |
Si on en reste là, la propriété delegate
reste celle défini par UIScrollView
car nous ne l’avons pas surchargée. On peut donc supposer que celle-ci répond au protocole UIScrollViewDelegate
, et non pas TapScrollViewDelegate
comme on l’aurai souhaité. Dans ce cas, il suffit de surcharger la propriété delegate
dans TapScrollView
.
Voilà le code obtenu:
1 | // TapScrollView.h |
Ok, on approche du but. TapScrollView
réponds bien au protocole et la méthode tap
sera correctement appelée elle-aussi. En revanche, les méthodes du protocole UIScrollViewDelegate
ne sont plus appelés…
On tourne en rond.
J’ai mis pas mal de temps à trouver la solution. L’astuce consiste à surcharger aussi les accès à la propriété delegate
, de façon à transmettre les appels dans les deux sens (UIScrollView
vers TapScrollView
et vice-versa).
Voilà le code final:
1 | // TapScrollView.m |
Vous voilà donc avec une ScrollView
qui, en plus de capturer les événements relatifs au scroll, va transmettre les actions de votre choix. Ici, un simple tap
, mais le principe reste valable pour des actions plus complexes.
Quelques liens utilies pour finir:
- Scrolling : un sample project de la documentation Apple
- UIScrollViewDelegate Protocol Reference: tout ce que fait le protocole associé aux UIScrollView (et ce qu’il ne fait pas)
- Protocols: la documentation iPhone sur les protocoles