-1

I want to show the english date styled. I made the following code to get the characters to "redesign":

    - (NSMutableAttributedString *)attributedInfoString:(NSString *)string;
    {
        NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:string];
        UIFont *smallFont = [UIFont boldSystemFontOfSize:17.0f];
        UIFont *boldFont = [UIFont fontWithName:@"HelveticaNeue-Bold" size:24.0f];

        [attString beginEditing];

        [attString addAttribute:NSFontAttributeName value:(smallFont) range:[string rangeOfString:@"th"]];
        [attString addAttribute:NSFontAttributeName value:(smallFont) range:[string rangeOfString:@"th" options:NSBackwardsSearch]];
        [attString addAttribute:(NSString*)kCTSuperscriptAttributeName value:@"1" range:[string rangeOfString:@"th"]];
        [attString addAttribute:(NSString*)kCTSuperscriptAttributeName value:@"1" range:[string rangeOfString:@"th" options:NSBackwardsSearch]];

        [attString addAttribute:NSFontAttributeName value:(boldFont) range:[string rangeOfString:@"the"]];
        [attString addAttribute:NSFontAttributeName value:(boldFont) range:[string rangeOfString:@"the" options:NSBackwardsSearch]];
        [attString addAttribute:(NSString*)kCTSuperscriptAttributeName value:@"0" range:[string rangeOfString:@"the"]];
        [attString addAttribute:(NSString*)kCTSuperscriptAttributeName value:@"0" range:[string rangeOfString:@"the" options:NSBackwardsSearch]];

        [attString addAttribute:NSFontAttributeName value:(smallFont) range:[string rangeOfString:@"st"]];
        [attString addAttribute:NSFontAttributeName value:(smallFont) range:[string rangeOfString:@"st" options:NSBackwardsSearch]];
        [attString addAttribute:(NSString*)kCTSuperscriptAttributeName value:@"1" range:[string rangeOfString:@"st"]];
        [attString addAttribute:(NSString*)kCTSuperscriptAttributeName value:@"1" range:[string rangeOfString:@"st" options:NSBackwardsSearch]];

        [attString addAttribute:NSFontAttributeName value:(boldFont) range:[string rangeOfString:@"August"]];
        [attString addAttribute:(NSString*)kCTSuperscriptAttributeName value:@"0" range:[string rangeOfString:@"August"]];

...

        [attString endEditing];
        return attString;
    }

The problem, I find only the first "hit" from the beginning or from the end. How can I arrange to search the whole string? Especially concerning the "th" because in the string is sometimes 5 or 6 times the word "the" which then stops the adding of the attributes.

Christian
  • 506
  • 4
  • 14

3 Answers3

1

If you find "th", keep looping using -rangeOfString:options:range: (where you set the range argument to just past where you found it).

David Dunham
  • 8,139
  • 3
  • 28
  • 41
  • Thanks, but the "verbal" way of the solution was known. Sorry for my imprecise question. My obstacle is the transforming from verbal to code. How can I do this looping? – Christian Feb 16 '16 at 04:04
1

I'm not sure of what you want to achieve. But this is what I usually use for adding attribute for a long string.

- (NSMutableAttributedString *)attributedInfoString:(NSString *)string;
{
    __block NSMutableAttributedString *attriString = [[NSMutableAttributedString alloc] initWithString:string];

    [attriString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:15.0f] range:NSMakeRange(0, string.length)];

    UIFont *bold = [UIFont boldSystemFontOfSize:17.0f];

    __block BOOL mustStop = NO;

    [string enumerateSubstringsInRange:NSMakeRange(0, [string length])
                               options:NSStringEnumerationByWords
                            usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop)
     {
         // terminates adding of attribute to string if YES
         // as you can see `og` from the word dog is ignored
         if (!mustStop)
         {
             // since we are enumeratingByWord this is to check for specific string(word) in the `string`
             // in this example `the` is the trigger to terminate adding attributes to mutableString
             //
             if (![substring isEqual:@"the"])
             {
                 // add attribute if the substring(word) has `ox` or `og`
                 //
                 if ([substring rangeOfString:@"ox"].location != NSNotFound || [substring rangeOfString:@"og"].location != NSNotFound)
                 {
                     [attriString addAttribute:NSFontAttributeName value:bold range:substringRange];
                 }

                 else
                 {
                     // this is to add attribute to some specified `substring`
                     //
                     NSString *subsubString = @"uic";

                     NSRange subRange = [substring rangeOfString:subsubString];

                     if (subRange.location != NSNotFound)
                     {
                         substringRange.location += subRange.location;

                         substringRange.length = subsubString.length;

                         [attriString addAttribute:NSForegroundColorAttributeName value:[UIColor orangeColor] range:substringRange];

                         [attriString addAttribute:NSFontAttributeName value:bold range:substringRange];
                     }
                 }
             } else mustStop = YES;
         }
     }
     ];

    return attriString;
}

If you use that like:

title.attributedText = [self attributedInfoString:@"The quick brown fox jumped over the lazy dog"];

sample output would be:

enter image description here

Hope this would help.. Cheers! :)

0yeoj
  • 4,500
  • 3
  • 23
  • 41
  • Thanks - but it works not as I needed. I use a xml-file which have several dates like June 15th or March 3rd. First step is to remove the html-tags and now I want to change the attributes of "th", "st", "nd" and "rd". Now I tried to keep the tags to determine the desired range and don't select "th" in "the" or "nd" ind "and" or "end". But how can I remove the tag in the attributed string? [attriString replaceCharactersInRange:[string rangeOfString:@""] withString:@""]; will end in a crash. – Christian Feb 16 '16 at 07:06
  • @Christian, i see.. Please include that **I use a xml-file which...** to the question, it's kinda misleading... – 0yeoj Feb 16 '16 at 08:38
0

Thanks to 0yeoj I found the solution:

  1. In the strings delete the opening-tag and replace the closing-tag by unique characters, that no word would have in this order (öäüß).

  2. Use the code from 0yeoj to find the string "thöäüß", stöäüß etc. and add the attributes as desired.

  3. Here my error took place - I tried to delete the characters "öäüß" in the sub-loop which causes always a crash.

  4. Found the solution in another post here and placed it just before the return-expression:

    while ([attriString.string containsString:@"öäüß"]) { NSRange rangeOfTag = [attriString.string rangeOfString:@"öäüß"]; [attriString replaceCharactersInRange:rangeOfTag withString:@""]; }

Works now perfect. Thanks for the fast help.

Christian
  • 506
  • 4
  • 14