将委托分配给视图控制器以外的其他对象时未调用 SFSafariViewControllerDelegate 方法
SFSafariViewControllerDelegate methods not called when assigning delegate to something other than view controller
我有一个简单的视图控制器,它在点击 link 按钮时显示 SFSafariViewController。
#import "ViewController.h"
#import "SafariDelegate.h"
@interface ViewController ()
@property(nonatomic, strong) NSString *url;
@property(nonatomic, weak) SafariDelegate *safariDelegate;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.url = @"http://www.google.com";
}
- (IBAction)linkTapped:(id)sender {
SFSafariViewController *vc = [[SFSafariViewController alloc] initWithURL:[NSURL URLWithString:self.url]];
SafariDelegate *safariDelegate = [[SafariDelegate alloc] init];
vc.delegate = safariDelegate;
[self presentViewController:vc animated:YES completion:nil];
}
@end
SafariDelegate 符合 SFSafariViewControllerDelegate 并仅在委托方法触发时记录。
SafariDelegate.h
#import <Foundation/Foundation.h>
#import <SafariServices/SafariServices.h>
@interface SafariDelegate : NSObject <SFSafariViewControllerDelegate>
@end
SafariDelegate.m
#import "SafariDelegate.h"
@implementation SafariDelegate
- (NSArray<UIActivity *> *)safariViewController:(SFSafariViewController *)controller activityItemsForURL:(NSURL *)URL title:(nullable NSString *)title
{
NSLog(@"safariViewController activityItemsForURL");
return @[];
}
- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller
{
NSLog(@"safariViewControllerDidFinish");
}
- (void)safariViewController:(SFSafariViewController *)controller didCompleteInitialLoad:(BOOL)didLoadSuccessfully
{
NSLog(@"safariViewController didCompleteInitialLoad");
}
@end
当我点击按钮时,safariviewcontroller 正确加载页面,但从未调用委托方法(包括当我点击 'Done' 时)。我在显示 'vc' 的行设置了一个断点,并确认在该点正确设置了委托。我错过了什么?
SafariViewController
不保留它的委托,所以它在你的 linkTapped:
方法 returns 之后立即被释放,因为没有其他东西对它有强引用。
你需要在某处保留对它的强引用。您可能只需将当前视图控制器中的 属性 更改为 strong
并将其存储在那里。您也可以将其保存在 Safari 浏览器视图控制器上的关联对象中。
我也遇到了同样的问题。
我创建了 "SafariViewController inside of function"。因此,SafariViewController 内存被清除。所以,我无法从 SafariViewControllerDelegate 获取触发器。
我终于找到了解决这个问题的方法。
当您在 class 中创建 SFSafariViewController 时。您必须将其声明为 全局变量 .
class Foo: NSObject {
var safariVC: SFSafariViewController!
}
然后您可以分配您的 SafariViewController。
func config(_ loadUrl: URL) {
if #available(iOS 11.0, *) {
let config = SFSafariViewController.Configuration()
config.barCollapsingEnabled = true
config.entersReaderIfAvailable = true
safariVC = SFSafariViewController(url: loadUrl, configuration: config)
} else {
// Fallback on earlier versions
safariVC = SFSafariViewController(url: loadUrl)
}
}
然后设置一个代表
self.safariVC.delegate = self
终于出现了 safariViewController。
UIApplication.shared.keyWindow?.rootViewController?.present(safariVC, animated: true, completion: nil)
现在肯定会触发 safariViewController 委托。
// MARK: - SFSafariViewControllerDelegate
extension Foo: SFSafariViewControllerDelegate {
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
print("SafariVC is dismissed")
}
}
我有一个简单的视图控制器,它在点击 link 按钮时显示 SFSafariViewController。
#import "ViewController.h"
#import "SafariDelegate.h"
@interface ViewController ()
@property(nonatomic, strong) NSString *url;
@property(nonatomic, weak) SafariDelegate *safariDelegate;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.url = @"http://www.google.com";
}
- (IBAction)linkTapped:(id)sender {
SFSafariViewController *vc = [[SFSafariViewController alloc] initWithURL:[NSURL URLWithString:self.url]];
SafariDelegate *safariDelegate = [[SafariDelegate alloc] init];
vc.delegate = safariDelegate;
[self presentViewController:vc animated:YES completion:nil];
}
@end
SafariDelegate 符合 SFSafariViewControllerDelegate 并仅在委托方法触发时记录。
SafariDelegate.h
#import <Foundation/Foundation.h>
#import <SafariServices/SafariServices.h>
@interface SafariDelegate : NSObject <SFSafariViewControllerDelegate>
@end
SafariDelegate.m
#import "SafariDelegate.h"
@implementation SafariDelegate
- (NSArray<UIActivity *> *)safariViewController:(SFSafariViewController *)controller activityItemsForURL:(NSURL *)URL title:(nullable NSString *)title
{
NSLog(@"safariViewController activityItemsForURL");
return @[];
}
- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller
{
NSLog(@"safariViewControllerDidFinish");
}
- (void)safariViewController:(SFSafariViewController *)controller didCompleteInitialLoad:(BOOL)didLoadSuccessfully
{
NSLog(@"safariViewController didCompleteInitialLoad");
}
@end
当我点击按钮时,safariviewcontroller 正确加载页面,但从未调用委托方法(包括当我点击 'Done' 时)。我在显示 'vc' 的行设置了一个断点,并确认在该点正确设置了委托。我错过了什么?
SafariViewController
不保留它的委托,所以它在你的 linkTapped:
方法 returns 之后立即被释放,因为没有其他东西对它有强引用。
你需要在某处保留对它的强引用。您可能只需将当前视图控制器中的 属性 更改为 strong
并将其存储在那里。您也可以将其保存在 Safari 浏览器视图控制器上的关联对象中。
我也遇到了同样的问题。 我创建了 "SafariViewController inside of function"。因此,SafariViewController 内存被清除。所以,我无法从 SafariViewControllerDelegate 获取触发器。
我终于找到了解决这个问题的方法。
当您在 class 中创建 SFSafariViewController 时。您必须将其声明为 全局变量 .
class Foo: NSObject {
var safariVC: SFSafariViewController!
}
然后您可以分配您的 SafariViewController。
func config(_ loadUrl: URL) {
if #available(iOS 11.0, *) {
let config = SFSafariViewController.Configuration()
config.barCollapsingEnabled = true
config.entersReaderIfAvailable = true
safariVC = SFSafariViewController(url: loadUrl, configuration: config)
} else {
// Fallback on earlier versions
safariVC = SFSafariViewController(url: loadUrl)
}
}
然后设置一个代表
self.safariVC.delegate = self
终于出现了 safariViewController。
UIApplication.shared.keyWindow?.rootViewController?.present(safariVC, animated: true, completion: nil)
现在肯定会触发 safariViewController 委托。
// MARK: - SFSafariViewControllerDelegate
extension Foo: SFSafariViewControllerDelegate {
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
print("SafariVC is dismissed")
}
}