JXOrientation : simplifier la gestion des rotations du device.
JegnuX
Membre
Salut à tous.
Je vous présente une petite classe que j'ai réalisée : JXOrientation - https://github.com/JegnuX/JXOrientation
Alors à l'origine, j'ai fais cette classe pour m'amuser un peu avec le runtime. Je n'ai donc jamais utilisé cette classe dans un projet, et je ne garanti même pas sa pertinence /biggrin.png' class='bbc_emoticon' alt=':D' />
Mais au cas où je la partage quand même, des fois que ça donne des idées à certains /smile.png' class='bbc_emoticon' alt=':)' />
L'idée était de faire un sorte d'objet proxy un peu comme UIAppearance.
En gros toutes les UIView ou sous-classe d'UIView ont de nouvelles properties :
Ce sont donc des objets proxy (qui héritent de NSProxy).
On peut leur envoyer n'importe quel message que le receveur sache gérer.
Les invocations sont conservées de côté et ne seront invoquées que lors d'un changement d'orientation, dans l'ordre où elles ont été saisies.
Petit exemple :
J'ai créé mon interface portrait dans un xib, et j'ai rajouté ce code dans mon viewDidLoad :
Et quand je tourne, je passe de ça :
[img]http://cl.ly/image/2W3228242J2B/Capture d'écran 2012-07-19 à %2013.36.08.png[/img]
à ça :
[img]http://cl.ly/image/302n0n3h2W2J/Capture d'écran 2012-07-19 à %2013.36.12.png[/img]
Bon là ça casse pas trois pattes à un canard, mais sur une interface iPad composée de plusieurs blocs distincts mais positionné totalement différemment d'une interface à l'autre, ça peut être intéressant.
Après, comme j'ai dit, je m'en suis encore jamais vraiment servi, c'était un peu pour m'amuser avec le runtime (on retrouve du message forwarding, du associated objects, et du method swizzling).
Je suis donc ouvert à toutes vos remarques, critiques, idées d'amélioration etc... /smile.png' class='bbc_emoticon' alt=':)' />
Je vous présente une petite classe que j'ai réalisée : JXOrientation - https://github.com/JegnuX/JXOrientation
Alors à l'origine, j'ai fais cette classe pour m'amuser un peu avec le runtime. Je n'ai donc jamais utilisé cette classe dans un projet, et je ne garanti même pas sa pertinence /biggrin.png' class='bbc_emoticon' alt=':D' />
Mais au cas où je la partage quand même, des fois que ça donne des idées à certains /smile.png' class='bbc_emoticon' alt=':)' />
L'idée était de faire un sorte d'objet proxy un peu comme UIAppearance.
En gros toutes les UIView ou sous-classe d'UIView ont de nouvelles properties :
- (id) portrait;<br />
- (id) portraitStraight;<br />
- (id) portraitUpsideDown;<br />
- (id) landscape;<br />
- (id) landscapeLeft;<br />
- (id) landscapeRight;<br />
Ce sont donc des objets proxy (qui héritent de NSProxy).
On peut leur envoyer n'importe quel message que le receveur sache gérer.
Les invocations sont conservées de côté et ne seront invoquées que lors d'un changement d'orientation, dans l'ordre où elles ont été saisies.
Petit exemple :
J'ai créé mon interface portrait dans un xib, et j'ai rajouté ce code dans mon viewDidLoad :
- (void)viewDidLoad<br />
{<br />
[super viewDidLoad];<br />
[[orientationLabel portraitStraight] setText:@"Portrait"];<br />
[[orientationLabel portraitUpsideDown] setText:@"Portrait Upside Down"];<br />
[[orientationLabel landscapeLeft] setText:@"Landscape Left"];<br />
[[orientationLabel landscapeRight] setText:@"Landscape Right"];<br />
<br />
[[imageView portrait] setCenter:imageView.center];<br />
[[imageView landscape] setCenter:CGPointMake(240., 160.)];<br />
<br />
[[textView portrait] setFrame:textView.frame];<br />
[[textView landscape] setFrame:CGRectMake(20., CGRectGetMaxY(orientationLabel.frame), 150., 250.)];<br />
<br />
[[textView portrait] setBackgroundColor:[UIColor whiteColor]];<br />
[[textView landscape] setBackgroundColor:[UIColor blackColor]];<br />
<br />
[[textView portrait] setTextColor:[UIColor blackColor]];<br />
[[textView landscape] setTextColor:[UIColor whiteColor]];<br />
<br />
[[separatorView portrait] setHidden:NO];<br />
[[separatorView landscape] setHidden:YES];<br />
<br />
[[wrapperView portrait] setFrame:wrapperView.frame];<br />
[[wrapperView landscape] setFrame:CGRectMake(310., CGRectGetMaxY(orientationLabel.frame), 150., 150.)];<br />
}<br />
Et quand je tourne, je passe de ça :
[img]http://cl.ly/image/2W3228242J2B/Capture d'écran 2012-07-19 à %2013.36.08.png[/img]
à ça :
[img]http://cl.ly/image/302n0n3h2W2J/Capture d'écran 2012-07-19 à %2013.36.12.png[/img]
Bon là ça casse pas trois pattes à un canard, mais sur une interface iPad composée de plusieurs blocs distincts mais positionné totalement différemment d'une interface à l'autre, ça peut être intéressant.
Après, comme j'ai dit, je m'en suis encore jamais vraiment servi, c'était un peu pour m'amuser avec le runtime (on retrouve du message forwarding, du associated objects, et du method swizzling).
Je suis donc ouvert à toutes vos remarques, critiques, idées d'amélioration etc... /smile.png' class='bbc_emoticon' alt=':)' />
Mots clés:
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Vraiment bien foutu ton truc. C'est une bonne idée !
C'est une très bonne idée.
Par contre je me pose une question sur l'utilisation de NSProxy. Quel est l'avantage face à NSObject dans ce contexte précis.. juste parce que "moins lourd" ? Au départ NSProxy est surtout utile pour du IPC (Inter-Process Communication)
Mais au final c'était plus simple de faire comme j'ai fait de sorte à ce que ce soit universel (dans le sens où on peut appeler ce qu'on veut), plutôt que d'implémenter chacune de ces méthodes là .
Par exemple, on pourrait vouloir faire un "setNeedsLayout" pendant la rotation pour s'adapter. Et du coup ça fonctionne.
Après pour les magics numbers je suis d'accord. À la base le projet iPad qui m'a donné l'idée de cette classe contenait des vues composé de plusieurs blocs dispersé et pour le coup, les "magic numbers" étaient ce qu'il y avait de plus pratique :-/
Mais je vais essayer d'apporter une evolution qui me permettrai d'avoir des getters fonctionnels.
À l'heure actuelle si on fait un [[view landscape] frame], bah ça va juste rien faire ni rien retourner : ça va se contenter d'appeller "frame" pendant la rotation.
Du coup ce que je pensait faire, c'est quand on envoie un message, je check le selector, je met "set" devant et je fous une majuscule. Si je vois que la target repond à ce nouveau selector, je considère que celui de base est un getter. À ce moment là je récupère l'invocation du "setter", j'en récupère l'argument, et je le retourne.
et du coup après on pourrait faire du positionnement relatif type :
Sinon, quand a l'utilisation du NSProxy, en fait pour être franc, au début j'avais fait un NSObject, puis en écrivant ce post, quand j'ai parlé de proxy je me suis souvenu qu'il existait une classe NSProxy. Et quand j'ai lu la description ça m'a semblé parfaitement adapté :
Mais bon honnêtement dans ce cas là l'utilisation de NSProxy ne me parait pas inadapté non plus dans le sens on tu n'as pas besoin d'un objet réel, mais juste du forwarding