iOS端做文檔預(yù)覽,其實(shí)iOS在早期設(shè)計(jì)的時(shí)候,就已經(jīng)考慮到了預(yù)覽的功能,所以在iOS系統(tǒng)的早期,就有<QuickLook>框架支持我們實(shí)現(xiàn)該功能 ,并且逐漸有了QLPreviewController(并不是一個(gè)視圖控制器,而是繼承NSObject的一個(gè)對(duì)象)和UIDocumentInteractionController這兩個(gè)類可以支持我們實(shí)現(xiàn)預(yù)覽,但是這兩個(gè)類默認(rèn)是支持分享功能的,不符合我們的app的要求(我們要求文檔有權(quán)限管理),所以這兩個(gè)都被pass了,在這個(gè)過(guò)程中,我們發(fā)現(xiàn)webView或者WKWebView也可以實(shí)現(xiàn)文件預(yù)覽,而且文件預(yù)覽或者展示UI易于操作,所以我們選擇了使用 網(wǎng)頁(yè)瀏覽器來(lái)完成這個(gè)功能.
首先說(shuō)一下webView吧,由于iOS8系統(tǒng)時(shí),iOS已經(jīng)發(fā)布了新版的WKWebView,性能更好,更省內(nèi)存,所以我們后來(lái)用的是WKWebView,這里先簡(jiǎn)單講一下webiView,webView用起來(lái)很簡(jiǎn)單:
這個(gè)是WebView加載文檔的簡(jiǎn)單應(yīng)用,本地沙盒目錄下的也一樣,這個(gè)不是重點(diǎn),我們的重點(diǎn)在WKWebView上,因?yàn)閕OS8 以下的用戶(有蘋果官網(wǎng)統(tǒng)計(jì)的數(shù)據(jù),17年 june月的的時(shí)候,iOS 9以下的只占3%了,), 我們這個(gè)暫時(shí)舍棄了,但是如果大家兼容,也是可以的.
統(tǒng)計(jì)數(shù)據(jù)的鏈接 : https://developer.apple.com/support/app-store/
下面我們來(lái)講WKWebView ,WKWebView在開(kāi)發(fā)的時(shí)候,要分兩種類型.iOS8和iOS8以上版本的客戶端,需要單獨(dú)處理
因?yàn)閃KWebView有一個(gè)loadFileUrl的方法,是在iOS9之后才出現(xiàn)的,iOS8這個(gè)方法不能用,那能不能直接使用loadRequest方法呢,實(shí)踐證明,loadRequest在WKWebView不太管用(也可能是我沒(méi)有摸索到,但是我是多次嘗試,都沒(méi)成功,但是loadFile在iOS9之上,是妥妥的管用的)
所以,為了處理這個(gè)問(wèn)題,我們這樣處理的
iOS8 以上的設(shè)備:
iOS8以上的設(shè)備,可以直接使用loadFileURL的加載和展示,沒(méi)有什么重要的可以講的,現(xiàn)在針對(duì)的是iOS8 怎么使用WKWebView呢?
通過(guò)翻墻查資料,發(fā)現(xiàn)了一個(gè)牛人的實(shí)現(xiàn)原理,先上代碼,
//將文件移動(dòng)到tmp目錄 瀏覽完再移動(dòng)回去
- (NSURL *)fileURLForBuggyWKWebView8:(NSURL *)fileURL {
NSError *error = nil;
if (!fileURL.fileURL || ![fileURL checkResourceIsReachableAndReturnError:&error]) {
return nil;
}
// Create "/temp/www" directory
NSURL *temDirURL = QDTempDirectoryURL;
if (![QDFileManager fileExistsAtPath:[temDirURL path]]) {
[QDFileManager createDirectoryAtURL:temDirURL withIntermediateDirectories:YES attributes:nil error:&error];
}
NSURL *dstURL = [temDirURL URLByAppendingPathComponent:fileURL.lastPathComponent];
// Now copy given file to the temp directory
[QDFileManager moveItemAtURL:fileURL toURL:dstURL error:&error];
if (error) {
NSLog(@"后調(diào)整失敗 ");
}
self.tempfilePath = dstURL;
// [fileManager copyItemAtURL:fileURL toURL:dstURL error:&error];
// Files in "/temp/www" load flawlesly :)
return dstURL;
}
之前的牛人是將文件copy(我的代碼是移動(dòng)的,我認(rèn)為移動(dòng)應(yīng)該會(huì)比copy更快吧,因?yàn)槲覀兊奈臋n有的時(shí)候是接近1g的視頻文件,)到 沙盒目錄下的 "/temp/www" 文件夾,然后再通過(guò)LoadRequest來(lái)實(shí)現(xiàn),發(fā)現(xiàn)WKWebView居然生效了,這樣的話 ,我理解的是/temp/www默認(rèn)應(yīng)該是存儲(chǔ)的WKWebView的網(wǎng)絡(luò)緩存,然后當(dāng)加載這個(gè)的時(shí)候,系統(tǒng)認(rèn)為是網(wǎng)頁(yè)請(qǐng)求的時(shí)候在優(yōu)先加載緩存,所有就可以讀取了這個(gè)文檔.然后這個(gè)文件就解決了.
ps : 你如果和我一樣 是使用的移動(dòng)文檔的話,要記得處理這幾個(gè)情況
- 用戶瀏覽的時(shí)候,移動(dòng)過(guò)去,瀏覽結(jié)束,記得將文檔移動(dòng)回去
2.當(dāng)用戶瀏覽的時(shí)候 項(xiàng)目出現(xiàn)了崩潰 或者被用戶強(qiáng)退 或者用戶退出后臺(tái)被系統(tǒng)殺死怎么辦?
要將文檔移動(dòng)到沙盒目錄的時(shí)候,對(duì)文件做個(gè)標(biāo)示(比如文件名加個(gè)后綴,展示給用戶的時(shí)候記得過(guò)濾一下),然后在應(yīng)用啟動(dòng)的時(shí)候,在appDelegate的啟動(dòng)方法中,去'temp/www'的目錄下做一個(gè)判斷,判斷是否存在這種前綴的文檔,如果存在,移回原來(lái)的目錄,就ok了,
此外.如果你們的產(chǎn)品和我們一樣,對(duì)文檔有權(quán)限要求,比如,不允許選擇,復(fù)制,粘貼,等操作,我們可以通過(guò)js注入WKWebView的方法讓禁止用戶交互,代碼如下
//禁止長(zhǎng)按彈出 UIMenuController 相關(guān)
//禁止選擇 css 配置相關(guān)
NSString*css = @"body{-webkit-user-select:none;-webkit-user-drag:none;}";
//css 選中樣式取消
NSMutableString*javascript = [NSMutableString string];
[javascript appendString:@"var style = document.createElement('style');"];
[javascript appendString:@"style.type = 'text/css';"];
[javascript appendFormat:@"var cssContent = document.createTextNode('%@');", css];
[javascript appendString:@"style.appendChild(cssContent);"];
[javascript appendString:@"document.body.appendChild(style);"];
[javascript appendString:@"document.documentElement.style.webkitUserSelect='none';"];//禁止選擇
[javascript appendString:@"document.documentElement.style.webkitTouchCallout='none';"];//禁止長(zhǎng)按
//javascript 注入
WKUserScript *noneSelectScript = [[WKUserScript alloc] initWithSource:javascript
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:YES];
WKUserContentController*userContentController = [[WKUserContentController alloc] init];
[userContentController addUserScript:noneSelectScript];
WKWebViewConfiguration*configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = userContentController;
//控件加載
[self.webView.configuration.userContentController addUserScript:noneSelectScript];
[self.view addSubview:self.webView];
[self.webView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.bottom.equalTo(self.view);
}];
以上是我的個(gè)人見(jiàn)解,有問(wèn)題請(qǐng)大家指出,謝謝大家.