DTCoreText的集成與使用

DTCoreText是可以將HTML字符串轉(zhuǎn)化為富文本使用的工具,既保證原生實(shí)現(xiàn)又能適應(yīng)靈活的樣式修改,而且相比于使用WebView顯示內(nèi)容在性能上也有很大優(yōu)勢。本篇就這一技術(shù)的使用進(jìn)行總結(jié)。

目錄

一、相關(guān)資源
二、DTCoreText的集成
三、DTCoreText的使用
四、可能遇到的錯誤
五、參考鏈接

一、相關(guān)資源

  1. DTCoreText源碼下載
  2. DTCoreText官方文檔
  3. DTCoreText集成文檔
  4. 本文DTCoreText測試工程

溫馨提示:文中代碼量比較大,看起來可能比較費(fèi)勁,所以先將本文的Demo鏈接放在這里,結(jié)合代碼看更方便,畢竟代碼才是硬道理嘛!

二、DTCoreText的集成

在項(xiàng)目中使用DTCoreText需要它的兩個靜態(tài)庫:DTCoreText.framework和DTFoundation,framework。但是從Github下載的文件卻不能直接使用。起初我是直接從網(wǎng)上其他地方下載打包好的靜態(tài)庫來使用的,但這樣會遺漏掉更新。所以還是總結(jié)了集成DTCoreText的具體步驟如下:

1.下載源碼

創(chuàng)建一個文件夾DTCoreText,使用終端命令下載源碼:

git clone --recursive [https://github.com/Cocoanetics/DTCoreText.git](https://github.com/Cocoanetics/DTCoreText.git) Externals/DTCoreText

2.設(shè)置編譯配置

使用下載的工程可以根據(jù)需求修改編譯配置,然后運(yùn)行工程得到適合不同平臺的靜態(tài)庫。為了獲取到適合iOS設(shè)備使用的SDK,我們選擇工程Target為DTCoreText(iOS),并依次選擇工程->TARGETS->DTCoreText(iOS)->Deployment Info,選擇需要最低支持的系統(tǒng)版本

image.png

3.設(shè)置Scheme

將Run環(huán)境修改為Release模式,依次選擇Product->Scheme->Edit Scheme

image.png

4.模擬器和真機(jī)分別編譯

使用commadn+B執(zhí)行代碼編譯,注意一定要選擇正確的Target,我們既然是用于iOS,就應(yīng)該選擇DTCoreText (iOS)這個Target進(jìn)行編譯

真機(jī)環(huán)境編譯.png
模擬器環(huán)境編譯.png

5.打開編譯緩存,獲取靜態(tài)庫

在Xcode依次打開File->File Setting->DerivedData,然后點(diǎn)擊之后的路徑箭頭可以找到DTCoreText的編譯緩存文件夾

屏幕快照 2018-01-30 下午2.01.52.png

然后我們再依次打開Build->Products,將會看到適合模擬器和真機(jī)使用的兩個靜態(tài)庫文件夾:

image.png

6.合并靜態(tài)庫

經(jīng)過上述步驟,我分別得到了適合模擬器和真機(jī)使用的靜態(tài)庫,現(xiàn)在我們把它們合并。首先我們把Products文件拷貝到一個合適的位置,然后在控制臺執(zhí)行合并靜態(tài)庫的命令如下:

合并靜態(tài)庫.png

如圖,我們使用lipo -create命令合并了適合模擬器和真機(jī)使用的可執(zhí)行文件并放在了桌面上如下:

image.png

然后我們需要將兩個文件分別對應(yīng)拷貝到Release-iphones文件夾中的DTCoreText.framework和DTFoundation.framework中。這樣最終我們就得到想要的靜態(tài)庫。

三、DTCoreText的使用

在這之前我們準(zhǔn)備一段測試用的Html如下:

_html = @"<span style=\"color:#333;font-size:15px;\"><strong>標(biāo)題1</strong></span><br/><span align=\"left\" style=\"color:#333;font-size:15px;\">詳細(xì)介紹詳細(xì)介紹詳細(xì)介紹詳細(xì)介紹詳細(xì)介紹詳細(xì)介紹。</span><br/><img src=\"http://cn-qinqimaifang-uat.oss-cn-hangzhou.aliyuncs.com/img/specialist/upload/spcetiicwlz1v_54e2e00fa8a6faf66168571654dbfee2.jpg\" _src=\"http://cn-qinqimaifang-uat.oss-cn-hangzhou.aliyuncs.com/img/specialist/upload/spcetiicwlz1v_54e2e00fa8a6faf66168571654dbfee2.jpg\"><br/><br/><span style=\"color:#333;font-size:15px;\">百度:<a href=\"http://www.baidu.com.cn\">my testlink</a></span><br/><br/><span style=\"color:#333;font-size:15px;\">電話:<a href=\"tel:4008001234\">my phoneNum</a></span><br/><br/><span style=\"color:#333;font-size:15px;\">我郵箱:<a href=\"mailto:dreamcoffeezs@163.com\">my mail</a></span>";

關(guān)于DTCoreText,我們主要用到它的三個控件,分別是DTAttributedLabel,DTAttributedTextView和DTAttributedTextCell。下面對它們的使用進(jìn)行具體說明:

1.DTAttributedLabel

顧名思義,我們也會把DTAttributedLabel當(dāng)做一個UILabel來使用(雖然事實(shí)上DTAttributedLabel并不屬于UILabel的子類)。這里針對DTAttributedLabel使用的三個問題進(jìn)行介紹。

1.1顯示基本文本

//1.創(chuàng)建DTAttributedLabel
_attributedLabel = [[DTAttributedLabel alloc] initWithFrame:CGRectZero];
_attributedLabel.delegate = self;
[self.view addSubview:self.attributedLabel];

//2.Html轉(zhuǎn)化富文本
NSData *data = [_html dataUsingEncoding:NSUTF8StringEncoding];
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithHTMLData:data documentAttributes:NULL];

