WKWebView에서 target="_blank" 링크를 열지 않는 이유는 무엇입니까?
WKWebView
를 포함하는 링크를 열지 않습니다.target="_blank"
a.k.a. HTML의 '새 창에서 열기' 속성<a href>
-태그.
제 해결책은 탐색을 취소하고 loadRequest:로 요청을 다시 로드하는 것입니다.이는 현재 프레임에서 항상 새 창을 여는 UI WebView와 유사한 동작이 됩니다.
구현WKUIDelegate
위임 및 설정_webview.uiDelegate
그런 다음 구현:
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
if (!navigationAction.targetFrame.isMainFrame) {
[webView loadRequest:navigationAction.request];
}
return nil;
}
@Cloud Xu의 답은 정답입니다.참고로 Swift에는 다음이 있습니다.
// this handles target=_blank links by opening them in the same view
func webView(webView: WKWebView!, createWebViewWithConfiguration configuration: WKWebViewConfiguration!, forNavigationAction navigationAction: WKNavigationAction!, windowFeatures: WKWindowFeatures!) -> WKWebView! {
if navigationAction.targetFrame == nil {
webView.load(navigationAction.request)
}
return nil
}
Swift 4.2+의 최신 버전을 사용하려면 다음과 같이 하십시오.
import WebKit
WKUID 딜러와 함께 강의를 확장
웹 보기에 대한 대리자 설정
self.webView.uiDelegate = self
프로토콜 방법 구현
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
if navigationAction.targetFrame == nil {
webView.load(navigationAction.request)
}
return nil
}
WK 내비게이션 딜러로 자신을 수행합니다.
_webView.navigationDelegate = self;
딜러 콜백 결정에서 다음 코드를 구현합니다. PolicyForNavigationAction:decisionHandler:
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
//this is a 'new window action' (aka target="_blank") > open this URL externally. If we´re doing nothing here, WKWebView will also just do nothing. Maybe this will change in a later stage of the iOS 8 Beta
if (!navigationAction.targetFrame) {
NSURL *url = navigationAction.request.URL;
UIApplication *app = [UIApplication sharedApplication];
if ([app canOpenURL:url]) {
[app openURL:url];
}
}
decisionHandler(WKNavigationActionPolicyAllow);
}
추신: 이 코드는 사용 가능한 UI를 WKWebView에 감싼 제 작은 프로젝트에서 가져온 것입니다.
WKWebView.navigationDelegate를 이미 설정한 경우
WKWebView.navigation 딜러 = 자체;
다음을 구현하기만 하면 됩니다.
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
BOOL shouldLoad = [self shouldStartLoadWithRequest:navigationAction.request]; // check the url if necessary
if (shouldLoad && navigationAction.targetFrame == nil) {
// WKWebView ignores links that open in new window
[webView loadRequest:navigationAction.request];
}
// always pass a policy to the decisionHandler
decisionHandler(shouldLoad ? WKNavigationActionPolicyAllow : WKNavigationActionPolicyCancel);
}
이렇게 하면 WKUID 위임 방법을 구현할 필요가 없습니다.
Cloud xu
의 대답이 제 문제를 해결합니다.
동일한 Swift(4.x/5.0) 버전이 필요한 경우 다음과 같습니다.
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
if let frame = navigationAction.targetFrame,
frame.isMainFrame {
return nil
}
// for _blank target or non-mainFrame target
webView.load(navigationAction.request)
return nil
}
당연히 설정해야 합니다.webView.uiDelegate
첫째로
이러한 솔루션 중 어떤 것도 저에게 효과가 없었습니다. 저는 다음과 같은 방법으로 문제를 해결했습니다.
WKUID 딜러 구현
@interface ViewController () <WKNavigationDelegate, WKUIDelegate>
wkWebview의 UID 대리인 설정
self.wkWebview.UIDelegate = self;
create WebView 구현구성 방법 포함
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
if (!navigationAction.targetFrame.isMainFrame) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[[UIApplication sharedApplication] openURL:[navigationAction.request URL]];
}
return nil; }
Bill Weinman의 Swift 코드가 맞는지 확인합니다.하지만 당신이 저처럼 개발하는 iOS를 처음 사용하는 경우를 대비하여 UID 대표를 위임해야 한다는 것을 언급할 필요가 있습니다.
이와 같은 것:
self.webView?.UIDelegate = self
그래서 여러분이 변경해야 하는 세 가지 장소가 있습니다.
다른 보기 컨트롤러를 누르거나 새 탭을 열 수도 있습니다.
func webView(webView: WKWebView, createWebViewWithConfiguration configuration: WKWebViewConfiguration, forNavigationAction navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
var wv: WKWebView?
if navigationAction.targetFrame == nil {
if let vc = self.storyboard?.instantiateViewControllerWithIdentifier("ViewController") as? ViewController {
vc.url = navigationAction.request.URL
vc.webConfig = configuration
wv = vc.view as? WKWebView
self.navigationController?.pushViewController(vc, animated: true)
}
}
return wv
}
allenhuang 답변 기준
세부 사항
- Xcode 버전 10.3(10G8), 스위프트 5
대상
- 연결 검색
target=“_blank”
push
web을 사용하여 컨트롤러 보기현재 컨트롤러의 경우 보기navigationController
present
webView가 포함된 컨트롤러 보기다른 모든 경우
해결책
webView.uiDelegate = self
// .....
extension ViewController: WKUIDelegate {
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
guard navigationAction.targetFrame == nil,
let url = navigationAction.request.url else { return nil }
let vc = ViewController(url: url, configuration: configuration)
if let navigationController = navigationController {
navigationController.pushViewController(vc, animated: false)
return vc.webView
}
present(vc, animated: true, completion: nil)
return nil
}
}
전체샘플
정보.plist
Info.plist 전송 보안 설정에 추가
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
뷰 컨트롤러
import UIKit
import WebKit
class ViewController: UIViewController {
private lazy var url = URL(string: "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_links_target")!
private weak var webView: WKWebView!
init (url: URL, configuration: WKWebViewConfiguration) {
super.init(nibName: nil, bundle: nil)
self.url = url
navigationItem.title = ""
}
required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
override func viewDidLoad() {
super.viewDidLoad()
initWebView()
webView.loadPage(address: url)
}
private func initWebView() {
let webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
view.addSubview(webView)
self.webView = webView
webView.navigationDelegate = self
webView.uiDelegate = self
webView.translatesAutoresizingMaskIntoConstraints = false
webView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
webView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true
webView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
webView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
}
}
extension ViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
guard let host = webView.url?.host else { return }
navigationItem.title = host
}
}
extension ViewController: WKUIDelegate {
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
guard navigationAction.targetFrame == nil,
let url = navigationAction.request.url else { return nil }
let vc = ViewController(url: url, configuration: configuration)
if let navigationController = navigationController {
navigationController.pushViewController(vc, animated: false)
return vc.webView
}
present(vc, animated: true, completion: nil)
return nil
}
}
extension WKWebView {
func loadPage(address url: URL) { load(URLRequest(url: url)) }
func loadPage(address urlString: String) {
guard let url = URL(string: urlString) else { return }
loadPage(address: url)
}
}
스토리보드
버전 1
버전 2
모바일 Safari에서 _bank 페이지를 여는 방법 및 Swift를 사용하는 경우:
webView.navigationDelegate = self
WKNavigation 딜러에게 이를 구현합니다.
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if navigationAction.targetFrame == nil, let url = navigationAction.request.url {
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
decisionHandler(WKNavigationActionPolicy.allow)
}
이것은 저에게 효과가 있었습니다.
-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
if (!navigationAction.targetFrame.isMainFrame) {
WKWebView *newWebview = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
newWebview.UIDelegate = self;
newWebview.navigationDelegate = self;
[newWebview loadRequest:navigationAction.request];
self.view = newWebview;
return newWebview;
}
return nil;
}
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
decisionHandler(WKNavigationActionPolicyAllow);
}
- (void)webViewDidClose:(WKWebView *)webView {
self.view = self.webView;
}
보다시피, 우리가 여기서 하는 일은 단지 새로운 것을 여는 것입니다.webView
새로운 URL로 마감될 가능성을 제어하고, 단지 당신이 그것으로부터 응답이 필요할 때.second webview
첫 번째에 표시됩니다.
를 사용하여 해결할 수 없는 몇 가지 문제가 발생했습니다.webView.load(navigationAction.request)
그래서 저는 새 웹 뷰를 만드는 작업을 하는데 잘 작동합니다.
//MARK:- WKUIDelegate
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
NSLog(#function)
if navigationAction.targetFrame == nil {
NSLog("=> Create a new webView")
let webView = WKWebView(frame: self.view.bounds, configuration: configuration)
webView.uiDelegate = self
webView.navigationDelegate = self
self.webView = webView
return webView
}
return nil
}
**Use following function to create web view**
func initWebView(configuration: WKWebViewConfiguration)
{
let webView = WKWebView(frame: UIScreen.main.bounds, configuration: configuration)
webView.uiDelegate = self
webView.navigationDelegate = self
view.addSubview(webView)
self.webView = webView
}
override func viewDidLoad() {
super.viewDidLoad()
if webView == nil { initWebView(configuration: WKWebViewConfiguration()) }
webView?.load(url: url1)
}
**WKUIDelegate Method need to be implemented**
extension WebViewController: WKUIDelegate {
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
// push new screen to the navigation controller when need to open url in another "tab"
print("url:\(String(describing: navigationAction.request.url?.absoluteString))")
if let url = navigationAction.request.url, navigationAction.targetFrame == nil {
let viewController = WebViewController()
viewController.initWebView(configuration: configuration)
viewController.url1 = url
DispatchQueue.main.async { [weak self] in
self?.navigationController?.pushViewController(viewController, animated: true)
}
return viewController.webView
}
return nil
}
}
extension WKWebView
{
func load(url: URL) { load(URLRequest(url: url)) }
}
이 방법을 사용하여 웹 보기에서 PDF를 다운로드합니다.
func webView(_ webView: WKWebView, WebView 만들기구성: WKWebViewConfiguration, 탐색 작업: WKNavigationAction, 창 기능: WKWindowFeatures) -> WKWebView?
언급URL : https://stackoverflow.com/questions/25713069/why-is-wkwebview-not-opening-links-with-target-blank
'programing' 카테고리의 다른 글
사이드바에 페이지 추가 (0) | 2023.06.23 |
---|---|
woocommerce 새 주문 전자 메일에 제품 미리 보기 표시 (0) | 2023.06.23 |
한 열에 특정 값을 가질 수 있도록 데이터베이스 테이블을 제한하는 방법은 무엇입니까? (0) | 2023.06.23 |
스프링 보안에 대한 요청 Matchers() 이해 (0) | 2023.06.23 |
traceback / sys.exc_info() 값을 변수에 저장하는 방법은 무엇입니까? (0) | 2023.06.23 |