iOSHTMLViewer.LoadURL only working in simulator

I don’t know why this is, but iOSHTMLViewer.LoadURL does nothing on devices. Did try it on iPad and iPhone.
I want to view html files located in the documents folder. In simulator it does the job perfectly. On the devices I get a white screen.
When I read the content of the html files in the documents folder and put that in the html viewer thru .LoadPage it does show the content.

How is that possible?
And can anybody present me a work around?

I had the same problem:

https://forum.xojo.com/49364-using-a-website-api-to-return-an-image

In my case I was getting an image back from a website, and ended up having to use HTTPSocket and an imageview to display it. Here’s what I ended up with:

https://forum.xojo.com/49532-httpsocket-post-multipart

I found a post on the Apple developer forum with a similar problem in Swift https://forums.developer.apple.com/thread/100125 . As it seems they solved the problem. Can this solution be translated to Xojo?

@J van der Putten — The solution you mentioned from Apple’s forum uses the NSFileManager. You can do it this way:

[code]const CocoaLib = “Cocoa.framework”

Declare Function NSClassFromString Lib CocoaLib ( aClassName as CFStringRef ) As Ptr
Declare function defaultManager lib CocoaLib selector “defaultManager” (cls as Ptr) as Ptr
Declare Function URLForDirectory lib CocoaLib selector “URLForDirectory:inDomain:appropriateForURL:create:error:” ( mgr as Ptr, dir as integer, domain as integer, aurl as Ptr, create as Boolean, error as Ptr ) as Ptr
Declare function absoluteString lib CocoaLib selector “absoluteString” (id as Ptr) as CFStringRef

dim fileManagerClass as Ptr = NSClassFromString( “NSFileManager” )
dim fileManager as Ptr = defaultManager( fileManagerClass )

dim url as Ptr = URLForDirectory( fileManager, 9, 1, nil, false, nil )
dim path as string = absoluteString( url )[/code]

@StphaneMons Thanks for your reply. However I get a linking executable error now when I build or run the app: framework not found Cocoa. Am I doing something wrong?

Change the constant to “Foundation”

Cocoa is only for desktop.

Thanks Greg, that solved that problem!
But I’m not sure how to implement the code. Where do I assign the file path?
Can you show me how I can load a local html file in the iOSHTMLviewer?

[quote=425535:@J van der Putten]Thanks Greg, that solved that problem!
But I’m not sure how to implement the code. Where do I assign the file path?
Can you show me how I can load a local html file in the iOSHTMLviewer?[/quote]
Make a folderitem that points to the file and then pass the URLPath property to LoadURL.

I know, that is just the problem. It works fine on the simulator, but not on a device. And the path is correct; I can read the content of the file.

Here the code in the open event handler of the view that contains the iOSHTMLViewer “htmlPresentation”

[code]Dim baseFolder As Xojo.IO.FolderItem
Dim htmlFile As Xojo.IO.FolderItem
Dim htmlPath As Text

baseFolder = Xojo.IO.SpecialFolder.Documents
htmlFile = baseFolder.Child(“index.html”)

If htmlFile <> Nil And htmlFile.Exists Then
htmlPath = htmlFile.URLPath
Self.htmlPresentation.LoadURL(htmlPath)
End If[/code]

@J van der Putten — But you are still using SpecialFolder.Documents which you know does not work

@StphaneMons I know, how do I use in this example the code you supplied?

@J van der Putten — Copy the following code and paste it into a module.

[code]Function DocumentsFolder() as FolderItem
const CocoaLib = “Foundation.framework”

Declare Function NSClassFromString Lib CocoaLib ( aClassName as CFStringRef ) As Ptr
Declare function defaultManager lib CocoaLib selector “defaultManager” (cls as Ptr) as Ptr
Declare Function URLForDirectory lib CocoaLib selector “URLForDirectory:inDomain:appropriateForURL:create:error:” ( mgr as Ptr, dir as integer, domain as integer, aurl as Ptr, create as Boolean, error as Ptr ) as Ptr
Declare function absoluteString lib CocoaLib selector “absoluteString” (id as Ptr) as CFStringRef

dim fileManagerClass as Ptr = NSClassFromString( “NSFileManager” )
dim fileManager as Ptr = defaultManager( fileManagerClass )

