我正在使用新的wkWebView,用于OS X和iOS系统。为了将webview呈现为图标,我需要获取所呈现URL的favicon。在旧的webview中,我可以使用以下函数:
var mainFrameIcon: NSImage! { get }
使用Swift或Objective-C中的wkWebView如何获取图像?
我正在使用新的wkWebView,用于OS X和iOS系统。为了将webview呈现为图标,我需要获取所呈现URL的favicon。在旧的webview中,我可以使用以下函数:
var mainFrameIcon: NSImage! { get }
NSURL *webpageURL = myWebView.URL;
NSString *hostURL = webpageURL.host;
NSString *faviconURL = [NSString stringWithFormat:@"http://%@/favicon.ico",hostURL];
NSImage *faviconImage = [[NSImage alloc] initWithContentsOfURL:[NSURL URLWithString:faviconURL]];
像其他帖子中的许多人所说,现在找到一个网站的 favicon 并不是一件容易的事情。
因此,我开发了一个开源框架来为您处理繁重的工作。 https://github.com/will-lumley/FaviconFinder/
不幸的是,获取网站图标不再是一个简单的属性。原因是网站可以为不同的分辨率声明多个favicon。您(应用程序开发人员)需要为自己的需求选择适当的图标。
另一个复杂之处在于,您(应用程序开发人员)需要在WKWebView对象中执行JavaScript才能从链接标签中获取网站图标!
(注意:依赖/favicon.ico会出现错误。有些网站不更新其CMS的/favicon.ico,并仅通过链接标签设置它。在这种情况下,一个在Chrome中具有正确图标的页面可能会在您的自定义浏览器中显示Drupal图标。)
以下是解析链接标签的JavaScript以及进一步阅读结果的Swift代码。
// Based on code from https://dev59.com/l2kv5IYBdhLWcg3w4kt3
static private var GET_FAVICON_SCRIPT = """
var favicons = [];
var nodeList = document.getElementsByTagName('link');
for (var i = 0; i < nodeList.length; i++)
{
if((nodeList[i].getAttribute('rel') == 'icon')||(nodeList[i].getAttribute('rel') == 'shortcut icon'))
{
const node = nodeList[i];
favicons.push({
url: node.getAttribute('href'),
sizes: node.getAttribute('sizes')
});
}
}
favicons;
"""
public private(set) var faviconUrls = Set<FaviconUrl>()
func updateFavicon() {
self.webView.evaluateJavaScript(TabViewController.GET_FAVICON_SCRIPT) { (result, error) in
// Favicon is returned from Javascript as an NSMutableArray with NSMutableDictionaries
// Needs to be turned into a list
var faviconUrls = Set<FaviconUrl>();
// If the script returned correctly
if let favicons = result as? NSArray {
for faviconObject in favicons {
if let faviconDictionary = faviconObject as? NSDictionary {
if let urlString = faviconDictionary["url"] as? String {
// The favicon url (href in link tag) needs to be resolved to the url from the page
if let url = URL(string: urlString, relativeTo: self.webView.url) {
let sizesString = faviconDictionary["sizes"] as? String;
let sizeStrings = sizesString?.components(separatedBy: "x") ?? []
if (sizeStrings.count == 2) {
let width = Int(sizeStrings[0])
let height = Int(sizeStrings[1])
faviconUrls.insert(FaviconUrl(url: url, width: width, height: height))
} else {
faviconUrls.insert(FaviconUrl(url: url, width: nil, height: nil))
}
}
}
}
}
}
// If no favicons were found, fallback to /favicon.ico
// Note that some sites never replace the one that comes with the CMS. If you don't
// use Javascript to parse the <link ...> tags, a site that works correctly in Chrome
// could have a Drupal icon in your application
if faviconUrls.count == 0 {
if let webViewUrl = self.webView.url {
let schemeAndHostUrl = webViewUrl.deletingPathExtension()
let url = schemeAndHostUrl.appendingPathComponent("favicon.ico")
faviconUrls.insert(FaviconUrl(url: url, width: nil, height: nil))
}
}
if (faviconUrls != self.faviconUrls) {
self.faviconUrls = faviconUrls
self.delegate?.faviconChanged()
}
if error != nil {
NSLog("Can not determine favicons: %@", error?.localizedDescription ?? "")
}
}
}
为了完整起见,这里是FaviconUrl类:
import Cocoa
class FaviconUrl: NSObject {
public private(set) var url: URL
public private(set) var width: Int?
public private(set) var height: Int?
init(url: URL, width: Int?, height: Int?) {
self.url = url
self.width = width
self.height = height
}
public var area: Int? {
get {
if let width = self.width {
if let height = self.height {
return width * height;
}
}
return nil
}
}
}