Get Control of & feedback from Webpage Or iOS/Mac App using the (newish) WKWebView

I have just started exploring WKWebView Os X for OS X apps. But the API is much the same for WKWebView iOS
The documentation could as usual do with some expanding and examples

But I just found a really good tutorial that shows how to create an IOS app and pass javascript between the app and the UI in the webpage.

This is Awesome and will open up so many things for controlling apps from the web UI that use the WKWebView and sending data to the web pages from the App.

One other thing to note is LocalStaorage etc… just works out of the bag with WKWebView, no extra code in your app needed

Here is the link to the Tutorial at http://www.joshuakehn.com which also has a link to the full source code. Go check it out…

Also if you can It would be great to see any ideas you come up with using it.

3 Likes

One small note about WKWebViews on both Mac an iOS is that they don’t work with file:/// URLs. This makes it a bit trickier to work with Hype content embedded in your application package. Luckily this deficiency is going to be addressed in iOS 9 and OS X 10.11.

@jonathan

Huh,

In the Kiosk App Project - #2 by MarkHunte I am playing with, the last version posted can use a default webpage that is in the bundle and and uses the normal API to get the url.

The App is also able to choose a file from the finder??.

The returned url is in the form of "file:///"

I do not do anything special apart from having the url stored in the user prefs. Then picked up again by the WKWebView request from the prefs. ?

10.10 xcode 6.4

My thinking is that this could be used to add Achievements and High Scores to games made with Hype, then ported to iOS. I haven't gotten to that part yet. I'm still trying to get games to work.

This week I got closer with Full-Screen mode and scrolling games. I'm not quite sure how to get the two working together. Anyway... with closer to native performance, a WKWebView template (in Xcode) could be cooked up to make it easy to port Hype games to Mac and iOS. If the document scaling issue gets fixed... Scaling content together - #5 by MarkHunte ...then I can create a game once and port it to multiple platforms.

I highly suspect that the WKWebView will be available on the new Apple TV, but I'm waiting to see what happens when the new model is announced. If it is available, that's the equivalent of creating console games.

This has been a dream I've been working towards for decades, so it's very important that I get this WKWebView stuff straightened out. Right now, it seems a little too bleeding edge. I tried building a WebView in Swift, then converting it to WKWebView, it was not as easy as I thought it would be. I think @jonathan is on to something, as I remember seeing some issue with iOS 8 vs iOS 9. I forgot exactly what it was though.

This is an area where Hype can kick the competition's ass. I'm a web developer. I hate making apps. Hype should export to Xcode and have ways to support common iOS features, like Game Center.

The nice thing about Hype is that if they don't do it, I only have to figure it out once. I'm thinking that porting Hype games to iOS should be a chapter in the book. I haven't decided what to do with templates / downloadable Hype projects yet. I might make them freely available at my site or the source might be available through the book.

Here is an example for a Mac Os X App. But should be easily convertible to iOS

The App has a Hype html embedded in the Bundle.

The Hype scene has two buttons that call a really simple Javascript function with the Mouse Click Actions

  var pWindow = element.id;
  
   window.webkit.messageHandlers.observe.postMessage(pWindow);

Button 1 (Prefs ) will open a window in the App which is called Prefs
Button 2 (Window 2 ) will open a window in the App which is called Window 2

These buttons use the callback method already shown in the other example above.

The Callback will also populate the innerHTML of a text box in the scene. ( The text comes from the App not the html doc)


In the Apps Window 2 you will see a Button named Run timeline.

This is connected to a IBAction in the App, which will send a direct call to the webpage to run a timeline.

The important think for this part to work is to use the code below inside your Head tag of the hype document.

	<script>
function myCallback(hypeDocument, element, event) {
window.myhypedocument = hypeDocument;
}

if("HYPE_eventListeners" in window === false) {
window.HYPE_eventListeners = Array();
}
window.HYPE_eventListeners.push({"type":"HypeDocumentLoad", "callback":myCallback});
</script>

The Apps IBAction’s code is then :

//-- Direct call From App Action to Webpage

- (IBAction)runTimeline:(id)sender {
    
    NSString *exec_template = @"window.myhypedocument.startTimelineNamed('timeline1');$('#headline').html(\"received: %@\");";
    NSString *theMessage = @"Call from App = Run Timeline";
    
    NSString *exec = [NSString stringWithFormat:exec_template, theMessage];
    //NSString *exec = [NSString stringWithFormat:exec_template, version];
    [_weviewM evaluateJavaScript:exec completionHandler:nil];
    
    
   
}

This is all really simple. and I think much easier to do with Hype than native HTML as we can use the built in function to construct the callback in the page.

i.e from this:

<script type="text/javascript">
    $(function () {
        var headline = $("#headline");
        var selection = $("#selector");
        function set_headline (text) {
            headline.text(text);
        }

        function call_native () {
            var prop = selection.val();
           set_headline("asked for " + prop + "..."); window.webkit.messageHandlers.observe.postMessage(prop);
        }

        setTimeout(call_native, 1000);

        selection.on("change", call_native);

        // Expose that function globally
        window.call_native = call_native;
    });
</script>

To this using a Hype function and actions:

  var pWindow = element.id;
      
   window.webkit.messageHandlers.observe.postMessage(pWindow);

Although I admit I am using buttons and not a dropdown… but hopefully you get the idea


Xcode Project

WKViewJavascriptExample.zip (1.0 MB)

Hype doc used:

AppControlTestWithWKWebView.hypetemplate.zip (14.9 KB)

I have made a new example that may show some usage better.

  • It shows direct calls to the webpages from the App to control
    timelines.

  • Calls from the webpages to the App to control the App UI. Obviously
    if the App allows your webpage can send calls to do much more than
    just control the App ui

.


xcode Project.

WKViewJavascriptExample 2.zip (1.2 MB)


Code signed App
WKViewJavascriptExample.app.zip (236.1 KB)


Hype Projects used

WKViewJavascriptExample 2 Used Projects.zip (75.3 KB)

I wrote a another, very simple Xcode Swift /project that shows how to control your document from the iOS app it is embedded in.

I actually did this because I miss read another thread:smile: and originally posted this there.

The poster wanted to refresh or restart the scene if the user came out of in Safari on an iPhone.
For some reason I read that as came out of an iOS app with a Hype document.

So any way here is the new simpler example.

The idea is to add Notification observers in the iOS app that listen to when the App has resigned active status or Enters the Foreground.

Resigning active states will happen when you come out of the app when you hit the home button.
The app enters the foreground when it is the active app.

Apart from show how you can use the native cocoa API to trigger changes in your document, it also show you how simple it is to control your document by sending javascript calls to the Hype document.

(In the example we do not send any calls from the Hype document to the App)

Here is a example Xcode project with all this in.

The Hype document has three scenes.

The first one has an Ellipse that moves to cross a line. When it does the scene will change to one with a Rect in animation (scene 2)

When we exit the app, the UIApplicationWillResignActiveNotification Notification will fire it’s function and the third scene ( splash scene )will fade in.

When we come back to the App, the UIApplicationWillEnterForegroundNotification Notification will fire it’s function and the first scene will fade in and start again.

Xcode 8 project

iOSHypeCalls.zip (287.4 KB)

3 Likes

This is an update of the Example above to take into account some changes in Xcode Version 9.0 (9A235) & Swift 4. , NotificationCenter Observers to swift 4 syntax and moved Objective C APIs to Swift APIs i.e NSURLRequest(url: theUrl!) to URLRequest(url: theUrl!)

Changing the Objective C API will help avoid using @objc inference.

TheSwift 3 compiler infers @objc behind the scenes on any Objective C api calls/functions for you. Swift 4 does not and you would need to add them your self or use the conversion tool when opening and older project.

Google for this if you need more info.

So for example.

Old Observer:

 NotificationCenter.default.addObserver(self, selector: #selector(enterBackground), name: NSNotification.Name("UIApplicationWillResignActiveNotification"), object: nil)

Old function :

func enterBackground()  {
        print("call 1")
        
         self.webView!.evaluateJavaScript("HYPE.documents['testCall'].showSceneNamed('splashScene', HYPE.documents['testCall'].kSceneTransitionCrossfade, 0.2);", completionHandler:nil )
       
    }

function with @objc inference and using old observer

 @objc func enterBackground()  {
        print("call 1")
        
         self.webView!.evaluateJavaScript("HYPE.documents['testCall'].showSceneNamed('splashScene', HYPE.documents['testCall'].kSceneTransitionCrossfade, 0.2);", completionHandler:nil )
       
    }

New observer and New function

  NotificationCenter.default.addObserver(forName:Notification.Name(rawValue:"UIApplicationWillResignActiveNotification"),
                                               object:nil, queue:nil,
                                               using:enterBackground)     

func enterBackground(notification:Notification) -> Void {
        print("call 1")
        
        webView!.evaluateJavaScript("HYPE.documents['testCall'].showSceneNamed('splashScene', HYPE.documents['testCall'].kSceneTransitionCrossfade, 0.2);", completionHandler:nil )
        
    }

Everything works the same.

iOSHypeCalls_v2_swift4.zip (299.7 KB)

2 Likes

Owing to a request on how to get an iOS app with a Hype scene to do a screen capture, I have written a quick example.

The main reason I am doing this is because I wanted a version of these example in swift which is now the more common way people want to write iOS apps.

So with much explaining since the concepts are above.

Here is a Swift version that shows how to send the calls from a Hype scene to the Parent App.

iOS_WKWebView iOS screen Capture.zip (288.9 KB)

2 Likes