OSX Sandbox WKWebView Load Local File Inside - swift

I have a WKWebView tied to an NSOpenPanel. I let the user select a file, but I am having trouble loading the file. When the app was not sandboxed I didn't have any problems, but once I turned on sandboxing I couldn't get it to work on OSX < 10.11. On OSX 10.11 I can use webView.loadFileURL(url, allowingReadAccessToURL: url), but it isn't available on < 10.11. What is the best way to load files from NSOpenPanel in a sandboxed osx swift app? Thanks!

NSURL from your NSOpenPanel into NSData with initWithContentsOfURL
then get a NSString out of this NSData
then use
WKWebView loadHTMLString(_ string: String,
baseURL baseURL: NSURL?)

Related

(half solve)Why copy file reference to clipboard programmatically only working for system folder in MacOS?

Solution
add this code pasteboard.data(forType: .fileURL) after pasteboard.writeObjects(emptyArray), it will work.
But I don't know why?
System Verison: MacOS Ventura 13.0
copy.swift
#!/usr/bin/swift
import Cocoa
private func copyToClipBoard(path :String) {
let pasteboard = NSPasteboard.general
var emptyArray = [NSPasteboardWriting]()
emptyArray.append(NSURL(fileURLWithPath: path))
pasteboard.clearContents()
pasteboard.writeObjects(emptyArray)
}
copyToClipBoard(path: CommandLine.arguments[1])
If I run swift copy.swift /Users/USER/Downloads/FILE, paste to chat window for third-party applications is working.
If I run swift copy.swift /Users/USER/tmp/FILE, cannot paste to chat window for third-party applications, application occur no permission error, I already give full access disk to this application.
What's the difference between Downloads and tmp?
How can I make copy file reference programmatically working for any folder?

MusicSequenceFileLoad Works in Playgrounds but not in Project

what am i doing wrong?
i'm trying to open a midi file and read it's contents. so far i can open the file in playgrounds but i get "Open::fopen failed" in my project
override func viewDidLoad() {
super.viewDidLoad()
let path = NSURL.fileURL(withPath: "/users/me/file.mid")
var midfile: MusicSequence?
NewMusicSequence(&midfile)
MusicSequenceFileLoad(midfile!, path as CFURL, .midiType , .smf_ChannelsToTracks)
}
i do have import AudioToolbox and CoreMIDI
EDIT: some progress
I'm able to open midi files from bundle with CFBundleCopyResourceURL, but i want to be able to open files from anywhere in finder
fileManager also fails, it returns nil when used inside a project and works in playgrounds.
figured it out.
code fails because the app runs sandboxed and the NSURL can't be accessed

PDF file not shown in iPad webView

I have a Swift application that opens a PDF file in webView with the function webView.load(request).
It perfectly works at debug time with the simulator, but when launched in the real device (an iPad) the PDF file is not shown.
The app does not set any error.
Any help is welcome
This might be so obvious question: Is your iPad connected to internet?
Then maybe it's because your link isn't and "https://...." but just an "http://" and maybe the webview won't open it because of that
The PDF file is located in the default documents folder.
Any loading to the webView is working, but not the loading of a PDF file.
The strange is that the same code works in the simulator.
For Swift 3 use this
let url = URL(fileURLWithPath: filePath)
let urlRequest = URLRequest(url: url)
webView?.loadRequest(urlRequest)

offline application cache support in mac os x embedded webkit webview

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

How to open bluetooth settings screen

I am using this code to open Bluetooth screen settings:
NSURL *url = [NSURL URLWithString:#"prefs:root=General&path=Bluetooth"];
[[UIApplication sharedApplication] openURL: url];
But it's not working, I am using iOS 6.0 SDK
I believe opening the settings app is deprecated in iOS 5.1.
Seems like all programmatic ways are either through urls (only works on 5.0 exactly), or directly modifying settings (non-public api).
However, it must also be possible somehow on 5.1+, as for example the "Runtastic"-App does exactly this (shows dialog that asks if you want to open bluetooth settings) when you start it.
Swift 3.0 & iOS 10 and above
func openBluetoothSettings(){
let urlBTSet = URL(string: "App-Prefs:root=Bluetooth")
let objApp = UIApplication.shared
objApp.openURL(urlBTSet!)
}
Objective-c
-(void) openBluetoothSettings{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"App-Prefs:root=Bluetooth"]];
}
So, In above code what they have changed is string need to add "App-Prefs:root=Bluetooth" (This the example of opening bluetooth settings)
Don't forgot : 'Goto taget -> info -> URL Types -> Add "prefs" in URL Schemes'
It's question for iOS 6.0 but for iOS 8/9 here is the answer,
Go to your XCode project, under Info -> URL Types section -> "prefs" in URL Scheme
In IOS9: let url = NSURL(string: "prefs:root=Bluetooth")!
IOS8: let url = NSURL(string: "prefs:root=General&path=Bluetooth")!