//3.計(jì)算Frame
//預(yù)設(shè)一個最大的Frame,限寬不限高,方便以后計(jì)算布局
_viewMaxRect =  CGRectMake(15, 15, ZSToolScreenWidth - 15*2, CGFLOAT_HEIGHT_UNKNOWN);        
DTCoreTextLayouter *layouter = [[DTCoreTextLayouter alloc] initWithAttributedString:attributedString];
NSRange entireStringRange = NSMakeRange(0, [attributedString length]);
DTCoreTextLayoutFrame *layoutFrame = [layouter layoutFrameWithRect:_viewMaxRect range:entireStringRange];
CGSize textSize = [layoutFrame frame].size;
self.attributedLabel.frame = CGRectMake(_viewMaxRect.origin.x, _viewMaxRect.origin.y, _viewMaxRect.size.width, textSize.height);
  
//4.設(shè)置富文本
self.attributedLabel.attributedString = [self getAttributedStringWithHtml:self.html];

1.2顯示圖片

既然是富文本,DTAttributedLabel也會顯示圖片。但是如果我們的Html字符串里圖片鏈接沒有包含大小,圖片并不能正常顯示。為了顯示圖片我們需要懶加載獲取寬高再刷新顯示,這就需要用到DTAttributedLabel的代理方法如下:

#pragma mark - Delegate:DTAttributedTextContentViewDelegate
//DTCoretText在解析Html的時候,如果遇到網(wǎng)絡(luò)圖片會插入一個占位符
//對于圖片類型(DTImageTextAttachmentd)的占位符,我們使用DTLazyImageView來顯示
- (UIView *)attributedTextContentView:(DTAttributedTextContentView *)attributedTextContentView viewForAttachment:(DTTextAttachment *)attachment frame:(CGRect)frame{
    if([attachment isKindOfClass:[DTImageTextAttachment class]]){
        NSString *imageURL = [NSString stringWithFormat:@"%@", attachment.contentURL];
        DTLazyImageView *imageView = [[DTLazyImageView alloc] initWithFrame:frame];
        imageView.delegate = self;//圖片懶加載代理
        imageView.contentMode = UIViewContentModeScaleAspectFit;
        imageView.image = [(DTImageTextAttachment *)attachment image];
        imageView.url = attachment.contentURL;

        //處理gif圖片
        if ([imageURL containsString:@"gif"]) {
           dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                NSData *gifData = [NSData dataWithContentsOfURL:attachment.contentURL];
                dispatch_async(dispatch_get_main_queue(), ^{
                    imageView.image = DTAnimatedGIFFromData(gifData);
                });
            });
        }
        return imageView;
    }
    return nil;
}

