Closed lexiaoyao20 closed 8 years ago
我使用的YYKit版本是 - YYKit (0.9.7): 另外,用UILabel不会有这个问题 会不会和TableView的重用机制有关呢?
把 ignoreCommonProperties
这个属性设为 NO 应该就没问题了。
这个属性是 YES 时,Label 只会用 textLayout 来显示,而忽略了 text、attributedText、parser 等属性。
还真是这样,非常感谢!!! 看来我还得多多深入的看你这套框架才行
// self.titleMessageLabel.text = messageItem.MessageBody;
self.titleMessageLabel.attributedText = [[NSAttributedString alloc] initWithString:messageItem.MessageBody];
我ignoreCommonProperties
这个属性设置未NO,还是有这个问题,但是cellForRowAtIndexPath 方法中设置attributedText能显示正常
能给一下更详细的代码吗?比如那个 textParser? 或者,你在 [YYLabel setText:] 这个方法里下个断点走一下看看。
这是我的textParser的代码:
@implementation FMEmojiParse
- (BOOL)parseText:(NSMutableAttributedString *)text selectedRange:(NSRangePointer)range {
if (text.length == 0) {
return NO;
}
NSArray *matches = [[FMWeiBoHelper regexEmoticon] matchesInString:text.string options:kNilOptions range:text.rangeOfAll];
if (matches.count == 0) return NO;
NSRange selectedRange = range ? *range : NSMakeRange(0, 0);
NSUInteger cutLength = 0;
for (NSUInteger i = 0, max = matches.count; i < max; i++) {
NSTextCheckingResult *one = matches[i];
NSRange oneRange = one.range;
if (oneRange.length == 0) continue;
oneRange.location -= cutLength;
NSString *subStr = [text.string substringWithRange:oneRange];
NSString *imageName = [FMWeiBoHelper emojiNameFromDescription:subStr];
UIImage *emoticon = [FMWeiBoHelper imageNamed:imageName];
if (!emoticon) continue;
CGFloat fontSize = 12; // CoreText default value
CTFontRef font = (__bridge CTFontRef)([text attribute:NSFontAttributeName atIndex:oneRange.location]);
if (font) fontSize = CTFontGetSize(font);
NSMutableAttributedString *atr = [NSAttributedString attachmentStringWithEmojiImage:emoticon fontSize:fontSize];
[atr setTextBackedString:[YYTextBackedString stringWithString:subStr] range:NSMakeRange(0, atr.length)];
[text replaceCharactersInRange:oneRange withString:atr.string];
[text removeDiscontinuousAttributesInRange:NSMakeRange(oneRange.location, atr.length)];
[text addAttributes:atr.attributes range:NSMakeRange(oneRange.location, atr.length)];
selectedRange = [self _replaceTextInRange:oneRange withLength:atr.length selectedRange:selectedRange];
cutLength += oneRange.length - 1;
}
if (range) *range = selectedRange;
return YES;
}
// correct the selected range during text replacement
- (NSRange)_replaceTextInRange:(NSRange)range withLength:(NSUInteger)length selectedRange:(NSRange)selectedRange {
// no change
if (range.length == length) return selectedRange;
// right
if (range.location >= selectedRange.location + selectedRange.length) return selectedRange;
// left
if (selectedRange.location >= range.location + range.length) {
selectedRange.location = selectedRange.location + length - range.length;
return selectedRange;
}
// same
if (NSEqualRanges(range, selectedRange)) {
selectedRange.length = length;
return selectedRange;
}
// one edge same
if ((range.location == selectedRange.location && range.length < selectedRange.length) ||
(range.location + range.length == selectedRange.location + selectedRange.length && range.length < selectedRange.length)) {
selectedRange.length = selectedRange.length + length - range.length;
return selectedRange;
}
selectedRange.location = range.location + length;
selectedRange.length = 0;
return selectedRange;
}
@end
基本上是照搬的你Demo的代码
看了下 setText 和 setAttributedText 两个方法,有一个不同之处是setAttributedText 方法会对 _innerText 重新赋值
仔细看了一下这块儿的代码,没发现什么问题啊。。我也一直复现不了这个问题。。
你能试试在 [YYLabel setText:] 这个方法里加个断点看看吗,看看这个方法里面都执行了哪些步骤?
数据项要有7,8项以上的数据才会有这个问题(即超过TableView的默认缓存cell个数)
我改了下 setText 的代码, 下面这个改运行是正常的:
- (void)setText:(NSString *)text {
if (_text == text || [_text isEqualToString:text]) return;
_text = text.copy;
BOOL needAddAttributes = _innerText.length == 0 && text.length > 0;
// [_innerText replaceCharactersInRange:NSMakeRange(0, _innerText.length) withString:text ? text : @""];
_innerText = [[NSMutableAttributedString alloc] initWithString:text];
// if (needAddAttributes) {
_innerText.font = _font ? _font : [self _defaultFont];
_innerText.color = _textColor;
_innerText.shadow = [self _shadowFromProperties];
_innerText.alignment = _textAlignment;
switch (_lineBreakMode) {
case NSLineBreakByWordWrapping:
case NSLineBreakByCharWrapping:
case NSLineBreakByClipping: {
_innerText.lineBreakMode = _lineBreakMode;
} break;
case NSLineBreakByTruncatingHead:
case NSLineBreakByTruncatingTail:
case NSLineBreakByTruncatingMiddle: {
_innerText.lineBreakMode = NSLineBreakByWordWrapping;
} break;
default: break;
}
// }
if ([_textParser parseText:_innerText selectedRange:NULL]) {
[self _updateOuterTextProperties];
}
if (!_ignoreCommonProperties) {
if (_displaysAsynchronously && _clearContentsBeforeAsynchronouslyDisplay) {
[self _clearContents];
}
[self _setLayoutNeedUpdate];
[self _endTouch];
}
}
我特意打印了下日志:
2016-01-07 18:32:42.180 Follow me[8840:2594372] _innerText:Aaaa{
CTForegroundColor = "<CGColor 0x7f9793e425f0> [<CGColorSpace 0x7f9791530960> (kCGColorSpaceDeviceRGB)] ( 0.4 0.4 0.4 1 )";
CTRunDelegate = "<CTRunDelegate 0x7f9794039590 [0x10da477b0]>";
NSColor = "UIDeviceRGBColorSpace 0.4 0.4 0.4 1";
NSFont = "<UICTFont: 0x7f97938edfc0> font-family: \".SFUIText-Regular\"; font-weight: normal; font-style: normal; font-size: 14.00pt";
NSParagraphStyle = "Alignment 0, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\n 28L,\n 56L,\n 84L,\n 112L,\n 140L,\n 168L,\n 196L,\n 224L,\n 252L,\n 280L,\n 308L,\n 336L\n), DefaultTabInterval 0, Blocks (\n), Lists (\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation NO, HeaderLevel 0";
YYTextAttachment = "<YYTextAttachment: 0x7f9794035670>";
YYTextBackedString = "<YYTextBackedString: 0x7f97940395f0>";
}
text:Aaaa
Aaaa 这个Text 并不包含表情,但是 innerText 里却有 YYTextAttachment,我怀疑replaceCharactersInRange 这个方法并不会改变它原有的 attachment 这些属性,所有显示就乱了。
两种修改建议:
你看这样有没有问题?
在 if (needAddAttributes) 上面加上一行:
[_innerText removeDiscontinuousAttributesInRange:NSMakeRange(0, _innerText.length)];
逻辑上应该就对了。
这个能解决你的问题吗?如果 OK 我就更新下代码。
用你上面的代码,能够解决问题
代码已更新
我的初始化代码:
然后在 cellForRowAtIndexPath 方法里面设置Model
上面我特意打印了log,输出的self.titleMessageLabel.text跟显示的不一样,不知道是不是YYLabel没有刷新。
下面附上效果图和打印日志:
打印日志如下: