This method does not seem to work consistently: SFSafariViewControllerDelegate.safariViewController(_ controller: SFSafariViewController, initialLoadDidRedirectTo URL: URL)
It was working 100% of the time until this week for me, now it has about a 1-5% success rate for detecting redirects.
The docs are not clear:
@discussion This method may be called even after -safariViewController:didCompleteInitialLoad: if
the web page performs additional redirects without user interaction.
Code snippet from calling UIViewController that conforms to SFSafariViewControllerDelegate:
let config = SafariViewController.Configuration()
config.entersReaderIfAvailable = false
let vc = SFSafariViewController(url: url, configuration: config)
vc.delegate = self
self.safariViewController = vc
print(self.safariViewController?.delegate)
self.present(vc, animated: true)
Did something change? How can I make this consistent again?
Safari Services
RSS for tagEnable web views and services in your app using Safari Services.
Posts under Safari Services tag
35 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
For some reason, not all of the time but most of the time, the SFSafariViewControllerDelegate method for initialLoadDidRedirectTo is not being triggered for subsequent reloads as specified in the docs.
@discussion This method may be called even after -safariViewController:didCompleteInitialLoad: if
the web page performs additional redirects without user interaction.
I am allowing a user to log in with an OAuth 2.0 Provider on the Safari browser and expecting to detect the redirect to continue the flow from the app once their credentials have securely been consumed by the IdP in Safari.
It was working consistently. It went from a 100% success rate up until this week to maybe 1/20 successful redirects.
Code snippet:
let config = SafariViewController.Configuration()
config.entersReaderIfAvailable = false
let vc = SFSafariViewController(url: url, configuration: config)
vc.delegate = self
self.safariViewController = vc
print(self.safariViewController?.delegate)
self.present(vc, animated: true)
Why is it not always detecting the redirects?
Preamble: I am creating an iOS build of a Ren'Py game. My coding experience with Swift/ObjC is nearly nonexistent and I've primarily followed tutorials up to this point. Ren'Py uses an underlying framework to create an Xcode project. I do not have control over how this framework does things, but I can add files before actually compiling inside Xcode. I MUST use the pyobjus library to do so based on my current understanding, abilities, and frameworks. The included IAPHelper class processes in-app purchasing and it works great! The following function indicates, however, that there is a rootViewController that I need to attach to.
- (void) showDialog {
if (alert != nil) {
return;
}
alert = [UIAlertController
alertControllerWithTitle:self.dialogTitle
message:nil
preferredStyle:UIAlertControllerStyleAlert ];
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge];
// Adjust the indicator so it is up a few pixels from the bottom of the alert
indicator.center = CGPointMake(alert.view.bounds.size.width / 2, alert.view.bounds.size.height - 50);
[indicator startAnimating];
[alert.view addSubview: indicator];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
[UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:alert animated:YES completion:nil];
#pragma clang diagnostic pop
}
Problem: I am TRYING to implement an in-app browser for Patreon authentication purposes. The files I have put together are as follows:
BrowserViewController.h
// BrowserViewController.h
#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
@interface BrowserViewController : UIViewController
- (void)loadURL:(NSString *)urlString;
@end
BrowserViewController.m
// BrowserViewController.m
#import "BrowserViewController.h"
@interface BrowserViewController ()
@property (nonatomic, strong) WKWebView *webView;
@end
@implementation BrowserViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.webView = [[WKWebView alloc] initWithFrame:self.view.frame];
[self.view addSubview:self.webView];
NSLog(@"viewDidLoad");
}
- (void)loadURL:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
NSLog(@"loadURL");
}
@end
OAuth2Strategy.py
init python in auth:
from urllib.parse import urlencode, urlparse, parse_qs
from urllib.request import urlopen, Request
import ssl
import certifi
from store import webserver, OpenURL
import json
class OAuth2Strategy():
def __init__(self, authorization_url, token_url, client_id, client_secret, callback_url, scope):
self.authorization_url = authorization_url
self.token_url = token_url
self.client_id = client_id
self.client_secret = client_secret
self.callback_url = callback_url
self.scope = scope
self.on_success_callback = None
self.on_fail_callback = None
def run(self, on_success_callback = None, on_fail_callback = None):
self.on_success_callback = on_success_callback
self.on_fail_callback = on_fail_callback
webserver.start(self)
if renpy.renpy.ios:
from pyobjus import autoclass, objc_str
# Import the Objective-C class
BrowserViewController = autoclass('BrowserViewController')
# Create an instance of the BrowserViewController
browser = BrowserViewController.alloc().init()
# Load a URL
url = self.make_authorize_url()
browser.loadURL_(objc_str(url))
elif renpy.renpy.android:
pass
else:
renpy.run(OpenURL(self.make_authorize_url()))
def make_authorize_url(self):
return self.authorization_url + "?client_id={client_id}&scope={scope}&redirect_uri={redirect_uri}&response_type=code".format(
client_id=self.client_id,
scope=self.scope,
redirect_uri=self.redirect_uri,
)
@property
def redirect_uri(self):
return "http://127.0.0.1:" + str(webserver.PORT) + self.callback_url
def handle_auth(self, request):
parsed_path = urlparse(request.path)
query = parse_qs(parsed_path.query)
code = query.get("code")
if not code:
request.send_response(400)
request.send_header('Content-type', 'text/html')
request.end_headers()
request.wfile.write(b'Failed to authenticate. You can now close this window.')
webserver.stop()
if self.on_fail_callback:
self.on_fail_callback()
return
code = code[0]
tokens = self.get_tokens(code)
request.send_response(200)
request.send_header('Content-type', 'text/html')
request.end_headers()
request.wfile.write(b'Success! You can now close this window.')
webserver.stop()
if self.on_success_callback:
self.on_success_callback(tokens)
def get_tokens(self, code):
ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH, cafile=certifi.where())
data = urlencode({
"grant_type": "authorization_code",
"code": code,
"client_id": self.client_id,
"client_secret": self.client_secret,
"redirect_uri": self.redirect_uri,
}).encode("utf-8")
headers = {"Content-Type": "application/x-www-form-urlencoded"}
req = Request(self.token_url, data=data, headers=headers, method="POST")
response = urlopen(req, context=ctx)
data = response.read().decode("utf-8")
data = json.loads(data)
return data
If I use the default OpenURL function Safari opens as the full blown browser rather than in-app, hence why I am trying to override it. When I run my app and click the button that SHOULD spawn the browser, nothing happens. I can see that my URL is getting pushed to the function in the log along with Warning: -[BETextInput attributedMarkedText] is unimplemented and Failed to request allowed query parameters from WebPrivacy. though my admittedly light research indicates this isn't an issue. I have a feeling I'm not attaching my webView to the right hierarchy but I'm not sure exactly what I'm doing wrong.
I have a link that is embedded in the app using WKWebView. This link is working fine in the Macbook Safari browser, But it's not open in iPhone Safari and wkWebView in the app.
Hi, I am developing a drawing app using SafariView and is using apple pencil double tap handler for crucial features.
In IOS 17.5 I lost functionality of it when interacting with SafariView, my friend confirmed that it worked with IOS 17.4 and I can confirm it also worked with IOS 17.1. However, I cannot downgrade my system nor can my uses. THIS IS A FATAL MALFUNCTION FOR MY APP.
Detailedly, as I tested, the double tap handlers cannot be activated when my last tapped component is SafariView, so it never works when interacting with my web app. But I can enable this by clicking outside the SafariView or some non-SafariView component on top of it, just anything other than the Safari view, even webkit view can work but it is not usable for me. My aim is to keep listening to double tapping while interacting with SafariView in full screen, so I cannot let the user tap elsewhere to just activate double tap, there is no other walk around for me, unless there is a way to enable 120fps animation in WebKit view, which is only available in safari feature flags as I know.
I would like to hear a solution in this situation or a promise of a fix, this is devastating to my users' experience.
code to reproduce:
import SwiftUI
import WebKit
import SafariServices
struct SafariView: UIViewControllerRepresentable {
let url: URL
func makeUIViewController(context: Context) -> SFSafariViewController {
return SFSafariViewController(url: url)
}
func updateUIViewController(_ uiViewController: SFSafariViewController, context: Context) {
// No update code needed for this example
}
}
struct WKWebViewWrapper: UIViewRepresentable {
let url: URL
func makeUIView(context: Context) -> WKWebView {
let webView = WKWebView()
let request = URLRequest(url: url)
webView.load(request)
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {
// No update code needed for this example
}
}
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
.onPencilDoubleTap { value in
print("tap1")
}
Text("Hello, world!")
.padding()
SafariView(url: URL(string: "https://www.example.com")!)
.onPencilDoubleTap { value in print("tap2")}
.frame(width:300)
WKWebViewWrapper(url: URL(string: "https://www.example.com")!).onPencilDoubleTap { value in
print("tap3")
}
.frame(width:300)
}
}
}
#Preview {
ContentView()
}
I want to implement in-app purchases for my Mac Safari web extension.
I can think of two ways:
Draw the payment UI in an extension web page, and send a message to the native extension app to call StoreKit code.
Open the container app from an extension web page, where the app draws the payment UI.
I couldn't make #1 work with either
StoreKit 2, which is async, and context.completeRequest(returningItems:) doesn't want to be called in a Task, saying context is not sendable)
or StoreKit 1, where calling context.completeRequest(returningItems:) in paymentQueue(_:updatedTransactions:) for some reason doesn't return a response to the extension's web page.
I couldn't make #2 work because I couldn't find a way to open the container app from the web extension. I registered a custom URL for my container app, but context.open that url does nothing.
Web extensions that use IAP with #2 are available on the Mac app store, so it must be possible, could anyone shed some light on how to open the container app and pass the purchased info to the extension web page even if the container app is not open?
Thanks in advance.
The SFSafariViewController documentation mentions not to display content from websites when using the pageSheet and formSheet presentation styles for the In-App browser.
Is this a hard restriction that is enforced or more of a loose guideline? And if possible, providing the reasoning behind it would be great.
Thanks in advance.
Scenario:
Apple decided to not support PWAs in Europe in IOS 17.4. My company has multiple Angular PWAs, all using IndexedDB and providing full offline-usage as main feature, that apparently won't work anymore.
The apps communicate with a server. We maintain two versions of that server, e.g. v1.1 and v1.2 - some customers don't want or can't upgrade to v1.2 just yet. Not all new features of an app will get implemented in v1.1, and eventually we won't push updates for it anymore. At some point, we'll have the same situation with e.g. v1.2 and v1.3.
My questions:
Do I understand correctly that offline-usage and IndexedDB features won't work anymore?
If I wrap the PWAs via Capacitor and upload them as Custom App via App Store Connect, in IOS 17.4...
Will the app, including routing, work offline?
Will the IndexedDb still be usable as permanent data storage?
Can I upload v1.1 and v1.2 as separate apps or will I have to create on app with in-app purchase options? If it's the latter, how do I push updates? Apparently, Apple Review can cause problems with separate apps that have similar functions...
Thank you for your time!
I recently noticed that using Google Docs, Google Sheets, and any other Google-related sites on a Safari browser uses tons of RAM. It usually consumes around 4-5 GB of RAM.
Compare it to when I use Google Docs on Chrome; it only uses around 1-2 GB.
Why is this so? I want to use Safari alone for work, but it's so slow. Do you have any tips on this?
Getting this error on some safari devices on few it is working.
{"logs":["Unable to generate ICNS file for push notification package"]}
https://monayqa.washgas.com/portal/auth/payment/2814a6ac-e9ef-4e54-86c3-a9e811cb46d2
Hi, I need to intercept from a UIViewController the postMessage that originate from the web page that is rendered in the SFSafariViewController component, is it possible to do it? how would be the correct implementation? thanks!
Hello, since the last iOS 17.4 Europe update, and since the implementation of new rules for default browsers, PWAs no longer work. In fact, they are nothing more than shortcuts for internet pages, so this makes the application unusable, which could not necessarily be launched in install mode with notifications. I tried looking for changes but couldn't find them. I think it's linked to the fact that you can install applications from the web from a marketplace. If anyone has a solution or the same problem. Thank you
On Safari Mobile and iOS version 16 or 17, while scrolling the webpage, the function browser.tabs.captureVisibleTab() is not returning the expected screen image.
The image is cropped from the top.
The probable reason for the same is the collapsible Address Bar.
The below attached image is the iPad mini (6th generation ) Simulator OS Version:17.0 simulator
The below attached image is created by browser.tabs.captureVisibleTab()
I tested it on
iPad mini (6th generation ) Simulator OS Version:17.0 and
iPad (8th generation) - iPadOS Version 16.2.
Hello everyone, i want to set transparent status bar (where wifi and time), in my pwa app, writing on html, using manifest.manifest and sw.js, i make:
and this not work, i am want but this work on ios 15-17.xx, who know, how do setup this variable?
Hi! I'm working on an iOS Safari extension that has a ServiceWorker. Lately we've noticed that this ServiceWorker seems to get killed seemingly at random, and there are no logs or crash reports to tell us what happened.
I'm hypothesizing that iOS might be shutting down Safari ServiceWorkers when the ProcessInfo.thermalState approaches .serious. I have circumstantial evidence that our ServiceWorker tends to get killed more often at higher levels of thermalState but can't yet say conclusively that this is the case. I can't find any direct evidence of this on internet searches either.
Is anyone able to shed light onto this topic? The specific symptoms are:
ServiceWorker stops, and the menu entry for its console window no longer appears on macOS Safari.
No crash logs via Xcode or Sentry, and no Console messages as far as we could tell (caveat: MobileSafari generates a LOT of messages! We might have missed it.)
If attached via debugger, the native part of our extension just disappears and the debugger loses connection with no error message.
ServiceWorker no longer works for the lifetime of the Safari process. Sometimes, when we kill Safari and restart, we can get the ServiceWorker back. This usually requires toggling our extension's "enabled" state in system settings.
In some cases, even killing/relaunching Safari and toggling the system setting doesn't bring our ServiceWorker back. I'm hypothesizing right now that this happens when the thermal state is high.
I've tried simulating a serious/critical thermal state in the Xcode Devices window, but couldn't repro the ServiceWorker problem. I don't know if that setting affects the whole system, though, or just our own apps.
Help appreciated!
Yuna