#pragma mark  Delegate:DTLazyImageViewDelegate
//懶加載圖片代理
- (void)lazyImageView:(DTLazyImageView *)lazyImageView didChangeImageSize:(CGSize)size {
    NSURL *url = lazyImageView.url;
    CGSize imageSize = size;
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"contentURL == %@", url];
    BOOL didUpdate = NO;
    
    //update all attachments that match this URL (possibly multiple images with same size)
    //更新所有匹配URL的占位符視圖 
    for (DTTextAttachment *oneAttachment in [self.attributedLabel.layoutFrame textAttachmentsWithPredicate:pred]){
        //update attachments that have no original size, that also sets the display size
        //更新沒有自帶尺寸的占位視圖(如網(wǎng)絡(luò)圖片) 
        if (CGSizeEqualToSize(oneAttachment.originalSize, CGSizeZero)){
            //原始圖片不帶寬高,被識別后修改Html
            oneAttachment.originalSize = imageSize;
          //使用新拿到的圖片尺寸更新HTML字符串 
            [self configNoSizeImageView:url.absoluteString size:imageSize];
            didUpdate = YES;
        }
    }
    if (didUpdate){    
        //重新顯示富文本
        CGSize textSize = [self getAttributedTextHeightHtml:self.html with_viewMaxRect:_viewMaxRect];
        self.attributedLabel.frame = CGRectMake(_viewMaxRect.origin.x, _viewMaxRect.origin.y, _viewMaxRect.size.width, textSize.height);
        self.attributedLabel.attributedString = [self getAttributedStringWithHtml:self.html];
        self.attributedLabel.layouter = nil;
        [self.attributedLabel relayoutText];
    }
}

#pragma mark - private Methods
//使用得到的新圖片尺寸,更新HtmlString字符串
- (void)configNoSizeImageView:(NSString *)url size:(CGSize)size{
    //_viewMaxRect是預(yù)設(shè)的最大Frame
    CGFloat imgSizeScale = size.height/size.width;
    CGFloat widthPx = _viewMaxRect.size.width;
    CGFloat heightPx = widthPx * imgSizeScale;
    NSString *imageInfo = [NSString stringWithFormat:@"_src=\"%@\"",url];
    NSString *sizeString = [NSString stringWithFormat:@"style=\"width:%.fpx; height:%.fpx;\"",widthPx,heightPx];
    NSString *newImageInfo = [NSString stringWithFormat:@"_src=\"%@\"%@",url,sizeString];
    if ([self.html containsString:imageInfo]) {
        NSString *newHtml = [self.html stringByReplacingOccurrencesOfString:imageInfo withString:newImageInfo];
        self.html = newHtml;
    }
}

//使用HtmlString,和預(yù)設(shè)的Frame,計(jì)算富文本視圖自適應(yīng)后的高度
- (CGSize)getAttributedTextHeightHtml:(NSString *)htmlString with_viewMaxRect:(CGRect)_viewMaxRect{
    //獲取富文本
    NSAttributedString *attributedString =  [self getAttributedStringWithHtml:htmlString];
    //獲取布局器
    DTCoreTextLayouter *layouter = [[DTCoreTextLayouter alloc] initWithAttributedString:attributedString];
    NSRange entireString = NSMakeRange(0, [attributedString length]);
    //獲取Frame
    DTCoreTextLayoutFrame *layoutFrame = [layouter layoutFrameWithRect:_viewMaxRect range:entireString];
    //得到大小
    CGSize sizeNeeded = [layoutFrame frame].size;
    return sizeNeeded;
}

1.3響應(yīng)事件

如果我們希望在DTAttributedLabel上操作點(diǎn)擊事件,那么對應(yīng)的我們也應(yīng)該在Html中使用超鏈接A標(biāo)簽。這里我們需要用到如下的代理方法如下:

- (UIView *)attributedTextContentView:(DTAttributedTextContentView *)attributedTextContentView
                          viewForLink:(NSURL *)url
                           identifier:(NSString *)identifier
                                frame:(CGRect)frame{
    //此方法需要我們在這里返回一個可以點(diǎn)擊響應(yīng)的控件如Button,然后就可以很方便的處理響應(yīng)事件了,其中:
    //url:Html中的超鏈接(可以根據(jù)需要設(shè)置http、tel、mailto等)
    //identifier:屬于該視圖的唯一性標(biāo)識
    //frame:超鏈接字符串所在的位置,需要將自定義響應(yīng)按鈕設(shè)置為此Frame
    return nil;
}

