I've made a fresh mac app project with the following code in the ViewController.
import Cocoa
import WebKit
class ViewController: NSViewController {
var loginWebView: WKWebView!
override func viewDidLoad()
{
super.viewDidLoad()
self.loginWebView = WKWebView(frame: self.view.frame)
self.view.addSubview(loginWebView)
let urlReq = URLRequest(url: URL(string: "https://apple.com/")!)
self.loginWebView.load(urlReq)
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
For some reason when I launch the app the web view isn't loading the website. Why is this? I've been developing on iOS for years and am just getting started with macOS.
EDIT: Update loading a local file wouldn't work either
self.loginWebView.loadFileURL(fileURL, allowingReadAccessTo: dirURL)
The problem was that I had not enabled Incoming and Outgoing Connections in my app's sandboxing settings. I discovered this by reverting to using the legacy WebView and then getting an error code in the console. WKWebKit will not print error messages making something really simple incredibly difficult and confusing!. Apple really needs to fix that
Related
I tried to create a simple Complex Number Calculator using classes. My application has compiled successfully, but when I ran it, a blank window appeared instead of a window with all my buttons, labels etc. and I got this message in the output window:
2016-03-08 22:20:42.499 Complex Numbers[30404:2328250] Failed to set
(contentViewController) user defined inspected property on (NSWindow):
Cannot create BOOL from object <_NSControllerObjectProxy:
0x6000000022c0> of class _NSControllerObjectProxy
This is my ViewController class code. It involves a complexNumber class, which I didn't submit here:
class ViewController: NSViewController {
#IBOutlet var Screen: NSView!
var a = complexNumber();
#IBOutlet var realValue: NSTextField!
#IBOutlet var imaginaryValue: NSTextField!
#IBOutlet var resultLabel: NSTextField!
#IBAction func lengthResult(sender: AnyObject) {
let r = NSString(string: realValue.stringValue).doubleValue;
let i = NSString(string: imaginaryValue.stringValue).doubleValue;
a = complexNumber(real: r, imaginary: i);
resultLabel.stringValue = String(a.trigonometric());
}
#IBAction func trigonometryResult(sender: AnyObject) {
let r = NSString(string: realValue.stringValue).doubleValue;
let i = NSString(string: imaginaryValue.stringValue).doubleValue;
a = complexNumber(real: r, imaginary: i);
resultLabel.stringValue = String(a.length());
}
#IBAction func operation(sender: AnyObject) {
a = complexNumber(real: NSString(string: realValue.stringValue).doubleValue, imaginary: NSString(string: imaginaryValue.stringValue).doubleValue);
realValue.stringValue = ""
imaginaryValue.stringValue = "";
let b = complexNumber(real: NSString(string: realValue.stringValue).doubleValue, imaginary: NSString(string: imaginaryValue.stringValue).doubleValue)
switch sender.stringValue {
case "+": a = a.sum(b)
case "-": a = a.dif(b)
case "x": a = a.mul(b)
case ":": a = a.div(b)
default: a = a.sum(complexNumber())
}
}
#IBAction func displayResult(sender: AnyObject) {
resultLabel.stringValue = String("\(a.real) + i*\(a.imaginary)");
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}
I found a similar thread here, but I don't think it's what I was looking for.
Can you help me, please?
Another reason - when you setup wrong binding.
Example of my error:
Failed to set (contentViewController) user defined inspected property on (NSWindow): [<NSProgressIndicator 0x10111b890> valueForUndefinedKey:]: this class is not key value coding-compliant for the key Enabled.
To solve this you need to delete the binding here:
For me was a timing issue I guess. All begins after I added an SFAuthorizationView some days ago, and I discovered that thanks to a bug report, where also was clear that this is happening on older OSes like Sierra, but it is fine, instead, in 10.13+.
Moving some code from viewDidLoad() to viewDidAppear() the problem gone.
Basically I'm just waiting to call any related method of the problematic view later the viewcontroller content view is declared as loaded. Clearly a an Apple problem fixed in new OSes. So after instantiate the nib/xib/storyboard involved I think anyone encounter problems like that should firstly show the view and then customise it. Just my testimony.
I had this problem and figured it out.
In my view I had a user defined property (if you look at the top of your view where you have view controller and first responder you should see it's icon next to it).
Simply delete it and run your application.
Hope this helps!
I you've created an app with a"storyboard" i.e. if there's a storyboard file with your views and windows in it, then there's one of two things missing:
1) If theres a main window and a view that should be it's main view, then right click - drag from the window controller to the view that should be the main view.. When the popup happens, click on "content view" i.e. like follows:
Check out my video example
If this fails, then I'll dig out plan two :)
How this helps!!
Ade.
One thing that may help others, I saw the same message, it looked like the contentViewController was the problem, but it turned out it was another component in something I was writing was failing. It seems the window manager catches all exceptions, not just window exceptions, and prints this deceptive message. What worked for me is stepping through to find component is not loading.
This happens when there is an error or exception in ViewDidLoad.
Ensure that error is cleared and your UI will load fine and u wont get this message.
PROBLEM: Getting a Thread 1: EXC_BAD_ACCESS (code=1, address=0x18) when setting the previewItem of a QLPreviewView object laid out in a window.
GOAL: Create an app with a preview of file contents and controls below for changing properties of the file being previewed. The preview must be tied to the size of the window and react to resizing of the window.
SETUP:
Using Xcode 6.1.1 I created a default OS X Cocoa Application using Swift, and Storyboards.
Using Storyboards for layout, there doesn't appear to be a QLPreviewView component in the Object Library, so I used a Custom View object and set the Class to QLPreviewView. I then set the constraints to allow the preview view to resize with the window frame.
I then linked the Custom View of class QLPreviewView into the ViewController.swift file as a member variable. In the viewDidLoad() method I added a set the previewItem of the QLPreviewView object to an implementation of the QLPreviewItem protocol. I also added an import Quartz.
Here is the source for ViewController.swift, as generated by Xcode, then modified by me to add the setup for QLPreviewView.
//
// ViewController.swift
// PreviewTest
//
// Created by Derek on 2015-03-02.
// Copyright (c) 2015 Derek. All rights reserved.
//
import Cocoa
import Quartz
class ViewController: NSViewController {
#IBOutlet var preview: QLPreviewView!
override func viewDidLoad() {
super.viewDidLoad()
preview.previewItem = {final class PreviewItem : NSObject, QLPreviewItem {
var previewItemURL: NSURL! {return NSURL(fileURLWithPath: "/Users/derek/Pictures/Scan.jpeg")}
var previewItemTitle: String! {return "Test" }
}
return PreviewItem()
} ()
// Do any additional setup after loading the view.
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}
The line where preview.previewItem is set gets the EXC_BAD_ACCESS error described at the top when the application is run.
I have successfully created a QLPreviewView and embedded it in a window, however I did it without using the storyboards or constraints, so it's size and position is not managed by the window, which is what I want.
The inline class PreviewItem works fine. I have tried switching it to a standalone class and then created it to a variable, then set QLPreviewView.previewItem to the variable. This fails in the same way as the set to previewItem doing it inline.
The inline class PreviewItem also works fine in the non storyboard case and the file scan.jpeg is shown as expected.
Other UI objects, like Text Field work fine when I set them up in a similar way.
I'm hoping to find out what I'm doing wrong here and how to correct it. Or suggestions on how to approach this goal in a different way.
Try defining PreviewItem as a nested class instead of the inline definition. JavaScript might define and invoke it with () like your program, but I think in Swift the nested class is more general.
class ViewController: NSViewController {
private final class PreviewItem : NSObject, QLPreviewItem {
var previewItemURL: NSURL! {return NSURL(fileURLWithPath: "/Users/derek/Pictures/Scan.jpeg")}
var previewItemTitle: String! {return "Test" }
}
#IBOutlet var preview: QLPreviewView!
override func viewDidLoad() {
super.viewDidLoad()
preview.previewItem = PreviewItem()
self.view.addSubview(preview)
// Do any additional setup after loading the view.
}
...
}
Also make sure the preview property is connected to the view by Interface Builder.
I've recently started working on some test projects to get the feel for OS X development with Xcode. I come from Windows, so I might not be making much sense here.
How would I subscribe to certain "events" in Swift? I have just learned how to connect actions to UI objects. For example, I can now click a button, and change the text of a label programatically. However, and this may just be a case of lack of knowledge on my part - I am not able to find a way to subscribe to a TextField's "Text Changed" event.
Let's say that I have a TextField, and when I change the text at runtime (i.e. type something), I want to do something in the textChanged event for that particular TextField.
Is there even such a thing as a TextChanged event in OS X development?
Update
I am now using the following code:
import Cocoa
class ViewController: NSViewController {
class textField:NSTextField, NSTextFieldDelegate
{
override func awakeFromNib() {
delegate = self;
}
override func controlTextDidChange(obj: NSNotification)
{
println("Text changed.")
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}
And I have added a ClassName to the TextField control in the Identity Inspector, but it isn't responding to the text changing. The message given is:
Failed to connect (textField) outlet from
(Xcode_Action_Basics.ViewController) to (NSTextField): missing setter
or instance variable
I just googled that error and came across this page: Failed to connect (storyboard) outlet from (NSApplication) to (NSNibExternalObjectPlaceholder) error in Cocoa and storyboard which states that this is a known issue in Xcode and that it does not mean there is a problem with your code - but I'm not so sure about that, because the code isn't working. Not sure if I've missed out on something.
Create a class that implements the protocol NSTextFieldDelegate like
class MyTextField:NSTextField, NSTextFieldDelegate {
override func awakeFromNib() {
delegate = self // tell that we care for ourselfs
}
override func controlTextDidChange(obj: NSNotification) {
// .... handle change, there are a lot of other similar methods. See help
}
}
In IB assign this class here:
I'm trying to add a new sub view form a nib using swift for OS X.
So far i've:
created a new "Cocoa Application"
added a new "Cocoa Class" called "TestSubView" as a subclass of NSViewController with a XIB file
I want to add this subview to my main view when the application loads.
in my ViewController ( the ViewController for the main window ) i have.
import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
let newSubView = TestSubView();
self.view.addSubview(newSubView.view);
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}
But i'm getting the following error
Failed to set (contentViewController) user defined inspected property on (NSWindow):
-[NSNib initWithNibNamed:bundle:] could not load the nibName: temp.TestSubView in bundle (null).
I realise i will need to size and position this subview but I can't seem to get to that point.
I've spent the better part of a day trying to figure this one out so any help would be greatly appreciated.
I finally got this thing to work. My new code looks like
import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
let subview = TestSubView(nibName: "TestSubView", bundle: nil)!
self.view.addSubview(subview.view)
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}
Found with the help of the docs & this answer
It was suggested that if the nib name and the class name are the same you shouldn't need to declare nibname: (as i'd tried to do originally) but the docs didn't mention this - explains why it didn't work!
For prosperity, this worked for me with Xcode 6.1.1 on OS X Yosemite (10.10.1)
A nib is really nothing but an XML file with view information in it. You have to get it from the application bundle and get one of the views contained in it explicitly. You are perhaps confounding views and view controllers (your attempt to extract view from newSubView suggests that).
Try this:
let subview = NSBundle.mainBundle().loadNibNamed("TestSubView",
owner:self, options:nil)![0]! // maybe no final unwrapping "!" in Swift 3
self.view.addSubview(subview)
Make sure the xib is really called the name you are using and contains at a least one view (otherwise the two unwrapping ! above will crash your app).
Cache manifest works fine and events fired in safari in IOS 8. Not working at all in WKWebView anyone else solve this issue?
import UIKit
import WebKit
class ViewController: UIViewController {
#IBOutlet var containterView : UIView! = nil
var webView : WKWebView?
override func loadView(){
super.loadView()
self.webView = WKWebView()
self.view = self.webView!
}
override func viewDidLoad() {
super.viewDidLoad()
var url = NSURL(string:"http://html5demos.com/offlineapp")
var req = NSURLRequest(URL:url)
self.webView!.loadRequest(req)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
The application cache comes back as supported if I were to use html5test.com
EDIT:
window.applicationCache does not return undefined either when loaded from WKWebView
console.log("Initializing Page");
if (window.applicationCache == undefined){
console.log("Application cache not suported!");
updateSplash();
}
console.log(window.applicationCache); returns: DOMApplicationCache
EDIT 2:
if (typeof window.applicationCache.update === 'function'){
console.log("Application has method update");
console.log(window.applicationCache.update); //shows swapCache() and update() methods
window.applicationCache.update();
}
window.applicationCAche.update() throws Error: InvalidStateError: DOM Exception 11: An attempt was made to use an object that is not, or is no longer, usable.
Just for the record, this question appears to have been asked on and linked from the Apple Developer Forums. The official response from Apple is that the HTML5 Application Cache functionality is not available in WKWebView:
The offline application cache is not enabled in WKWebView. Feel free to request that it be made available via https://bugreport.apple.com.
I think you are trying to solve the same problem as I do. This is what I do.
Save the start page of your web app into one HTML file(index.html), embedding everything (CSS, JS, images as base 64, icon fonts). And add that file into your Xcode project.
Start the app by reading the content of the HTML file and load it in your WKWebView. You can set the base as the same url you are supposed to start with. This way, it'll be as if the web app is opened on your web site.
The benefit is that your app will always start even when the user's network isn't good. Here's the SWIFT code that I use, courtesy of Matt Neuberg (https://books.google.com/books?id=wLaVBQAAQBAJ&pg=PT669&lpg=PT669&dq=addConstraints+wkwebview&source=bl&ots=7trE7MR1zR&sig=VT6GDBGbDw9dh89wDb5Uajd4gUY&hl=en&sa=X&ei=cyyeVNH4MM3ToATukoDgAQ&ved=0CDkQ6AEwBA#v=onepage&q=addConstraints%20wkwebview&f=false). If you want the full source code, please let me know and I'll post it on Github.
let templatepath = NSBundle.mainBundle().pathForResource("index", ofType: "html")!
let base = NSURL(string:"http://m.ftchinese.com/iphone-2014.html#iOSShare")
var s = NSString(contentsOfFile:templatepath, encoding:NSUTF8StringEncoding, error:nil)!
self.webView!.loadHTMLString(s, baseURL:base)