offline application cache support in mac os x embedded webkit webview - swift

I am writing OS X HTML5 app which has to function both online and offline. Offline application cache was prototyped based on this and works well in Safari. When i do a simple test using webview in Xcode, the manifest file seems never to be fetched by the webview. A simple way to test uses this minimal html file:
<html manifest="example.manifest"><head> <title>Test with
manifest</title> </head> <body> Test with manifest<br> <br>
</body></html>
the manifest file example.manifest contains:
CACHE MANIFEST
# ver 1
CACHE:
When i view this page in Safari, the page loads, and the manifest is read. If i quit safari, go offline, then start Safari and refresh this page, it loads from cache. the offline cache here seems to work fine.
when i repeat this with web view, in Xcode 7.3 Mac OS 10.11, using the following code (storyboard has a web view in a view controller inside of the window):
class ViewController: NSViewController {
#IBOutlet var webview: WebView!
let THEURL:String = "http://192.168.23.180/WithManifest/"
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL(string: THEURL)
let request = NSURLRequest(URL: url!, cachePolicy:NSURLRequestCachePolicy.UseProtocolCachePolicy ,timeoutInterval: 10)
webview.mainFrame.loadRequest(request)
}
}
In the web view case, the page loads fine, but after quitting and restarting offline, the page fails to load. looking at the network traffic, it is clear that the manifest file is never requested from the client. I have tried all of the different cache policies without success. I have also tried creating my own shared URL cache as has been suggested elsewhere with no success.
let cacheSizeMemory:Int = 4*1024*1024; // 4MB
let cacheSizeDisk:Int = 32*1024*1024; // 32MB
let sharedCache:NSURLCache = NSURLCache(memoryCapacity:cacheSizeMemory, diskCapacity:cacheSizeDisk, diskPath:"nsurlcache")
NSURLCache.setSharedURLCache(sharedCache)
My questions:
1) does webkit webview in OS X support offline application cache as described in html5?
2) if yes, what has to be done to make it work?
My workaround is to implement a subclass of NSURLProtocol that implements custom caching and doing the loading logic (offline vs. online) in the app. I would much rather use the standard approach if at all possible.

I was able, with help from different places and people, to find an answer. There is an Objective-C webview preference called setOfflineWebApplicationCacheEnabled, which is for some reason not exposed in swift. To make it work, first make a bridging header file. Use Xcode to create a header file and put this into it:
#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
#interface WebPreferences (WebPreferencesPrivate)
- (void)_setLocalStorageDatabasePath:(NSString *)path;
- (void) setLocalStorageEnabled: (BOOL) localStorageEnabled;
- (void) setOfflineWebApplicationCacheEnabled:(BOOL)offlineWebApplicationCacheEnabled;
- (void) setDatabasesEnabled:(BOOL)databasesEnabled;
#end
and save it in your project. Go to Build Settings->Swift Compiler - Code Generation and select 'Objective C Bridging Header'. double click on the right side and put in the relative path (based on the file system, not the project organization) to the header file. In my case it was testwebviewmanifest/Header.h, where testwebviewmanifest folder is at the same level as the .xcodeproj file.
Once that is done and you can build successfully (it may complain it can't find your header file if the path is wrong), put this line at a startup place where you have a handle to your webview. For me it was easy to put it in the ViewController.
webview.preferences.setOfflineWebApplicationCacheEnabled(true)
Once that is done, the cache manifest will be downloaded, and application caching appears to work flawlessly. Extensive testing has not been done yet. I will update if any gotchas are found...
A demo project can be found here: https://github.com/graySquirrel/testwebviewmanifest

Related

"Your browser doesn't support full screen" - WKWebview, macOS

I am currently developing a cocoa web browser application like google chrome. I was testing it until I came across the problem that the wkwebview doesn't support full screen on videos. When I open a video, I get this message...
I thought I had to make the wkwebview a subview of the view, using this code
view.addSubview(webView)
I tried it and it still show the image above.
Can you please assist me on supporting full screen.
Open your project.
Right click on prject app grade folder from sidebar and click new file.
in choose a template click objective-C file.
name it for example WKPreferences and enter.
Now next window press create.
On next create Bridging-Header.
Now you can see two new files in your sidebar.
Paste following code in WKPreferences.m
#import <Foundation/Foundation.h>
Paste following code in Bridge-Bridging-Header.h
#import <WebKit/WebKit.h>
#interface WKPreferences ()
-(void)_setFullScreenEnabled:(BOOL)fullScreenEnabled;
#end
Now Paste following code in viewcontroller.swift
webView.configuration.preferences._setFullScreenEnabled(true)
Thats it.
You should be able to just put the following in the Swift-File where the WebView is created:
webView.configuration.preferences.setValue(true, forKey: "fullScreenEnabled")

Take screenshot of host app using iOS share/action extensions?

I will like to know how to take a screenshot of the iOS host app with the use of a share/action extension.
My use case is as follows:
use the Safari browser to access a webpage (https such as gmail)
tap on the Share button and select the extension
the extension will take a screenshot of the current webpage
An working example for this use case is the Awesome Screenshot iOS app.
I had tried the following methods
reload the baseURI (loadRequest) on a UIWebView/WKWebkit (would not be able to access https contents such as Gmail). So not doing any reload (Awesome Screenshot is not doing a reload btw)
Used the ExtensionPreprocessingJS to obtain the DOM contents through the arguments.completionFunction function. I could not extract the document.body here although i could get the source etc. loadHTMLString with the baseURI will mess up the presentation layer.
Used html2canvas in the ExtensionPreprocessingJS to obtain an image and appended it to the host app's webpage as a child but do not know how to extract it. Also, the image got lost for some webpages such as Gmail.
Mobile Safari does not have the visibleContentsAsDataURL method.
I think a viable approach will be to use the html2canvas in the ExtensionPreprocessingJS but how do I save this image somehow?
Edit: So the below works in the Simulator but does not work on the device. I'm presently looking for a solution as well.
Here's a solution that I think the Awesome Screenshot app uses:
func captureScreen() -> UIImage
{
// Get the "screenshot" view.
let view = UIScreen.mainScreen().snapshotViewAfterScreenUpdates(false)
// Add the screenshot view as a subview of the ShareViewController's view.
self.view.addSubview(view);
// Now screenshot *this* view.
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, false, 0);
self.view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
let image: UIImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Finally, remove the subview.
view.removeFromSuperview()
return image
}