注意:如果我們需要顯示一些輸入框之類的視圖,也可以借助此方法。
最終效果圖:

屏幕快照 2018-01-30 下午2.24.32.png

2.DTAttributedTextView

其實(shí),DTAttributedTextView和DTAttributedLabel的用法幾乎一樣。從其源碼上就能看出,DTAttributedLabel繼承于DTAttributedTextContentView的,而DTAttributedTextView包含DTAttributedTextContentView屬性??梢哉fDTAttributedTextView就是借助DTAttributedLabel實(shí)現(xiàn)的視圖。

DTAttributedTextView是支持滑動顯示的富文本視圖,在使用時計(jì)算富文本的Frame也就沒那么必要了,一般我們都會指定它的Frame。其在這里的用法就不累述了。

3.DTAttributedTextCell

如果我們需要在單元格上顯示富文本,DTCoretText也為我們提供了特有的類來解決這個問題,那就是DTAttributedTextCell。通過這個單元格類,我們可以方便的設(shè)置富文本以及獲取單元格高度。以下是使用DTAttributedTextCell顯示富文本的核心代碼:

3.1. 聲明控制器內(nèi)屬性

@interface TestTableViewController ()<UITableViewDataSource,UITableViewDelegate,DTAttributedTextContentViewDelegate,DTLazyImageViewDelegate>
@property(nonatomic,strong)UITableView *tableView;
//普通單元格與富文本單元格
@property (nonatomic, copy) NSString *cellID_Normal;
@property (nonatomic, copy) NSString *cellID_DTCoreText;
//類似tabelView的緩沖池,用于存放圖片大小
@property (nonatomic, strong) NSCache *imageSizeCache;
@property (nonatomic,strong)NSCache *cellCache;
//表視圖數(shù)據(jù)源
@property (nonatomic, strong) NSArray  *dataSource;
//當(dāng)前表視圖是否在滑動
@property (nonatomic,assign)BOOL isScrolling;

@end

3.2.表視圖代理方法返回單元格及其高度

//代理方法:返回單元格
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    switch (indexPath.section) {
        case 0:{
            //普通單元格
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:_cellID_Normal];
            cell.textLabel.text = self.dataSource[indexPath.section][indexPath.row];
            return cell;
            break;
        }
        case 1:{
            //自定義方法,創(chuàng)建富文本類型的單元格
            ZSDTCoreTextCell *dtCell = (ZSDTCoreTextCell *) [self tableView:tableView prepareCellForIndexPath:indexPath];
            return dtCell;
            break;
        }
        default:
            break;
    }
    return nil;
}

//返回單元格高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(nonnull NSIndexPath *)indexPath{
    switch (indexPath.section) {
        case 0:{
            return 50;
            break;
        }
        case 1:{
          //返回富文本類型單元格的方法
            ZSDTCoreTextCell *cell = (ZSDTCoreTextCell *)[self tableView:tableView prepareCellForIndexPath:indexPath];
            return [cell requiredRowHeightInTableView:tableView];
            break;
        }
        default:
            break;
    }
    return 0;
}

3.3.懶加載處理無寬高屬性的圖片

#pragma mark - DTAttributedTextContentViewDelegate
//對于沒有在Html標(biāo)簽里設(shè)置寬高的圖片,在這里為其設(shè)置占位
- (UIView *)attributedTextContentView:(DTAttributedTextContentView *)attributedTextContentView viewForAttachment:(DTTextAttachment *)attachment frame:(CGRect)frame{
    if([attachment isKindOfClass:[DTImageTextAttachment class]]){
        //自定義的ZSDTLazyImageView繼承于DTLazyImageView,增加了一個屬性textContentView
        //用于更新圖片大小
        ZSDTLazyImageView *imageView = [[ZSDTLazyImageView alloc] initWithFrame:frame];
        imageView.delegate = self;
        imageView.image = [(DTImageTextAttachment *)attachment image];
        imageView.textContentView = attributedTextContentView;
        imageView.url = attachment.contentURL;
        return imageView;
    }
    return nil;
}


