簡體   English   中英

NSLayoutManager characterIndexForPoint方法在iOS9上失敗

[英]NSLayoutManager characterIndexForPoint method failing on ios9

我正在實現帶有鏈接單擊支持的自定義UILabel 為此,我有以下方法:一種用於初始化結構(僅調用一次),一種用於檢測字符串中確定范圍內的文本的單擊:

- (void) sharedInit {
    // Remember, this method is only called once
    self.layoutManager = [[NSLayoutManager alloc] init];
    self.textContainer = [[NSTextContainer alloc] initWithSize:self.frame.size];
    [self.layoutManager addTextContainer:self.textContainer];
    self.myGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTap:)];

    self.textContainer.lineFragmentPadding = 0.0;
    self.textContainer.lineBreakMode = self.lineBreakMode;
    self.textContainer.maximumNumberOfLines = self.numberOfLines;
    self.textContainer.size = self.frame.size;
}

- (void) onTap:(UITapGestureRecognizer*) tapGesture {
    CGPoint location = [tapGesture locationInView:tapGesture.view];
    NSInteger index = [self.layoutManager characterIndexForPoint:locationOfTouchInLabel
                                                 inTextContainer:self.textContainer
                        fractionOfDistanceBetweenInsertionPoints:nil];

    NSLog(@"index of tapped character: %li", index);

    // ... and some more code to work with that index
}

- (void) setFrame:(CGRect)frame {
    [super setFrame:frame];
    self.textContainer.size = self.frame.size;
}

- (void) setAttributedText:(NSAttributedString *)attributedText {
    [super setAttributedText:attributedText];
    self.textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedText];
    [self.textStorage addLayoutManager:self.layoutManager];
}

- (void) setNumberOfLines:(NSInteger)numberOfLines {
    [super setNumberOfLines:numberOfLines];
    self.textContainer.maximumNumberOfLines = numberOfLines;
}

此處的關鍵變量是indexonTap: mehtod)。 該變量返回被點擊字符的索引,因此我們可以使用它。 這可以在iOS 8上完美運行,但是對於iOS 9,我看到了以下行為:

  • 如果標簽只有一行,它將返回正確的索引
  • 如果標簽有多行, 無論您在哪里單擊, 它始終返回零

在開發iOS 8的功能時,我遇到了類似的問題,我通過將maximumNumberOfLinesNSTextContainer設置為正確的值來解決它,如您在初始化中所看到的。 當運行onTap方法時,TextContainer的配置參數(大小,maxNumOfLines等)正確。 我已經檢查了文檔( https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/NSTextContainer_Class_TextKit/index.html#//apple_ref/occ/instm/NSTextContainer/lineFragmentRectForProposedRect:atIndex:writingDirection :remainingRect :)顯然在此版本中沒有任何變化,所以我很迷路。 到目前為止,這似乎是一個iOS9錯誤,但我不想放棄任何選項。 我也提供了一些解決方法,但是如果可能的話,我想知道該方法的作用。

那么,有人知道發生了什么嗎? 提前致謝...

編輯:

兩件事情:

  • 我嘗試咨詢glyphIndex而不是charIndex ,到目前為止,它返回的結果相同(好一行,零行以上)
  • 我注意到結果不正確時, firstUnlaidCharIndex等於0。 在正常工作的情況下(iOS8和iOS9僅使用一行),它會返回正確的值,第一個越界字符。

嘗試使用相同的UILabel寬度和CGFLOAT_MAX高度初始化NSTextContainer的大小

    self.textContainer.size = CGSizeMake(self.bounds.size.width, CGFLOAT_MAX);

解決了! 看起來問題出在setAttributedText:重載。 每當您更改標簽的文本時,都會重新創建TextStorage,看起來布局管理器根本不喜歡它。 重用textStorage並通過調用setAttributedString:僅更改文本setAttributedString:解決了該問題。

實際上,我很早以前就解決了這個問題:((我編輯了帖子,但忘了回答自己。對不起!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM