前言
背景:最近做的項目中有這樣一個需求疯搅,一個話題詳情界面內(nèi)部分內(nèi)容為html標(biāo)簽锰霜,其他為普通內(nèi)容,然后html標(biāo)簽是嵌套在Cell中的车份,一開始用的是UILabel加載html標(biāo)簽驻子,結(jié)果發(fā)現(xiàn)對于圖片標(biāo)簽沒有更好的適應(yīng)屏幕灿意,果斷換成UIWebView,使用WebView加載計算高度的時候是有些注意點的崇呵,所以在此記錄一下脾歧,并總結(jié)一下相關(guān)知識,以備后續(xù)查閱演熟。
一鞭执、cell嵌套webView具體代碼及講解
1、自定義Cell并初始化數(shù)據(jù)
if (indexPath.section == 0) {
LSTopicDetailMainCell *cell = [tableView dequeueReusableCellWithIdentifier:[NSString stringWithUTF8String:object_getClassName([LSTopicDetailMainCell class])] forIndexPath:indexPath];
cell.viewModel = self.viewModel.topMainCellViewModel;
return cell;
}
使用viewModel裝配自定義Cell芒粹,注意其identifier已經(jīng)注冊兄纺,如下
[_mainTableView registerClass:[LSTopicDetailMainCell class] forCellReuseIdentifier:[NSString stringWithUTF8String:object_getClassName([LSTopicDetailMainCell class])]];
2、返回高度
比較麻煩的是高度的計算化漆,因為我對于Cell自動布局高度的計算是用的 UITableView+FDTemplateLayoutCell
這個第三方估脆,核心是提前計算高度及緩存,對UILabel加載Html標(biāo)簽來說很OK座云,但是對于webView來講就有些問題疙赠,因為他的高度需要在加載完的回調(diào)中去獲取并刷新,所以需要手動計算朦拖。
if (indexPath.section == 0) {
return self.viewModel.topMainCellViewModel.cellHeight;
}
3圃阳、自定義Cell內(nèi)相關(guān)代碼
- 加載Html標(biāo)簽
[self.contentWebView loadHTMLString:viewModel.content baseURL:nil];
- UIWebView回調(diào)處理(核心代碼)
- (void)webViewDidFinishLoad:(UIWebView *)webView {
// 獲取內(nèi)容高度
CGFloat height = [[webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.scrollHeight"] intValue];
// 防止死循環(huán)
if (height != _viewModel.htmlHeight) {
_viewModel.htmlHeight = height;
if (_viewModel.htmlHeight > 0) {
// 更新布局
CGFloat paddingEdge = 10;
WS(weakSelf)
[self.contentWebView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(paddingEdge);
make.right.equalTo(-paddingEdge);
make.top.equalTo(weakSelf.headerImageView.mas_bottom).offset(paddingEdge);
make.bottom.equalTo(-paddingEdge);
}];
// 刷新cell高度
_viewModel.cellHeight = _viewModel.otherHeight + _viewModel.htmlHeight;
[_viewModel.refreshSubject sendNext:nil];
}
}
}
上面的代碼注釋已經(jīng)很清楚了,需要解釋的是防止死循環(huán)的意思是你刷新cell的代碼在回調(diào)里璧帝,當(dāng)你刷新的時候捍岳,他也會走回調(diào),不判斷處理的話會造成死循環(huán)。
4锣夹、刷新Cell
[self.viewModel.topMainCellViewModel.refreshSubject subscribeNext:^(id x) {
@strongify(self);
[self.mainTableView reloadSection:0 withRowAnimation:UITableViewRowAnimationNone];
}];
5页徐、完事
二、Cell嵌套UILabel加載Html標(biāo)簽處理
假如你只是需要處理文字相關(guān)的Html標(biāo)簽的話银萍,使用Label加載是最好的選擇
1变勇、高度處理(核心代碼)
if (indexPath.section == 0) {
return [tableView fd_heightForCellWithIdentifier:[NSString stringWithUTF8String:object_getClassName([LSTopicDetailMainCell class])] cacheByIndexPath:indexPath configuration:^(LSTopicDetailMainCell *cell) {
@strongify(self);
cell.viewModel = self.viewModel.topMainCellViewModel;
}];
}
2、Masonry布局
[self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(paddingEdge);
make.right.equalTo(-paddingEdge);
make.top.equalTo(weakSelf.headerImageView.mas_bottom).offset(paddingEdge);
make.bottom.equalTo(-paddingEdge);
}];
3贴唇、Label加載Html
NSAttributedString *content = [[NSAttributedString alloc] initWithData:[viewModel.content dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
self.contentLabel.attributedText = content;
三搀绣、UIWebView詳解
1、三種加載方式
- 加載URL內(nèi)容
NSURL *url = [NSURL URLWithString:@"http://www.reibang.com/users/1a9cd48c3cf0/latest_articles"];
[self.webview loadRequest:[NSURLRequest requestWithURL:url]];
- 加載本地的HTML文件
NSString *htmlPath = [[[NSBundle mainBundle] bundlePath]
stringByAppendingPathComponent:@"wanglongshuai.html"];
[self.webview loadRequest:[NSURLRequest requestWithURL:
[NSURL fileURLWithPath:htmlPath]]];
- 加載html字符串
NSString *htmlPath = [[[NSBundle mainBundle] bundlePath]
stringByAppendingPathComponent:@"wanglongshuai.html"];
NSString *htmlString = [NSString stringWithContentsOfFile: htmlPath
encoding:NSUTF8StringEncoding
error:NULL];
[self.webview loadHTMLString:htmlString baseURL:[NSURL
fileURLWithPath:htmlPath]];
2滤蝠、UIWebViewDelegate代理方法
//準(zhǔn)備加載內(nèi)容: 通過返回值來進(jìn)行是否加載的設(shè)置
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
//開始加載
- (void)webViewDidStartLoad:(UIWebView *)webView;
//加載完成
- (void)webViewDidFinishLoad:(UIWebView *)webView;
//加載失敗
- (void)webView:(UIWebView *)webView didFailLoadWithError:(nullable NSError *)error;
3豌熄、常用屬性及API
- 基本屬性及API
**webView的代理**
@property (nullable, nonatomic, assign) id <UIWebViewDelegate> delegate;
**內(nèi)置的scrollView**
@property (nonatomic, readonly, strong) UIScrollView *scrollView NS_AVAILABLE_IOS(5_0);
**URL請求**
@property (nullable, nonatomic, readonly, strong) NSURLRequest *request;
**是否縮放到適合屏幕大小**
@property (nonatomic) BOOL scalesPageToFit;
**執(zhí)行javaScript操作**
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
- 加載相關(guān)屬性及API
- (void)reload; //重新加載數(shù)據(jù)
- (void)stopLoading; //停止加載數(shù)據(jù)
@property (nonatomic, readonly, getter=isLoading) BOOL loading; //是否正在加載
- (void)goBack; //返回上一級
- (void)goForward; //跳轉(zhuǎn)下一級
@property (nonatomic, readonly, getter=canGoBack) BOOL canGoBack; //能否返回上一級
@property (nonatomic, readonly, getter=canGoForward) BOOL canGoForward; //能否跳轉(zhuǎn)下一級
- 視頻相關(guān)屬性
//YES肉康,自動檢測網(wǎng)頁上的電話號碼演侯,單擊可以撥打
@property (nonatomic) BOOL detectsPhoneNumbers NS_DEPRECATED_IOS(2_0, 3_0);
//設(shè)置某些數(shù)據(jù)變?yōu)殒溄有问结2牵@個枚舉可以設(shè)置如電話號,地址览闰,郵箱等轉(zhuǎn)化為鏈接
@property (nonatomic) UIDataDetectorTypes dataDetectorTypes NS_AVAILABLE_IOS(3_0);
//設(shè)置是否使用內(nèi)聯(lián)播放器播放視頻
@property (nonatomic) BOOL allowsInlineMediaPlayback NS_AVAILABLE_IOS(4_0); // iPhone Safari defaults to NO. iPad Safari defaults to YES
//設(shè)置視頻是否自動播放
@property (nonatomic) BOOL mediaPlaybackRequiresUserAction NS_AVAILABLE_IOS(4_0); // iPhone and iPad Safari both default to YES
//設(shè)置音頻播放是否支持ari play功能
@property (nonatomic) BOOL mediaPlaybackAllowsAirPlay NS_AVAILABLE_IOS(5_0); // iPhone and iPad Safari both default to YES
//設(shè)置是否將數(shù)據(jù)加載如內(nèi)存后渲染界面
@property (nonatomic) BOOL suppressesIncrementalRendering NS_AVAILABLE_IOS(6_0); // iPhone and iPad Safari both default to NO
//設(shè)置用戶交互模式
@property (nonatomic) BOOL keyboardDisplayRequiresUserAction NS_AVAILABLE_IOS(6_0); // default is YES