Core Text in UITableviewCell's content overlap

2020-03-31 08:11发布

问题:

I am using Core Text to add text to UITableviewCell's content but arabic content seems to be overlapping and repeating itself as I scroll and superimpose on the other cells.

I am also using other elements on the page which appear just fine and are not repeating . Just the Core Text seems to be repeating.

I cant figure out why .

Here is my code:

     - (CTFontRef)newCustomFontWithName:(NSString *)aFontName
                            ofType:(NSString *)type
                        attributes:(NSDictionary *)attributes {
    NSString *fontPath = [[NSBundle mainBundle] pathForResource:aFontName ofType:type];

    NSData *data = [[NSData alloc] initWithContentsOfFile:fontPath];
    CGDataProviderRef fontProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);


    CGFontRef cgFont = CGFontCreateWithDataProvider(fontProvider);
    CGDataProviderRelease(fontProvider);

    CTFontDescriptorRef fontDescriptor = CTFontDescriptorCreateWithAttributes((__bridge CFDictionaryRef)attributes);
    CTFontRef font = CTFontCreateWithGraphicsFont(cgFont, 0, NULL, fontDescriptor);
    CFRelease(fontDescriptor);
    CGFontRelease(cgFont);
    return font;
}

- (CATextLayer *)customCATextLayer:(NSString *)textString {
    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                [NSNumber numberWithFloat:24.f], (NSString *)kCTFontSizeAttribute,
                                [NSNumber numberWithInt:1], (NSString *)kCTLigatureAttributeName,
                                nil];

    CTFontRef font = [self newCustomFontWithName:@"me_quranKer6"
                                          ofType:@"ttf"
                                      attributes:attributes];

    CATextLayer *normalTextLayer = [[CATextLayer alloc] init];
    normalTextLayer.font = font;
    normalTextLayer.string = textString;
    normalTextLayer.wrapped = YES;
    normalTextLayer.foregroundColor = [[UIColor blackColor] CGColor];
    normalTextLayer.fontSize = 24.f;
    normalTextLayer.alignmentMode = kCAAlignmentCenter;
    normalTextLayer.frame = CGRectMake(0.f, 10.f, 320.f, 32.f);

    CFRelease(font);
    return normalTextLayer;
}



- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    QuranVersesViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"verseCell"];

    Verse *verse = [self.fetchedResultsController objectAtIndexPath:indexPath];

     //English Content starts


    NSMutableAttributedString * englishAttributedString;
    if (!englishAttributedString)
        englishAttributedString = [[NSMutableAttributedString alloc] initWithString:@""];

    NSMutableAttributedString * englishSubtitleAttributedString;


    NSMutableAttributedString * englishVerseAttributedString;
    if (!englishVerseAttributedString)
        englishVerseAttributedString = [[NSMutableAttributedString alloc] initWithString:verse.english_version];

    NSMutableAttributedString * englishFootnoteAttributedString;
    if (!englishFootnoteAttributedString)
        englishFootnoteAttributedString = [[NSMutableAttributedString alloc] init];



    NSString *englishString = @"";

    if(verse.subtitle.length>0)
    {
        NSMutableParagraphStyle *mutParaStyle=[[NSMutableParagraphStyle alloc] init];

        [mutParaStyle setAlignment:NSTextAlignmentCenter];




        englishSubtitleAttributedString = [[NSMutableAttributedString alloc] initWithString:verse.subtitle];

    [englishSubtitleAttributedString addAttributes:[NSDictionary dictionaryWithObject:mutParaStyle
                                                       forKey:NSParagraphStyleAttributeName]
                     range:NSMakeRange(0,[[englishSubtitleAttributedString string] length])];
        [englishAttributedString appendAttributedString:englishSubtitleAttributedString];

        [englishAttributedString addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Arial" size:30] range:NSRangeFromString(verse.subtitle)];
        NSLog(@"text us %@", englishAttributedString);

    }// englishString = [englishString stringByAppendingString:[NSString stringWithFormat:@"%@\n\n", verse.subtitle]];

    [englishAttributedString appendAttributedString:englishVerseAttributedString];

    englishString = [englishString stringByAppendingString:[NSString stringWithFormat:@"[%@:%@] %@\n",  verse.whichSura.sura_no, verse.verse_no, verse.english_version]];

    if(verse.footnote.length>0)
        englishString = [englishString stringByAppendingString: [NSString stringWithFormat:@"\n%@\n", verse.footnote]];


englishString =  [englishString stringByReplacingOccurrencesOfString:@"“" withString:@"\"" ];
  englishString =   [englishString stringByReplacingOccurrencesOfString:@"_" withString:@"\n" ];


  cell.quranVerseEnglishTextView.attributedText = englishAttributedString;
  [cell.quranVerseEnglishTextView autoResizeWithMaxWidth:MAX_TEXT_WIDTH];


    cell.quranVerseEnglishTextView.backgroundColor = [UIColor clearColor];
  //English Content starts


//Arabic Content

    CATextLayer *arabicTextLayer = [self customCATextLayer:verse.arabic_version];
    [cell.arabicView.layer addSublayer:arabicTextLayer];







    return cell;

}

回答1:

I was facing the same problem until I read up about NSAttributedStrings (made available in iOS 6) on this tutorial here.

The following code will solve your issue:

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:info.text attributes:@{ NSFontAttributeName : [UIFont fontWithName:@"Scheherazade" size:32], NSLigatureAttributeName: @2}];

cell.textLabel.attributedText = attributedString;

Out of curiosity, would I be correct to say that you opted to use CoreText because of difficulties in rendering embedded arabic fonts? I ventured the guess because I was attempting to use a similar method as you have done in your code when faced with that exact problem for a Quran app that I'm currently developing. If this so then I can confirm that using NSAttributedString also solves the problem. If you notice in the code above I've also set the NSLigatureAttributeName to 2 which according to the official Apple Class Reference Documentation means 'all ligatures'. Just note that this is something that I'm currently testing and I have yet to see the effects of this but I know that ligatures is a common problem in the rendering of some arabic fonts on certain platforms.

While on the subject, another common problem you may be facing is the line-spacing of arabic text and the slight overlapping of multi-line text and I've found that NSAttributedString can also be a good solution when used together with NSParagraphStyle (Hooray again for NSAttributedString!). Simply modify the above code as below:

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:info.text attributes:@{ NSFontAttributeName : [UIFont fontWithName:@"Scheherazade" size:32], NSLigatureAttributeName: @2}];

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:20];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [info.text length])];

cell.textLabel.attributedText = attributedString;

Hope this helps you or anyone else out there!


EDIT - Adding this helpful post on Common Mistakes With Adding Custom Fonts to Your iOS App for reference as a "checklist" when adding custom fonts on iOS.



回答2:

Actually fixed the issue myself by adding the following line in cellforRowAtIndexPath:

 if (cell == nil)
            {

                cell = [[QuranVersesViewCell alloc] init];
              .....

and also did all the initialization and setting only when the cell was nil. And MOST importantly tagged the view layer and set the text for only the matching tagged view...