dim url as Ptr = URLForDirectory( fileManager, 9, 1, nil, false, nil )
dim path as string = absoluteString( url )

dim f as new FolderItem( path, FolderItem.PathTypeURL )
return f
End Function[/code]

Then replace all your calls to SpecialFolder.Documents to DocumentsFolder.

Please try this.

htmlFile is a xojo.io.folderitem pointing to the html file in SpecialFolder.Documents

[code]Declare Function NSClassFromString Lib “Foundation.framework” (clsName As CFStringRef) As ptr
Declare Function URLWithString Lib “Foundation.framework” Selector “URLWithString:” ( id As Ptr, URLString As CFStringRef ) As Ptr

Declare sub loadFileURL lib “UIKit.framework” selector “loadFileURL:allowingReadAccessToURL:” (obj as ptr, url as ptr, readAccessURL as ptr)

Dim nsURL As Ptr = URLWithString(NSClassFromString(“NSURL”), htmlFile.URLPath)
Dim readURL As Ptr = URLWithString(NSClassFromString(“NSURL”), htmlFile.parent.URLPath)

loadFileURL(htmlPresentation.Handle, nsURL, readURL)[/code]

=== EDIT ===
Explanation from apple forums thread

[quote]The most important thing in my code is not the way how to get url or path, but using the method loadFileURL(_:allowingReadAccessTo:).

In fact, the core part of WKWebView runs in a different process (or processes, maybe), which does not have read access to an app’s Documents folder where it it Sandboxed.

In simulators, some part of macOS file system is simulated as an iOS devices file system, but the protection of Sandboxing is sort of loose and the process of WKWebView can access the Documents directory of the app.

allowingReadAccessTo: allows temprary read access to the WKWevView process (I do not know the detail, just that it works), so even in strictly Sandboxed environment, loadFileURL(_:allowingReadAccessTo:) would work as expected.[/quote]

@Jeremie Leroy You’re a lifesaver!!!

LoadFile function has been added to https://github.com/jkleroy/iOSDesignExtensions

Jeremie’s declares were working fine for me but are now failing.

It seems that as long as I am loading html files from the documents folder it all works fine… but once I load an “external” url like “http://somelink.com” then I can no longer load files from the documents folder… I get an “Error: loading doc (1) The operation couldn’t be completed. Operation not permitted”.

Any ideas are appreciated.

You need to add to the plist, same as in the docs:
https://documentation.xojo.com/api/deprecated/xojo.net.httpsocket.html

Scoll down on page

Derk…

Thanks for the reply but my plist does already include:

NSAppTransportSecurity

NSAllowsArbitraryLoads

Is there something else I am missing?

My code works in the debugger but not in the built app.

[quote=466710:@Jim Meyer]Jeremie’s declares were working fine for me but are now failing.

It seems that as long as I am loading html files from the documents folder it all works fine… but once I load an “external” url like “http://somelink.com” then I can no longer load files from the documents folder… I get an “Error: loading doc (1) The operation couldn’t be completed. Operation not permitted”.

Any ideas are appreciated.[/quote]

I found a work-around for my problem.

My Xojo project settings include a Build Automation that copies my “local” HTML files into the app’s Resources folder. When the app first opens it copies those files from Resources into Documents… which is where I would access them at runtime. (I thought that was the proper thing to do.) Now I just leave them in the Resources folder and access them from there.

Trying to re-open this problem.

This is not working for me as I need to modify some js/css file on the fly, they have to be placed in Document folder.

Using loadFileURL from @Jeremie Leroy doesn’t work for me, I’m still getting Sandbox error when running on the device.
Errors in console are:

Sandbox: com.apple.WebKit(1140) deny(1) file-issue-extension target:/Private/Var/mobile/Containers/Data/Application/72AA325C-46D4-4C1F-AC31-204C753AA0C4/Documents/html/index.html Class:com.apple.app-sandbox.read Sandbox: com.apple.WebKit(1141) deny(1) file-read-data /Private/Var/mobile/Containers/Data/Application/72AA325C-46D4-4C1F-AC31-204C753AA0C4/Documents/html/index.html

The console reports 2 other Sandbox errors before, but I don’t think they are coming from my code (Xojo ?):

Sandbox: myapp(1161) deny(1) sysctl-read kern.bootargs Sandbox: myapp(1161) deny(2) file-test-existence /private/etc/.mdns_debug