//對于無寬高的圖片懶加載,緩存記錄其大小,然后執(zhí)行表視圖更新
- (void)lazyImageView:(ZSDTLazyImageView *)lazyImageView didChangeImageSize:(CGSize)size{
    BOOL needUpdate = NO;
    NSURL *url = lazyImageView.url;
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"contentURL == %@", url];
    /* update all attachments that matchin this URL (possibly multiple
        images with same size)
     */
    for (DTTextAttachment *oneAttachment in [lazyImageView.textContentView.layoutFrame textAttachmentsWithPredicate:pred]){
        // update attachments that have no original size, that also sets the display size
        if (CGSizeEqualToSize(oneAttachment.originalSize, CGSizeZero)){
            oneAttachment.originalSize = size;
            NSValue *sizeValue = [_imageSizeCache objectForKey:oneAttachment.contentURL];
            if (!sizeValue) {
                //將圖片大小記錄在緩存中,但是這種圖片的原始尺寸可能很大,所以這里設(shè)置圖片的最大寬
                //并且計(jì)算高
                CGFloat aspectRatio = size.height / size.width;
                CGFloat width = ZSToolScreenWidth - 15*2;
                CGFloat height = width * aspectRatio;
                CGSize newSize = CGSizeMake(width, height);
                [_imageSizeCache setObject:[NSValue valueWithCGSize:newSize]forKey:url];
            }
            needUpdate = YES;
        }
    }
    if (needUpdate){
        //有新的圖片尺寸被緩存記錄的時候,需要刷新表視圖
        [self reloadCurrentCell];
    }
}

3.4.創(chuàng)建富文本單元格的方法

#pragma mark - private Methods
//創(chuàng)建富文本單元格,并更新單元格上的數(shù)據(jù)
//ZSDTCoreTextCell是自定義的繼承于DTCoreTextCell的單元格
- (ZSDTCoreTextCell *)tableView:(UITableView *)tableView prepareCellForIndexPath:(NSIndexPath *)indexPath{
    NSString *key = [NSString stringWithFormat:@"dtCoreTextCellKEY%ld-%ld", (long)indexPath.section, (long)indexPath.row];
    ZSDTCoreTextCell *cell = [_cellCache objectForKey:key];
    if (!cell){
        cell = [[ZSDTCoreTextCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:_cellID_DTCoreText];
        cell.attributedTextContextView.edgeInsets = UIEdgeInsetsMake(0, 15, 0, 15);
        [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
        cell.accessoryType = UITableViewCellAccessoryNone;
        cell.hasFixedRowHeight = NO;
        cell.textDelegate = self;
        cell.attributedTextContextView.shouldDrawImages = YES;
        //記錄在緩存中
        [_cellCache setObject:cell forKey:key];
    }
    //2.設(shè)置數(shù)據(jù)
    //2.1為富文本單元格設(shè)置Html數(shù)據(jù)
    [cell setHTMLString:self.dataSource[indexPath.section][indexPath.row]];
    //2.2為每個占位圖(圖片)設(shè)置大小,并更新
    for (DTTextAttachment *oneAttachment in cell.attributedTextContextView.layoutFrame.textAttachments) {
        NSValue *sizeValue = [_imageSizeCache objectForKey:oneAttachment.contentURL];
        if (sizeValue) {
            cell.attributedTextContextView.layouter=nil;
            oneAttachment.displaySize = [sizeValue CGSizeValue];
            [cell.attributedTextContextView relayoutText];
        }
    }
    [cell.attributedTextContextView relayoutText];
    return cell;
}

3.5.處理表視圖的刷新

如果當(dāng)前表視圖在滑動就不執(zhí)行刷新,因?yàn)榛瑒訒r候會自動調(diào)用表視圖的刷新方法

- (void)reloadCurrentCell{
    if (self.isScrolling) {
        return;
    }
    //如果當(dāng)前表視圖沒有在滑動,就手動刷新當(dāng)前在屏幕顯示的單元格
    NSArray *indexPaths = [self.tableView indexPathsForVisibleRows];
    if(indexPaths){
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
        });
    }
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{
    _isScrolling = NO;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    _isScrolling = YES;
}

3.6.set方法創(chuàng)建表視圖與數(shù)據(jù)源

#pragma mark - set/get方法
- (UITableView *)tableView{
    if (_tableView == nil) {
        _tableView = [[UITableView  alloc] initWithFrame:CGRectMake(0, 0, ZSToolScreenWidth, ZSToolScreenHeight-64) style:UITableViewStylePlain];
        _tableView.dataSource = self;
        _tableView.delegate = self;
        [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:_cellID_Normal];
        //[_tableView registerClass:[ZSDTCoreTextCell class] forCellReuseIdentifier:_cellID_DTCoreText];
    }
    return _tableView;
}

