如何在 UIView 中呈现 SFSafariViewController

How to present SFSafariViewController in UIView

我有一个带有按钮 属性 的自定义 UIView,我想向它添加一个操作以在应用程序中打开 webview。为此,我想使用 SFSafariViewController。这就是我正在努力实现这一目标的方法。

import UIKit
import SafariServices

class CustomViewScreen: UIView, SFSafariViewControllerDelegate {

@IBAction func privacyNoteBtnAction(_ sender: UIButton) {
    if #available(iOS 9.0, *) {
        let urlString = "https://whosebug.com/"
        if let url = URL(string: urlString) {
            let vc = SFSafariViewController(url: url, entersReaderIfAvailable: true)
            vc.delegate = self
           UIApplication.shared.keyWindow?.rootViewController?.present(vc, animated: true, completion: nil)
        }
    } else {
        // Fallback on earlier versions
    }
}

func safariViewControllerDidFinish(_ controller: SFSafariViewController) { 
  controller .dismiss(animated: true, completion: nil) // also not able to trigger this method when i tap "Done"
}

我什至不能 属性 使用这种方式,因为我收到“谁的视图不在 window 层次结构中!”此外,我无法在点击 "Done" 按钮后调用 SFSafariViewControllerDelegate 方法来关闭视图。当我在 UIView 中时有什么想法可以给出动作,或者有什么想法可以将此动作连接到我的主控制器以使用正确呈现的方法吗?

这样做,

@IBAction func privacyNoteBtnAction(_ sender: UIButton) {
   if #available(iOS 9.0, *) {
    let urlString = "https://whosebug.com/"
    if let url = URL(string: urlString) {
        let vc = SFSafariViewController(url: url, entersReaderIfAvailable: true)
        vc.delegate = self

       if var topController = UIApplication.shared.keyWindow?.rootViewController {
          while let presentedViewController = topController.presentedViewController {
              topController = presentedViewController
          }

          topController.present(vc, animated: true, completion: nil)
       }

    }
} else {
    // Fallback on earlier versions
}
}

我不这么认为。 UIView 无法显示 viewcontroller,因为它们不同。您只能在 viewcontroller.

中显示 viewcontroller

所以我建议你的视图只获取触摸事件,并委托给 viewcontroller ,告诉它呈现一个 SFSafariViewController。像这样:

// view.h
@protocol AccountBindingDelegate <NSObject>
- (void)jumpWebVC:(UIButton*)sender;
@end
@interface CustomRegisterView : UIView
@property (nonatomic, weak) id<AccountBindingDelegate> delegate;
@end

// view.m
[agreementBtn addTarget:self action:@selector(agreementBtnClick:) forControlEvents:UIControlEventTouchUpInside];

- (void)agreementBtnClick:(UIButton*)sender
{
    if (self.delegate && [self.delegate respondsToSelector:@selector(jumpWebVC:)]) {
        [self.delegate jumpWebVC:sender];
    }
}

// code in controller
@interface uiviewContrller ()<AccountBindingDelegate> 

@end

- (void)viewDidLoad {
    _registerView.delegate = self;
}

//tell viewcontroller to present
- (void)jumpWebVC:(UIButton*)sender
{
    PSMFWebVC *webVC = [PSMFWebVC new];
    [self.navigationController pushViewController:webVC animated:YES];
}

UIView 不需要知道url,他只是告诉viewcontroller:uiview 中的某个按钮被点击了。如果你的 uivew 有很多按钮,你的 CustomViewScreen 会很重,这不好。

import UIKit
import SafariServices

class ViewController: UIViewController {

    var safariVC = SFSafariViewController(url: URL(string: "https://apple.com")!)
    
    override func viewDidLoad() {
        super.viewDidLoad()
        addViewControllerAsChildViewController()
    }
    
    //firstVCIdentifier
    
    func addViewControllerAsChildViewController() {
        addChild(safariVC)
        self.view.addSubview(safariVC.view)
        safariVC.didMove(toParent: self)
        self.setUpConstraints()
    }
    
    func setUpConstraints() {
        self.safariVC.view.translatesAutoresizingMaskIntoConstraints = false
        self.safariVC.view.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 100).isActive = true
        self.safariVC.view.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: -100).isActive = true
        self.safariVC.view.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor, constant: 100).isActive = true
        self.safariVC.view.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: -100).isActive = true
    }

}