我想为我的应用程序使用自定义URL方案,但是无法配置URL方案。
当我以编程方式创建WKWebView对象时(使用initWithFrame:...),我能够指定自己的WKWebViewConfiguration对象,但是当在Nib / Storyboard中自动创建WKWebView时(通过initWithCoder :),我无法指定组态。该配置为只读,因此事后我无法对其进行更改。如果可能,我真的希望避免以编程方式创建WkWebView。
注意:存在与此相关的问题(here),但是在那里接受的答案仅解决了实际程序的一部分(涉及添加用户脚本而不是配置)对象,因此无法添加自定义网址方案处理程序)。那里的其他答案都不能解决这个问题,因此我提出了另一个问题。
答案 0 :(得分:0)
如何创建包含WKWebView的自定义视图。您可以在Storyboard中代替WKWebView使用此视图。
final class MyWebView: UIView {
var webView: WKWebView!
required init?(coder: NSCoder) {
super.init(coder: coder)
let config = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: config)
addSubview(webView)
}
override func layoutSubviews() {
super.layoutSubviews()
webView.frame = bounds
}
}
要自定义情节提要中的其他属性,请将@IBInspectable
添加到包装视图并将该值传递给内部配置。
下面的代码缺少情节提要中WKWebView的某些属性,但是 可以实现其他这样的属性。
final class MyWebView: UIView {
@IBInspectable var userAgent: String?
@IBInspectable var appName: String? {
didSet {
config.applicationNameForUserAgent = appName
}
}
private var types: WKDataDetectorTypes = [
.phoneNumber,
.link,
.address,
.calendarEvent,
.trackingNumber,
.flightNumber,
.lookupSuggestion
]
@IBInspectable var phoneNumber: Bool = true {
didSet {
if phoneNumber {
types.insert(.phoneNumber)
} else {
types.remove(.phoneNumber)
}
config.dataDetectorTypes = types
}
}
@IBInspectable var link: Bool = true {
didSet {
if link {
types.insert(.link)
} else {
types.remove(.link)
}
config.dataDetectorTypes = types
}
}
@IBInspectable var address: Bool = true {
didSet {
if address {
types.insert(.address)
} else {
types.remove(.address)
}
config.dataDetectorTypes = types
}
}
@IBInspectable var calendarEvent: Bool = true {
didSet {
if calendarEvent {
types.insert(.calendarEvent)
} else {
types.remove(.calendarEvent)
}
config.dataDetectorTypes = types
}
}
@IBInspectable var trackingNumber: Bool = true {
didSet {
if trackingNumber {
types.insert(.trackingNumber)
} else {
types.remove(.trackingNumber)
}
config.dataDetectorTypes = types
}
}
@IBInspectable var flightNumber: Bool = true {
didSet {
if flightNumber {
types.insert(.flightNumber)
} else {
types.remove(.flightNumber)
}
config.dataDetectorTypes = types
}
}
@IBInspectable var lookupSuggestion: Bool = true {
didSet {
if phoneNumber {
types.insert(.lookupSuggestion)
} else {
types.remove(.lookupSuggestion)
}
config.dataDetectorTypes = types
}
}
@IBInspectable var javaScriptEnabled: Bool = true {
didSet {
config.preferences.javaScriptEnabled = javaScriptEnabled
}
}
@IBInspectable var canAutoOpenWindows: Bool = false {
didSet {
config.preferences.javaScriptCanOpenWindowsAutomatically = canAutoOpenWindows
}
}
lazy var webView: WKWebView = {
let webView = WKWebView(frame: .zero, configuration: config)
webView.customUserAgent = userAgent
addSubview(webView)
return webView
}()
private var config = WKWebViewConfiguration()
override func layoutSubviews() {
super.layoutSubviews()
webView.frame = bounds
}
}
答案 1 :(得分:-1)
所以,我做了一些测试:
@interface ViewController ()
@property (strong) IBOutlet WKWebView *webView ;
@end
@implementation ViewController
- (void) awakeFromNib
{
static BOOL hasBeenDone = NO ; // because otherwise, awakeFromNib is called twice
if (!hasBeenDone)
{
hasBeenDone = YES ;
// Create the scheme handler
SchemeHandler *mySchemeHandler = [SchemeHandler new] ;
NSLog(@"scheme handler : %lx",mySchemeHandler) ;
if (!(self.webView))
{
// Case 1 - we don't have a web view from the StoryBoard, we need to create it
NSLog(@"Case 1") ;
// Add the scheme
WKWebViewConfiguration *configuration = [WKWebViewConfiguration new] ;
[configuration setURLSchemeHandler:mySchemeHandler
forURLScheme:@"stef"] ;
// Create and set the web view
self.webView = [[WKWebView alloc] initWithFrame:NSZeroRect
configuration:configuration] ;
}
else
{
// Case 2 - we have a web view from the story board, just set the URL scheme handler
// of the configuration
NSLog(@"Case 2") ;
WKWebViewConfiguration *configuration = self.webView.configuration ;
[configuration setURLSchemeHandler:mySchemeHandler
forURLScheme:@"stef"] ;
}
// Log the view configuration
NSLog(@"View configuration : %lx",self.webView.configuration) ;
NSLog(@"URL handler for scheme : %lx",[self.webView.configuration urlSchemeHandlerForURLScheme:@"stef"]) ;
}
}
- (void) viewDidLoad
{
[super viewDidLoad] ;
// Log the view configuration
NSLog(@"View configuration : %lx",self.webView.configuration) ;
NSLog(@"URL handler for scheme : %lx",[self.webView.configuration urlSchemeHandlerForURLScheme:@"stef"]) ;
// Start loading a URL with the scheme - this should log "start" if everything works fine
NSURL *url = [NSURL URLWithString:@"stef://willIWinTheBounty?"] ;
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url] ;
[self.webView loadRequest:urlRequest] ;
}
@end
如果在情节提要中未设置IBOutlet webView的情况下运行该代码(案例1),则该代码将创建Web视图,为方案配置它,一切都很好。
方案处理程序:600000008e30
案例1
查看配置:600003d0c780
方案的网址处理程序:600000008e30
查看配置:600003d0c780
方案的网址处理程序:600000008e30
方案处理程序启动
如果在情节提要中设置了IBOutlet webView的情况下运行该代码(案例2),则setURLSchemeHandler:forURLScheme:实际上不起作用。在这种情况下,urlSchemeHandlerForURLScheme的日志将返回nil。
方案处理程序:600000005160
案例2
查看配置:600003d08d20
方案的网址处理程序:0
查看配置:600003d08d20
方案的网址处理程序:0
请注意,未调用方案处理程序启动
原因不是您通过getter获得了不同的副本,因为配置日志表明它保持不变。尽管调用了setURLSchemeHandler:forURLScheme,但只是没有设置方案处理程序。
因此,我想唯一的解决方案是使用案例1。根据您的视图设置,插入视图可能会或多或少地困难。我建议您在故事板上使用一个空的“母亲”视图,并使用以下代码:
@interface ViewController ()
@property (weak) IBOutlet NSView *webViewMother ;
@property (strong) WKWebView *webView ;
@end
@implementation ViewController
- (void) awakeFromNib
{
static BOOL hasBeenDone = NO ; // because otherwise, awakeFromNib is called twice
if (!hasBeenDone)
{
hasBeenDone = YES ;
// Create the scheme handler
SchemeHandler *mySchemeHandler = [SchemeHandler new] ;
// Create the configuration
WKWebViewConfiguration *configuration = [WKWebViewConfiguration new] ;
[configuration setURLSchemeHandler:mySchemeHandler
forURLScheme:@"stef"] ;
// Create the web view at the size of its mother view
self.webView = [[WKWebView alloc] initWithFrame:self.webViewMother.frame
configuration:configuration] ;
[self.webViewMother addSubview:self.webView] ;
// Log the view configuration
NSLog(@"View configuration : %lx",self.webView.configuration) ;
NSLog(@"URL handler for scheme : %lx",[self.webView.configuration urlSchemeHandlerForURLScheme:@"stef"]) ;
}
}
@end
对我来说很好,但是如果您有Web视图的子视图,则可能会很棘手。
查看配置:600003d082d0
方案的网址处理程序:600000004c90
查看配置:600003d082d0
方案的网址处理程序:600000004c90
方案处理程序启动
请注意,配置通过调用保持不变...
编辑:添加了运行日志