- (NSArray *)dataSource{
    if(_dataSource == nil){
        NSMutableArray *noramDataArray = @[].mutableCopy;
        NSMutableArray *htmlDataArray = @[].mutableCopy;
        NSArray *images = @[@"https://i0.hdslb.com/bfs/archive/d5ad3cf95d32f3d2f2e3471a39120237200d84d8.jpg",
                           @"https://i0.hdslb.com/bfs/archive/71d2fed927d9351e759f408ca7d66c556c37a6b4.jpg",
                           @"https://i0.hdslb.com/bfs/archive/7f520b31b67cd5d89dd30b61b40711327bb00288.png",
                           @"https://i0.hdslb.com/bfs/archive/6edbe81bf74c106087ad139aca169d6e8d9d963b.jpg",
                           @"https://i0.hdslb.com/bfs/archive/805aa8f7ae722fcc277f425bb9927e29ec1d2468.jpg",
                           @"https://i0.hdslb.com/bfs/archive/a7c61d94c583363a970d2a2e339eea97f8f32317.jpg",
                           @"https://i0.hdslb.com/bfs/archive/b447ee1fd63b4cf6f4465a5621cc12898867d26b.jpg"];
        for(int i = 0;i<1000;i++){
            if(i <6){
                [noramDataArray addObject:[NSString stringWithFormat:@"測試普通單元格:%d",i]];
            }
            //這里提供的Html圖片鏈接,沒有寬高屬性,代碼中已經(jīng)演示了如何處理
            int k = i % 6;
            NSString *htmlString =[NSString stringWithFormat:@"<span style=\"color:#333;font-size:15px;\"><strong>測試富文本單元格%d:</strong></span><br/><span style=\"color:#333;font-size:15px;\">記??!砍價(jià)是由你自己先砍,砍不動時再由砍價(jià)師繼續(xù)砍;由砍價(jià)師多砍下的部分,才按照下列標(biāo)準(zhǔn)收費(fèi):</span><br/><span style=\"color:#333;font-size:15px;\"><img src=%@ _src=%@></span>",i,images[k],images[k]];
            [htmlDataArray addObject:htmlString];
        }
        _dataSource = @[noramDataArray,htmlDataArray];
    }
    return _dataSource;
}

使用上述方法使用DTAttributedTextCell的效果圖如下:


DTAttributedTextCell效果圖

四、可能遇到的錯誤

原本上,在項(xiàng)目中使用只需將Release-iphones的DTCoreText.framework和DTFoundation.framework中拖入工程就可以使用了。然而我們編譯工程卻會遇到這樣一個錯誤:"image not found”
解決方法如下圖:

image.png

五、參考鏈接

1.DTCoreText集成:
http://m.itdecent.cn/p/b09d3fa1cd98
2.DTCoreText使用總結(jié):
http://duxinfeng.com/2017/08/02/DTCoreText%E4%BD%BF%E7%94%A8%E6%80%BB%E7%BB%93/
3.iOS富文本框架DTCoreText在UITableView上的使用
http://blog.csdn.net/lala2231/article/details/50780842
4.CoretText的優(yōu)缺點(diǎn)
http://m.itdecent.cn/p/6f8162537975

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,660評論 4 61
  • 你好嗎…… 青春年少,誰都有過懵懂無知的時期,可是,愛情卻悄無聲息地來過... 很多人都會說年少輕狂,...
    花棉木閱讀 275評論 0 0
  • 浮動的框可以向左或向右移動,直到它的外邊緣碰到包含框或另一個浮動框的邊框?yàn)橹?。由于浮動框不在文檔的普通流中,所以文...
    五秋木閱讀 211評論 0 0
  • 2017年5月13日,凌晨0:49分,難眠…… 突然想起公司的一個項(xiàng)目,要做一個后臺數(shù)據(jù)錄入頁面,方便編輯操作上傳...
    阿斌_1009閱讀 188評論 0 0
  • 2月看火影的劇場版博人傳,旁邊小孩居多,看到博人都喊帥,而我卻忍不住想要哭。 想起自己和旁邊小孩一般大小的年紀(jì),那...
    小爽_回家有肉吃閱讀 403評論 0 0

友情鏈接更多精彩內(nèi)容