Swift: Build succeeds, a blank app window and this message appear: Failed to set (contentViewController) user defined inspected property on (NSWindow) - xcode

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.

Related

NSCollectionView memory leak in High Sierra?

I have noticed a memory leak in NSCollectionView through Instruments. When I track down to the code, it shows the specific line below:
collectionView.makeItem(withIdentifier: identifier, for: indexPath) as? DisplayableCellProtocol
Then I looked it in Xcode, memory debugger, and find out there are some non-referenced items that caused the leak. However, not all items created by makeItem is leaking, some of them are normal, but some are not even shown.
Managed normal unleaked item is like this graph
And the leaked ones are like this (without any connections):
Is that normal, does anyone else has the same problem? Does anyone know how to correctly solve this problem? Does this have anything to do with using xib to design the items views?
Here are some code that may be helpful to understand the situation:
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
let data = datasource[indexPath.item]
let identifier: String = "ServiceCell"
// Next line is where the leak occurs
guard let cell = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: identifier), for: indexPath) as? ServiceCell else {
return ServiceCell(nibName: NSNib.Name("ServiceCell.xib"), bundle: Bundle.main)
}
cell.iconView.image = data.icon
cell.serviceLabel.stringValue = data.name
cell.introLabel.stringValue = data.content
cell.highlighted = false
return cell
}
The definition of ServiceCell is:
class ServiceCell: NSCollectionViewItem {
#IBOutlet weak var iconView: NSImageView!
#IBOutlet weak var serviceLabel: NSTextField!
#IBOutlet weak var cmdLabel: NSTextField!
#IBOutlet weak var introLabel: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
}
}
Not sure if the code is helpful here. I have tried to find if there is any bug in my own code, but have not found any yet.
Meanwhile, I found a lot of other leaks, and most of them points to the makeItem line
Update: I have looked through it again. So every time it will double the number of items that is actually needed. For example, I need 2 cells, it will create 4 instead of 2, and two of them is the leaked ones. Any ideas?
This is finally solved. When creating a class inherited from NSCollectionViewItem with creating an xib file, the class of the File Owner in the xib is set to the subclass created before by default. When we add a custom object in the xib, this needs to be set empty.
I assume you're seeing this issue if your delegate and dataSource are (weakly?) set to the NSCollectionView itself. I had this slightly questionable setup on MacOSX 10.14.6.
With the delegates so-wired in, I questionably "solved" this by introducing empty stubs for willDisplayItem and didEndDisplayingItem. With that, the memory leaks went away.
My collection view content was 48 items; without these stubs, the first return from itemForRepresentedObjectAtIndexPath (which called makeItemWithIdentifier) beach-balled my app with memory usage shooting through the roof.
I'm in the process now of relocating this collection view into an NSViewController to avoid these shenanigans.

How can I go from First ViewController to Second ViewController, get values and go back to First

I just spent couple of days for trying to figure this out for mac app, but not doing it successfully.
I have first ViewController and second ViewController. Let's say, ViewControllerA(VC-A) and ViewControllerB(VC-B). In Main.storyboard, they are connected by segue with identifier "PromptToUser".
VC-B gets triggered not by button, but if condition during the process.
It is triggered by:
performSegue(withIdentifier: "PromptToUser", sender: self)
in VC-A.
In VC-A, I put the followings so far:
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
}
In VC-B, so far, I have:
#IBOutlet weak var Login: NSTextField!
#IBOutlet weak var Pass: NSSecureTextField!
VC-B also has a button which I want to make as a trigger to collect information entered by user for above variables and send it back to first view.
I found many similar topics on this in stackoverflow. However, it seems most of them are for iOS, but not for mac app as I could not make UI... and other classes (delegates) and protocols they mentioned to be recognized for Swift 3 environment. I have NSViewController, and NS... not UI...
What would be the best way to approach this for mac app with Swift 3?
You Can make a static variable in VC-A and just update the value of static variable from VC-B. Example
In VC-A
static var login = ""
static var password = ""
In VC-B
VC-A.login = nameTextField.text
VC-A.password = passTextField.text
Write the code in SaveButton Action of VC-B, and you will get the update value in VC-A.
If You are not using any Save Button in VC-B, then You can write code in viewWillDisappear Method of VC-B
override func viewDidDisappear(_ animated: Bool) {
firstVC_A.login = nameTextField.text
firstVC_A.password = passTextField.text
}

How can I disable a button until text in all UITextFields has been entered in swift?

I need a way to disable the save button until text has been entered in all of the required text boxes? I am developing the application in Swift and I have found lots of answers in Objective-c. As I have absolutely now Objective-c knowledge, I am unable to work out what it means.
Does anybody have a solution for this which can be done in Swift?
I know how to enable/disable a button. I also know how to check if a text field is empty. I'm just not sure how to make it so that my code is always checking to see if it is empty or not. I have tried a while loop but as I expected, this froze everything.
Listing one of the ways to achieve this:
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var button: UIButton!
//Need to have the ViewController extend UITextFieldDelegate for using this feature
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// Find out what the text field will be after adding the current edit
let text = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
if !text.isEmpty{//Checking if the input field is not empty
button.userInteractionEnabled = true //Enabling the button
} else {
button.userInteractionEnabled = false //Disabling the button
}
// Return true so the text field will be changed
return true
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//Setting the Delegate for the TextField
textField.delegate = self
//Default checking and disabling of the Button
if textField.text.isEmpty{
button.userInteractionEnabled = false // Disabling the button
}
}
}
Reference Link for the above solution
Despite of all the comments given so far and to not blow up the comment area further, I try to give some hints on how to solve your problem:
Put all the textfields in an outlet collection
Set the delegate of all textfields to your viewController
implement the delegate's didEndEditing method and within that method iterate over the outlet collection to check each textfield for its input
Note that this is only ONE way to implement that but you might get the idea.
Use the textfield's delegate methods (or the target-action pattern) to check the conditions required for the user to proceed. If they're met, enable the button.

OS X addsubview from xib in swift

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).

webViewDidFinishLoad not firing called working

(Swift, iOS8, Xcode6, iPhone/iPad)
webViewDidFinishLoad is not being called, is not firing, and is not working.
Yes, I have set the containing view controller as the delegate. I CTRL-mousedowned on the UIWebView, dragged up to the little yellow circle representing the view controller, and released. A right-click on the UIWebView object shows that the delegate is set.
Yes, I did implement UIWebViewDelegate in my class declaration, like so:
class Paragraph: UIViewController, UIWebViewDelegate {
Yes, I did restart Xcode, and test on both the simulator and an actual iPhone 4S.
The request looks like this:
#IBOutlet var paragraph : UIWebView = nil
var r = NSBundle.mainBundle().pathForResource("cheddar", ofType: "htm")
var u = NSURL(fileURLWithPath: r)
paragraph.loadRequest(NSURLRequest(URL: u))
The callback function looks like this:
func webViewDidFinishLoad() {
println("webViewDidFinishLoad")
}
I got it. The callback was missing a parameter. For posterity:
func webViewDidFinishLoad(webView: UIWebView!) {
Note the webView: UIWebView! parameter
In this case, perhaps even more important, is the way I found the bug. I created an entirely new view controller, and pieced it back together, carefully checking at each step to make sure that I didn't miss anything.
When the Intellisense popup showed the function with the parameter, I saw my error.
NOTE: In Swift 2.2, the UIWebViewDelegate protocol specifies a different optionality:
webView: UIWebView.
webView: UIWebView! spawns a warning.

Resources