這段時間在開發一個應用,其中大部分頁面是加載Web頁面,而UINavigationController原生框架的標題是根據頁面加載結束,回調UIWebViewDelegate的時候獲取的,示例代碼如下。
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
self.navigationItem.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
}
大部分Web頁面跳轉頁面的時候都是重新加載URL,從而會觸發UIWebViewDelegate回調。
問題來了,如果是Vue單頁應用呢?因為Vue在加載時會一次性加載所有內容,而在該頁面操作跳轉都不需要重新加載URL,就不會觸發UIWebViewDelegate回調。
可是如果我們還是需要在每次切換頁面的時候獲取Web信息時該怎么辦呢,顯然從UIWebViewDelegate回調中獲取是不可能的了。在網上搜索了一下,基本的辦法都是讓Web開發修改代碼或者增加Schema調用。
辦法總是有的,畢竟Web頁面是運行在原生上,如果原生都無法解決這問題,還怎么混下去。
現在說一下我的解決辦法,用幀刷新回調!
因為我這里的需求就是獲取Web頁面的標題和加載情況等,所以我可以在每一幀的回調中獲取Web頁面的狀態(這里就不要用定時器了,你確定每秒執行一次?看看CPU占用率!)
直接上代碼吧
@interface WebViewController ()<UIWebViewDelegate>
@property(nonatomic, retain) UIWebView *webView;
@property(nonatomic, retain) CADisplayLink *displayLick;
@end
@implementation WebViewController
- (void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
if(_displayLick == nil){ // 初始化幀回調
_displayLick = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink)];
}
[_displayLick addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; // 因為viewWillAppear是在主線程里面執行的,所以是添加到主線程的RunLoop。
}
- (void) viewDidDisappear:(BOOL)animated
{
if(_displayLick != nil){ // 跳轉到其他頁面就把幀回調移除
[_displayLick removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
}
- (void) handleDisplayLink
{
self.navigationItem.title = [_webView stringByEvaluatingJavaScriptFromString:@"document.title"]; // 獲取標題
_webView.isLoading; // 是否正在加載
}
@end