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.
This is my ViewController for the WKWebView:
// IABrowser.m
#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
@interface IABrowser : UIViewController {
UIWindow *window;
}
@property (nonatomic, strong) WKWebView *webView;
@end
@implementation IABrowser
- (void)viewDidLoad {
[super viewDidLoad];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
window = [[ UIApplication sharedApplication] keyWindow];
#pragma clang diagnostic pop
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
[ [ [ window subviews ] objectAtIndex: 0 ] addSubview: self.webView];
// [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
Here is the Python file where I’m using pyobjus to spawn the in-app browser:
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
# Import the Objective-C class
InAppBrowser = autoclass('IABrowser')
# Create an instance of the BrowserViewController
browser = InAppBrowser.alloc().init()
# Load a URL
url = self.make_authorize_url()
browser.loadURL_(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
The problem I’m running into is that I get a log message from the loadURL
function but it doesn’t actually load the WKWebView and I don’t know why. I assume it’s because I haven’t parented the view to the root view controller properly but I’m not sure where I’ve gone wrong specifically.
I’m happy to share the entire Xcode project after I sanitize some auth codes out of it if that would be more helpful.
I have the worst nagging feeling that the solution is right in front of my face but I just can’t see it.
Black Cat is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.