Application pour un forum : Balises

LarmeLarme Membre
septembre 2013 modifié dans Vos applications #1

Bonjour tout l'monde.


 


J'ai toujours en tête de créer une application pour un site web.

Je sais que je vais passer par des WebServices comme il m'a été conseillé précédemment. J'ai commencé à  les utiliser pour une autre applications, donc pas de soucis à  ce niveau-là .


 


Je ne vais pas ici parler du comment optimiser au mieux mes chargements dans une UITableView (là , je sais que j'ai pas mal de lecture et que ça a été discuté pas mal de fois ici, j'f'rais une p'tite recherche le moment venu).


 


Non, ici, je me pose la question sur quel est le meilleur moyen pour montrer les messages de manière plus complexe.

En effet, imaginons que je reçoive un post de forum (via mon WS). Il contiendra sans doute des balises (gras, soulignés, couleur, taille, etc.). Je pense donc parser rapidement ça et jouer avec des AttributedStrings.


 


Là , où ça va devenir plus complexe, c'est concernant deux choses :


- Liens (qui n'est pas une simple URL, mais un lien derrière un mot/texte)


- Images (insertion d'une image)


 


À votre avis, qu'est-ce qui est le mieux ?

Faire en sorte que ce que mes cells contiennent des UIWebView (qui sont assez " longues " à  charger la première fois) ? des UITextView ?

Comment vous géreriez l'insertion des images ? En les regroupant tout en bas du post, et en les touchant, une nouvelle vue apparaà®t et on la voit en " grand " ?

Pour les liens, je pourrais mettre le texte en " clair ", suivi entre parenthèse de l'URL, mais je me verrais sûrement confronté à  un problème d'URL à  rallonge.


Réponses

  • Je n'ai pas de réponses mais deux remarques :

    -tu ne dis pas si l'utilisateur va pouvoir modifier le texte ou les images, ça peut avoir son importance.

    -tu melanges une problematique technique (conception) et design (spécification). Ce qui est normal et sain pour un developeur. Mais du coup, ça te limite surement dans le choix des design possibles.
  • LarmeLarme Membre
    septembre 2013 modifié #3

    L'utilisateur ne pourra pas modifier à  la volée. Juste voir.


    Il pourra éditer (ses propres messages), mais "verra" les balises, et ça s'ra une textview.


     


    Pour illustrer :

    Je reçois :



    Hello tout l'monde.
    Vous connaissez ce [url=http:/google.com]site[/url] ?
    Y'a une superbe image trop lol : [img]youhou[/img].
    À plus sous l'bus.

    Comment le montrer à  l'utilisateur final, en bref.

    Et s'il veut éditer le message, il le verra ainsi.


  • AliGatorAliGator Membre, Modérateur
    Avec OHAtteibutedLabel et un custom parser sur le modèle de ceux que je fournis déjà  ?


    Ceci dit ça ne gèrera pas les images. Pour une mise en forme complexe avec des images au milieu tu n'as pas 36 choix :

    - CoreText (efficace mais potentiellement lent à  faire un rendu dans ton cas)

    - WebView
  • LarmeLarme Membre
    octobre 2013 modifié #5

    Bon, j'ai eu le temps de m'y atteler, mais j'suis tombé par hasard sur une piste suite à  ce poste :
    http://stackoverflow.com/questions/19299556/how-to-make-key-and-key-clickable-in-ios7
    http://stackoverflow.com/questions/12884520/get-word-from-tap-in-uitextview


     


    Cela me permettrait de passer outre les UIWebView qui sont trop lourdes à  mon goût...

    Je regarderais si j'peux pas ajouter une sorte de Attributed spécial qui contiendrait une référence d'URL, avec la possibilité par exemple, de mettre un mini-icône (en fonction de la taille du texte, peut-être la taille d'un " M " et ainsi rendre les images visibles lorsqu'on fait un touch dessus, ce qui par ailleurs pourrait permettre l'insertion de smiley par la même occasion)... Par contre, pour l'Attributed custom, je ne sais pas ce que ça peut réellement donné, j'ai pas encore eu le temps de faire joujou avec. Donc soit lui refourguer un paramètre NSString/NSURL en plus ou garder une référence des toutes les URLS dans la UITextView...


     


     


    à‰dit : Encore mieux !


    Apparemment, y'a textView:shouldInteractWithURL:inRange avec iOS7 !

    Va falloir que je regarde tout ça...


    Re-à‰dit : Apparemment, cette nouvelle méthode permet de faire du tri sur les liens qui sont déjà  détectables actuellement...


  • LarmeLarme Membre
    octobre 2013 modifié #6

    J'ai eu le temps de creuser un peu plus...


    J'aurais voulu passer par des Attributs (de NSAttributedString Perso), mais je n'arrive pas à  les récupérer par la suite).


    Du coup, j'ai un Array avec des objets du type (Range, Link)...


     


    L'idée :


    J'ajoute un array (contenant Ranges & Links) pour savoir quel caractère correctement à  quel lien.

    Je rajoute un TapGestureRecognizer sur mon UITextView.


    Je détecte le tap, je cherche quel mot/caractère c'était, je regarde via le Range s'il y a un lien derrière.

    Si c'est le cas, je notifie mon delegate.

    De là , on peut soit ouvrir une UIWebView, soit détecter qu'on sait gérer ce lien-là  (on affiche par exemple une UIImageView par-dessus notre vue globale si c'est une url finissant par un .jpg, ou on va ailleurs dans notre application).


     


    Note : J'ai passé outre le parsing pour l'instant. Là , y'a suffisamment de trucs sur le web.


     


     


    C'est pas encore parfait (encore très brouillon) mais voilà  ce que j'ai.


     


    L4TextView.h




    #import <UIKit/UIKit.h>
    #import "L4Links.h"


    enum
    {
    L4LinkTypeString,
    L4LinkTypeURL,
    };


    @protocol L4TextViewDelegate < NSObject >


    @optional
    -(void)textView:(UITextView *)textView wantToLaunchStringLink:(NSString *)stringLink;
    -(void)textView:(UITextView *)textView wantToLaunchURLLink:(NSURL *)urlLink;


    @end


    @interface L4TextView : UITextView
    {

    }


    @property (nonatomic, weak) id < L4TextViewDelegate > customDelegate;
    @property (nonatomic, strong) NSMutableArray *links;


    @property (nonatomic, assign) int linkType;


    -(void)settings;


    @end

    L4TextView.m



    #import "L4TextView.h"


    @implementation L4TextView


    @synthesize customDelegate = _customDelegate;
    @synthesize links = _links;
    @synthesize linkType = _linkType;


    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self)
    {
    [self settings];
    _linkType = L4LinkTypeString;
        }
        return self;
    }


    -(void)settings
    {
    [self setEditable:FALSE];
    [self settingTapGestureRecognizer];
    }


    -(void)settingTapGestureRecognizer
    {
    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
    action:@selector(textViewDidGetTapped:)];
    [self addGestureRecognizer:tapRecognizer];
    }


    -(IBAction)textViewDidGetTapped:(id)sender
    {
    CGPoint touchPosition = [sender locationInView:self];

    UITextPosition *textPosition = [self closestPositionToPoint:touchPosition];

    UITextRange *wordRange = [[self tokenizer] rangeEnclosingPosition:textPosition
      withGranularity:UITextGranularityCharacter
      inDirection:UITextLayoutDirectionRight];

    if (wordRange)
    {
    NSRange range2 = [self rangeFromUITextRange:wordRange fromTextView:self];
    NSString *stringLink = [self getStringLinkFromRange:range2];


    if (stringLink)
    {
    if (_linkType == L4LinkTypeString)
    {
    if ([_customDelegate respondsToSelector:@selector(textView:wantToLaunchStringLink:)])
    [_customDelegate textView:self wantToLaunchStringLink:stringLink];
    }
    else if (_linkType == L4LinkTypeURL)
    {
    if ([_customDelegate respondsToSelector:@selector(textView:wantToLaunchURLLink:)])
    [_customDelegate textView:self wantToLaunchURLLink:[NSURL URLWithString:stringLink]];
    }
    }
    }
    }


    -(NSRange)rangeFromUITextRange:(UITextRange *)textRange fromTextView:(UITextView *)textView
    {
    NSInteger startOffset = [textView offsetFromPosition:[textView beginningOfDocument] toPosition:[textRange start]];
    NSInteger endOffset = [textView offsetFromPosition:[textView beginningOfDocument] toPosition:[textRange end]];
    NSRange offsetRange = NSMakeRange(startOffset, endOffset - startOffset);

    return offsetRange;
    }




    -(NSString *)getStringLinkFromRange:(NSRange)textRange
    {
    NSString *stringLink = nil;

    for (int i = 0; i < [_links count]; i ++)
    {
    L4Links *l4links = [_links objectAtIndex:i];
    NSRange aRange = [l4links range];
    if(aRange.location <= textRange.location && aRange.location+aRange.length >= textRange.location+textRange.length)
    stringLink = [l4links stringLink];
    }

    return stringLink;
    }


     


    L4Links.h & .m (vu que c'est petit, je condense) :



    #import <Foundation/Foundation.h>


    @interface L4Links : NSObject
    {


    }


    @property (nonatomic, assign) NSRange range;
    @property (nonatomic, strong) NSString *stringLink;




    -(id)initWithStringLink:(NSString *)aLink andRange:(NSRange)aRange;
    -(id)initWithURLLink:(NSURL *)aLink andRange:(NSRange)aRange;
    @end


    #import "L4Links.h"


    @implementation L4Links


    @synthesize stringLink = _stringlink;
    @synthesize range = _range;


    -(id)initWithStringLink:(NSString *)aLink andRange:(NSRange)aRange
    {
    self = [super init];
    if (self)
    {
    _stringlink = aLink;
    _range = aRange;
    }
    return self;
    }




    -(id)initWithURLLink:(NSURL *)aLink andRange:(NSRange)aRange
    {
    self = [super init];
    if (self)
    {
    _stringlink = [aLink absoluteString];
    _range = aRange;
    }
    return self;
    }

    Exemple d'utilisation :



    NSString *text = @bpetb brnpbe gzr fefz la femz;


    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:text];
    [self setAttributeLookLinkTo:attributedString withRange:NSMakeRange(3, 5)];
    otherTextView = [[L4TextView alloc] initWithFrame:CGRectMake(20, 20, 280, 250)];
    [otherTextView setAttributedText:attributedString];
    NSMutableArray *array = [[NSMutableArray alloc] init];
    L4Links *l4links = [[L4Links alloc] initWithStringLink:@http://google.com andRange:NSMakeRange(3, 5)];
    [array addObject:l4links];
    [otherTextView setLinks:array];
    [otherTextView setCustomDelegate:self];
    [otherTextView setBackgroundColor:[UIColor yellowColor]];
    [[self view] addSubview:otherTextView];


    -(void)setAttributeLookLinkTo:(NSMutableAttributedString *)attributedString withRange:(NSRange)range
    {
    [attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:range];
    [attributedString addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:NSUnderlineStyleSingle] range:range];
    }


    -(void)textView:(UITextView *)textView wantToLaunchURLLink:(NSURL *)urlLink
    {
    NSLog(@URL Link: %@", urlLink);
    }


    -(void)textView:(UITextView *)textView wantToLaunchStringLink:(NSString *)stringLink
    {
    NSLog(@String Link: %@", stringLink);
    }

    Va falloir que je renomme correctement les trucs, etc.


    Dès que c'est plus propre, je devrais filer ça sur GitHub je pense...

    Mais si vous avez besoin de voir l'idée globale de ce qui se cache derrière, c'est là . 


     


     


     


     


     


     


     


    Ce qu'il manque : Gestion des images.


    Là , mon idée actuelle et que je dois vérifier, c'est si je ne pourrais pas mettre un p'tit Emoji derrière et détecter (de la même manière) son tap. Je n'utilise pas les Emoji, donc j'avouerais que je ne sais pas comment ça marche derrière (à  part que c'est un caractère unicode spécial), mais c'est juste une idée que j'ai pour l'instant (doit bien en exister un qui ressemble à  une photo ?). Si on peut en faire des persos aussi... Car apparemment, ajouter des UIImage( sous-entendu UIImageView) dans des UITextField, c'est vraiment pas évident...


  • LarmeLarme Membre
    octobre 2013 modifié #7

    P'tit Update :

    Apparemment, la solution de ranger un custom attributes, et de le récupérer est possible à  partir d'iOS7. De quoi se débarrasser de l'object {range/lien}...

    En effet, sous iOS6 en tout cas, l'UITextView se débarrasse rapidement des custom attributes.


    Bon, là  je suis toujours en suspend, attendant Mavericks pour passer à  XCode 5, parce que bon, avoir Moutain Lion pour une semaine maintenant (d'après les rumeurs), j'trouve ça useless...


  • LarmeLarme Membre
    octobre 2013 modifié #8

    Génial, j'viens trouver que j'embêtais un peu pour rien...


    iOS7 apporte : NSLinkAttributeName


    Bon, au moins, j'ai déjà  fait pas mal de boulot (j'suis sur mon propre parser, ça apporte un peu de challenge, même si j'dois pas tout optimiser encore pour l'instant, j'en apprends plus sur les RegularExpression, et c'est pas plus mal), donc je sais comment ça marche et vu comment j'ai codé pour l'instant, j'devrais changer qu'une ligne ou deux, m'enfin :o

    Ma méthode permet donc de faire ça sur de l'iOS < 7.0 (iOS6 quoi).

     


Connectez-vous ou Inscrivez-vous pour répondre.