Building hybrid apps; is it even possible?

Taking a look at it right now!!

have you used nativescript… its awesome

One thing to add here is that iOS app usually build pretty well especially with WKWebview, but Android always seems to be the problem.

Is sharing the same UIWebView possible? (http://stackoverflow.com/questions/32341819/using-the-same-uiwebview-across-different-viewcontrollers)

Yes, you should be able to move the UIWebView from one view controller to the other. Just make sure you add the right constraints or set an autoresizing mask when you add it as a subview.

1 Like

I’d appreciate it a lot if you could take a look at this when you have 10 minutes to spare. For some reason, re-using a previously loaded UIWebView doesn’t seem as simple as it sounds…

What do you want me to take a look at? I think you probably meant to link somewhere?

Oh, yes I meant to link to this question. Thank you so much for sparing your time for me by the way. I really appreciate it. – never mind!! I solved it. I don’t think screen capturing is necessary if you use the events before transitions carefully. I will let you know when things are finalized!

Good to hear! Looking forward to hearing about your experiences. I suspect you might encounter a need for taking a screen shot before the transition after all, if you want to support things like the interactive pop gesture for example.

Making these types of hybrid apps easier to develop is definitely something on my mind. I hope to find the time to do some work on this in the future.

Hey @martijnwalraven this is the current status!

  1. on Simulator: https://youtu.be/OGR-gvSzeQw
  2. on iPhone6: https://youtu.be/A7EY0K0Nng0

You will notice on a simulator, the app is perfect. Users would believe it’s a native app. However, on a device, there’s unwanted 100ms delay between transitions. This is the last block that I must solve, and I thought you would have insight on this one too!

I followed your advice of doing transitions. I recycle a webView and in between transitions I execute either Router.go() through javascript or webView goBack() natively. In the above case, where you navigate from a detailedView to indexView, I do

- (void)willMoveToParentViewController:(UIViewController *)parent{
    if (parent == nil){
        [_webViewManager.webView goBack];
    }
}

The issue might be resolved if I could invoke goBack a little faster. But I am not sure where the real cause for that extra 100ms lies.

If you look at those movies frame by frame, there are actually some problems both on the simulator and on the device, they are just more pronounced on the latter. The main difficulty is in coordinating the route change in the web view with the transition. In the ‘imperfect’ movie, on the first transition, you can see the web view changing to the new screen before the transition starts (although without the data loaded). The second transition completes first with the old screen and then suddenly switches to the new one.

Replacing the web view in the source view controller with a screen capture would help replacing the screen too soon. It would also improve the user experience of the transition. If you think about it, what makes a transition work is that you have both the source and target view visible at some point, and only displaying the shared web view will never allow that.

The second problem is more difficult to solve, because you need to make sure the original page is never shown in the target view controller. You could wait until the route change and resulting load have completed, but that would delay the start of the transition and that might not give a very nice user experience. Alternatively, you could start the transition without the web view in the target view controller, but with a progress spinner for instance. And you then replace it with the web view when the new page load has been completed.

I realize this is all getting quite complicated, and although I admire the experiment, I know from experience how much work this can be. You want to make sure you don’t get sidetracked too much and leave enough time to actually build your app! So depending on the type of app you might be better off with a slightly less nice web-based solution, especially if you also require Android support. I really hope supporting these more hybrid approaches can be made easier, but that might be a while.

1 Like

Thank you so much again. The app is actually built already but without these natural transitions the app doesn’t seem complete to the users. It is getting complicated but we don’t have a choice… What do you mean by slightly less nice web-based solution?

I don’t understand how Amazon and Instagram handle transitions so beautifully in their mobile apps…

What I meant by that was doing without native transitions, but trying to optimize what you had before using a pure web-based approach. Many developers seem happy with sticking to web technologies and manage to achieve impressive results. I don’t think it will get you all the way to a native user experience, but especially if you use an existing UI framework the difference in time investment might be worth it.

I’m not sure how many hybrid apps implement all their navigation using web technologies. From the screen shot in this article for instance, I would say Instagram combines native navigation elements with a web view for its timeline.

1 Like

Ah I see. Thank you so much. I am going to give it a few more trys. What do you think of the following way?
Before transitioning to PostsShowVC create another webView inside PostsListVC and load the same url /posts, and move the initial webView to PostsShowVC. When I transition back to PostsListVC, I destroy the webView that was used inside PostsShowVC and show the user the one I created before. Do you think this approach works?

I think using webViews gets tricky because it only starts loading in viewDidLoad and there aren’t that many ways to prefetch data.

I’m not sure how that would help, but maybe I’m misunderstanding. The best approach still seems to be to replace the web view with a screen shot in the source view controller, which shouldn’t be too hard. Just make sure you take the screen shot first and only transition to the new page after.

1 Like

@woniesong: I am working on the very same thing (building a Meteor Cordova app with native iOS extensions), as described here:

I haven’t read through this whole thread yet, but regarding the re-usage of the web view, I’ve described how I did this in the thread linked above. I would be interested in sharing experiences on this, as this is indeed quite challenging.

At the moment, I am trying to find a solution to send messages from the web view to my native code, as described here:

How did you solve this?

PS: On the native side, I am focusing on iOS only, since I am a single developer with limited time. For Android, I plan to use standard Cordova, and accept that it might not run that smooth as on iOS.

iOS and webview can communicate with each other rather easily: http://stackoverflow.com/questions/9473582/ios-javascript-bridge. Wrapping Meteor app with native ios code is definitely better, and for Android it’s almost unavoidable, in my experience.

Thanks for the link to the stackoverflow page.

Regarding Android: why exactly do you think native code is inevitable there? At least on my fairly new devices (Nexus 7, HTC One), everything runs smoother than on my iPad 3 actually. Just for instance, whereas the iPad takes ages to react to a hot code reload, on the Nexus 7 it is much faster. And while HCR tends to break the whole app beyond restoration on the iPad, this never happened to me on Android.

The only problem I had with Android so far is that my custom fonts are not loading if the app is run for the first time. Fonts only appear after a first Hot Code Reload, and I have absolutely no clue why this is the case.

@wonisong: I am wondering why you are passing the web view from one controller to the other programmatically. I am using container views, and this does the trick for me automatically. All you have to do is to embed the same web view into different containers using an embed segue. One of the advantages of this approach also is that you get a better feeling of your app’s structure in your storyboard.

And instead of using two different view controllers to maintain smooth transitions, I would try to apply the trick mentioned in the link @nilsdannemann posted: https://hansoftx.com/blog/building-an-ultra-responsive-ui These guys just render two templates at the same time (i.e. in the same layout template) and switch between those templates using CSS visibility. That’s a really clever idea, as this switch nearly happens instantly. Of course there’s the drawback of having a quite long page, but if you combine this with infinite scroll techniques like these guys did, the overall experience should still be good.

Thank you for sharing your experience! It’s good to know someone else is trying to do the same thing that I am trying. In my experience, iPhone was in a usable state even without the native wrapper. Pure Meteor + Meteoric approach worked pretty well with the introduction of WKWebView. However, when we tried Android, we saw the result above (https://youtu.be/u0ebeev2fcE). Android phones use different webviews based on the device, and I heard Samsung Galaxy tends to have poor webview performance. Crosswalk is supposed to be the solution for this problem, but in our case, it made the performance worse.

We resorted to wrapping our Meteor app with a native container. The transitions and scrolling behavior seem to be much better. I just looked at your link (https://hansoftx.com/blog/building-an-ultra-responsive-ui) and I don’t understand how they managed to not load when they go back from a postShow view to postIndex view. How come they don’t have to load their data again? In other words, how come they don’t have to wait for the subscriptions to get ready?

@martijnwalraven your idea of taking a screenshot worked perfectly.