Adding iPad XIB to a View Based Application Template Application in XCode 4

I've created a View Based Application in XCode4; when creating the application I selected iPhone as the Device Family:
The application was created with the following files:
I designed the UI on the TestushViewController.xib file and without adding any code in the Delegate files, the application is uploading immediately to the TestushViewController.xib view and I'm very happy about it.
Now I want to add an iPad xib. How do I do that?
(I knew how to do it in XCode 3, but I used some code in the Delegate file, and now if I try to use the same code it doesn't work because the template default implementation works differently - Apple uses #class TestushViewController and self.window.rootViewController = self.viewController and it goes directly to the iPhone.xib. I don't know how to go around it without changing the entire thing to the way it was done in XCode3)
You'll need to structure your code in a similar way that the Window Template does. The file structure that template uses when the "Universal" option is ticked at creation is:
App Name/
AppNameAppDelegate
iPhone/
AppNameAppDelegate_iPhone
MainWindow_iPhone.xib
iPad/
AppNameAppDelegate_iPad
MainWindow_iPad.xib
The iPhone and iPad AppDelegates are simply subclasses of the AppNameAppDelegate
#interface YourAppNameAppDelegate_iPhone : YourAppNameAppDelegate {}
In your target summary you can set what .xib file is initially loaded for each device. It is called the "Main Interface" and has a pulldown menu.
Quite frankly, if you're wanting to do a universal app (iPhone + iPad) it's probably easier just to start with the Window Template and add in your view controllers instead of starting with the View template and trying to change it up.

PhoneGapHtml5_Problem

Just wanted to ask u how do we link HTML file in PhoneGap Applications.As u know that in when we create PhoneGap application one Html file comes with it i just want to know how it is linked to the application so that i could add more Html files to it and use it ib webview
Thanks all in advance
To use multiple pages you can just link to them as normal. (Remember, use relative links).
It's hower normal to use only 1 page in phonegap application. 1 page that uses hidden divs. Don't really know why, besides the fact symbian only supports 1 page with acces to the device.
Just place your HTML files and other resouces (like images, scripts, etc) inside the "www" folder :) as Erik said, just link them as yoiu normally do. You don't need to edit any Objective-C files (like .m or .h).
Good Luck
PhoneGapDelegate.m is where the phonegap settings are stored. The PhoneGapViewController.m is where the UIWebView is bound to the xib.
Please control click on any web view delegate method placed in App delegate method then in the new class which appears after contrl clicking make following changes...
(NSString*) wwwFolderName { return #"www"; }
(NSString*) startPage { return #"index.html"; }
In these 2 functions i.e wht html file u want to attach in your phone gap u can write the name in start page function as shown above.

No response after submitting form on iPad from UIWebView

I am currently opening a webpage in UIWebView and submitting a form which performs a query on the server side and youtube video is returned (if available). I have no say/control over the server side implementation.
This webview works fine on iPhone/iPod, however, when I try to run the same app on iPad there is no response after submitting the form.
I created a dummy app, compiled on iOS 3.2 and problem is still there.
I put NSLogs in webview delegate methods which shows that after the form is submitted (UIWebViewNavigationTypeFormSubmitted) nothing happens.
I'm unable to figure out why this happens only on iPad and not on iPhone/iPod Touch.
I have created the webview in IB and setting the URL is viewDidLoad
[viewTourWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.realestatetour.com/mobiletours.htm"]]];
The URL for reference is http://www.realestatetour.com/mobiletours.htm
Enter the Tour ID as 10.
Thanks
The reason it wasn't working is because the form opens the result in a new page, (i.e. _blank) and apparantly all links opening in new window are ignored by uiwebview and its delegates.
I found 2 possible solutions for this:
1) Modifying the html using javascript to replace all _blank with _self for all anchor tags.
(source)
2) A more elegant solution which works for handling links which open a new window.
(source)
In my case i recreated the web page displaying form on the iphone app and changed _blank to _self.