Forum Archive

SFSafariViewController as a ui.View

coltonboyd

I was wondering if any of you that are good with objc_util could help me out.

I would like to present a SFSafariViewController as a ui.View from a ui.View that is already presented.

Or be able to add SFSafariViewController as a subview for the already presented view.

Thx in advance.

cvp

@coltonboyd see here

cvp

@coltonboyd or

import ui
from objc_util import *

import os

#========= SFSafariViewController to allow Safari extension in WebView
def safariViewControllerDidFinish_(_self, _cmd, _controller):
    #print('SafariViewControllerDidFinish_')
    SFSafariViewController = ObjCInstance(_controller)
    #....... still close view problems
    try:
        SFSafariViewController.uiview.close()
    except Exception as e:
        SFSafariViewController.uiview().close()

methods = [safariViewControllerDidFinish_,]
protocols = ['SFSafariViewControllerDelegate']
try:
        MySFSafariViewControllerDelegate = ObjCClass('MySFSafariViewControllerDelegate')
except:
    MySFSafariViewControllerDelegate = create_objc_class('MySFSafariViewControllerDelegate', methods=methods, protocols=protocols)

@on_main_thread 
def MySFSafariViewController(url, w=None, h=None, local=None, popover_location=None, reader=False):
    uiview = ui.View()
    uiview.background_color = 'white'
    if w and h:
        uiview.frame = (0,0,w,h)
        uiview.present('sheet',hide_title_bar=True)
    else:
        uiview.present('fullscreen',hide_title_bar=True)

    # SFSafariViewController only accepts http: or https:,  not file:
    # thus, in this case, we need to create a local server
    ns_url = nsurl(url)

    SFSafariViewControllerConfiguration = ObjCClass('SFSafariViewControllerConfiguration').alloc().init()
    #
    SFSafariViewControllerConfiguration.setEntersReaderIfAvailable_(reader)
    SFSafariViewController = ObjCClass('SFSafariViewController').alloc().initWithURL_configuration_(ns_url,SFSafariViewControllerConfiguration)
    #print(dir(SFSafariViewController))

    # Use new delegate class:
    delegate = MySFSafariViewControllerDelegate.alloc().init()
    SFSafariViewController.delegate = delegate      
    SFSafariViewController.setModalPresentationStyle_(3)
    SFSafariViewController.uiview   = uiview        # used by delegate

    objc_uiview = ObjCInstance(uiview)
    SUIViewController = ObjCClass('SUIViewController')
    vc = SUIViewController.viewControllerForView_(objc_uiview)  

    vc.presentViewController_animated_completion_(SFSafariViewController, True, None)

if __name__ == '__main__':  
    url = 'https://www.eqsl.cc/qslcard/Index.cfm'
    url = 'http://www.kanisette.com/2018/06/roule-au-saumon-et-courgettes.html'
    MySFSafariViewController(url,600,500)   

coltonboyd

@cvp to clarify I am attempting to run this is the most current Xcode Template. Your code is good starting place but when I tried it was just a blank white screen. The code I am trying to incorporate is:

from objc_util import *

SFSafariViewController = ObjCClass('SFSafariViewController')

@on_main_thread
def open_in_safari_vc(url, tint_color=None):
    vc = SFSafariViewController.alloc().initWithURL_(nsurl(url))
    if tint_color is not None:
        vc.view().tintColor = tint_color
    app = UIApplication.sharedApplication()
    root_vc = app.keyWindow().rootViewController()
    root_vc.presentViewController_animated_completion_(vc, True, None)
    vc.release()

open_in_safari_vc('http://apple.com', UIColor.orangeColor())

Basically I have an ui.View called App that is presented from the point of where the iOS app starts. When clicking on a button view on this App class I want it to open a SFSafariViewController with the designated url given to the open_in_safari_vc function.

When I attempt this in the Xcode Template I get this error:

[Presentation] Attempt to present <SFSafariViewController: 0x7fbfa7a98000> on <PYAViewController: 0x7fbfa4408e80> (from <PYAViewController: 0x7fbfa4408e80>) whose view is not in the window hierarchy.

I hope this clarifies what I'm trying to do.

coltonboyd

Also to add, I added the code above to a blank main.py file in a blank Xcode project and it worked just fine. I think it has something to do with the App ui.View that I am presenting.

cvp

@coltonboyd I can't help you with Xcode....

coltonboyd

For anybody following this thread I figured how to present SFSafariViewController from an already presented view:

```

Necessary imports.

from objc_util import *

class WebView():
@on_main_thread
def init(self,url,uiview,bar_tint_color,control_tint_color):
self.safari_view_controller = ObjCClass("SFSafariViewController").alloc().initWithURL_(nsurl(url))
self.safari_view_controller.preferredBarTintColor = bar_tint_color
self.safari_view_controller.preferredControlTintColor = control_tint_color
self.view_controller = ObjCClass('UIViewController').viewControllerForView_(ObjCInstance(uiview))

@on_main_thread
def present(self):
self.view_controller.presentViewController_animated_completion_(self.safari_view_controller,True,None)

cvp

@coltonboyd sorry, I didn't correctly understood your post ๐Ÿ™„

coltonboyd

@cvp itโ€™s all good. Your code gave me a good starting place and led me to the code I got so thank you!