Ios 如何在UIView中显示SFSafariViewController

Ios 如何在UIView中显示SFSafariViewController,ios,swift,uiwebview,webkit,sfsafariviewcontroller,Ios,Swift,Uiwebview,Webkit,Sfsafariviewcontroller,我有一个自定义UIView,它有一个按钮属性,我想向它添加一个操作以在应用程序中打开webview。为此,我想使用SFSafariViewController。以下是我如何努力实现这一目标的 import UIKit import SafariServices class CustomViewScreen: UIView, SFSafariViewControllerDelegate { @IBAction func privacyNoteBtnAction(_ sender: UIButt

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

import UIKit
import SafariServices

class CustomViewScreen: UIView, SFSafariViewControllerDelegate {

@IBAction func privacyNoteBtnAction(_ sender: UIButton) {
    if #available(iOS 9.0, *) {
        let urlString = "https://stackoverflow.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"
}
我甚至不能正确地使用这种方式,因为我得到了“谁的视图不在窗口层次结构中!”并且我不能在点击“完成”按钮后调用SFSafariViewControllerDelegate方法来关闭视图。当我在UIView中时,有没有想过要执行操作,或者有没有想过要将此操作连接到我的主控制器以使用正确的呈现方法?

这样做

@IBAction func privacyNoteBtnAction(_ sender: UIButton) {
   if #available(iOS 9.0, *) {
    let urlString = "https://stackoverflow.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
}
}
这样做,

@IBAction func privacyNoteBtnAction(_ sender: UIButton) {
   if #available(iOS 9.0, *) {
    let urlString = "https://stackoverflow.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

所以我建议您的视图只需获取touch事件,并委托给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];
}
//view.h
@协议AccountBindingDelegate
-(无效)jumpWebVC:(UIButton*)发送器;
@结束
@接口CustomRegisterView:UIView
@属性(非原子,弱)id委托;
@结束
//view.m
[agreementBtn addTarget:self action:@selector(agreementBtnClick:)for ControlEvents:UIControlEventTouchUpInside];
-(作废)协议点击:(UIButton*)发送者
{
if(self.delegate&&[self.delegate respondsToSelector:@selector(jumpWebVC:)])){
[self.delegate jumpWebVC:sender];
}
}
//控制器中的代码
@接口uiviewContrller()
@结束
-(无效)viewDidLoad{
_registerView.delegate=self;
}
//告诉viewcontroller显示
-(无效)jumpWebVC:(UIButton*)发送器
{
PSMFWebVC*webVC=[PSMFWebVC新];
[self.navigationController pushViewController:webVC动画:是];
}

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

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

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
    }

}
所以我建议您的视图只需获取touch事件,并委托给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];
}
//view.h
@协议AccountBindingDelegate
-(无效)jumpWebVC:(UIButton*)发送器;
@结束
@接口CustomRegisterView:UIView
@属性(非原子,弱)id委托;
@结束
//view.m
[agreementBtn addTarget:self action:@selector(agreementBtnClick:)for ControlEvents:UIControlEventTouchUpInside];
-(作废)协议点击:(UIButton*)发送者
{
if(self.delegate&&[self.delegate respondsToSelector:@selector(jumpWebVC:)])){
[self.delegate jumpWebVC:sender];
}
}
//控制器中的代码
@接口uiviewContrller()
@结束
-(无效)viewDidLoad{
_registerView.delegate=self;
}
//告诉viewcontroller显示
-(无效)jumpWebVC:(UIButton*)发送器
{
PSMFWebVC*webVC=[PSMFWebVC新];
[self.navigationController pushViewController:webVC动画:是];
}
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
    }

}


您只能在另一个视图控制器上显示视图控制器……您不能在视图中显示视图控制器……相反,您可以添加其他视图控制器的子视图……发生了什么
self.present(
您只能在另一个视图控制器上显示视图控制器……您不能在视图中显示视图控制器……相反,您可以添加其他视图控制器的子视图……发生了什么
self.present(