Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IBOutlets in Swift are nil

(Developing on OSX 10.9, Xcode 6.1b)

If I declare IBOutlets in my AppController, everything is fine. I instantiate an object in InterfaceBuilder, drag it across to form an outlet, and by the time I have reached applicationDidFinishLaunching, my IBOutlets are populated and everything is great.

If I go a step further in abstraction and instantiate a custom controller object in InterfaceBuilder (a subclass of NSObject), and declare one of my objects as an IBOutlet in that class, they're nil, each and every one.

I can set the connection just fine, IB seems convinced it exists, the 'referenced outlets' list is correct, but it doesn't take, and I haven't been able to find anything in the documentation beyond

It is implicitly unwrapped because after your class is initialized from a storyboard or xib file, you can assume that the outlet has been connected.

Well, I was assuming that.

All of my code is boilerplate Xcode offerings:

@IBOutlet weak var sceneController: NSArrayController!

and I've checked and double-checked and triple-checked the connections. I've looked at dozens of iOS tutorials (although I cannot find the equivalent for OSX) all of which seems to be variations on the theme of 'yes, you can totally declare an outlet in a file other than the AppController, just make sure that every involved instance exists'.

(At the time of writing, the 'mac' documentation uses examples featuring UIButton etc.)

I'm out of ideas. It's obvious that the connection is not formed, presumably because the objects are instantiated in an order other than 'controller class first, IBOutlets later', but how can I force this connection?

like image 291
green_knight Avatar asked Sep 19 '14 17:09

green_knight


People also ask

What are IBOutlets in Swift?

In the case of @IBOutlet , this is a connection from an Interface Builder user interface component – e.g. a UIButton – to a property in a view controller or other piece of Swift code.

Should IBOutlets be weak Swift?

The official answer from Apple is that IBOutlets should be strong. The only case when an IBOutlet should be weak is to avoid a retain cycle. A strong reference cycle can result in memory leaks and app crashes.

What is IBOutlets?

An IBOutlet helps connect the object control to the code to make the object accessible via the program. IBOutlet makes the connection between the declared instance variables wit the elements in the prototype cell. It typically holds these other objects as properties backed by instance variables.

Why outlets are weak in Swift?

Outlets that you create will therefore typically be weak by default, because: Outlets that you create to, for example, subviews of a view controller's view or a window controller's window, are arbitrary references between objects that do not imply ownership.


1 Answers

@IBOutlet weak var sceneController: NSArrayController!

The weak keyword is your problem. If, after the system finishes decoding your nib, nothing else references the NSArrayController, then the system will immediately set the outlet to nil and deallocate the NSArrayController.

Try removing the weak keyword from your outlets.

UPDATE

Add this code:

@IBOutlet var sceneController: NSArrayController! {
    didSet {
        NSLog("sceneController set to %@", sceneController);
    }
}

What's the output? Put a breakpoint on the NSLog. What's the stack trace when it's hit? Is it hit repeatedly?

like image 80
rob mayoff Avatar answered Oct 03 '22 03:10

rob mayoff