How to do Cocoa bindings in Swift? IB rejects optionals


(Jean-Denis Muys) #1

Hi,

I am exploring the use of Swift for a Mac Cocoa application - using Xcode 8.2.1, and it seems I hit a roadblock regarding Cocoa bindings.

In this toy Core Data document-based project, I added an NSArrayController in the StoryBoard. I need to bind it a NSManagedObjectContext so that my user interface works by itself. I followed the solution outlined in Technical Q&A QA1871 (https://developer.apple.com/library/content/qa/qa1871/_index.html).

So I want to add a property of type ManagedObjectContext to my ViewController class.

I naturally declared it as an optional:

var moc: ManagedObjectContext?

But when I enter the property name in the bindings inspector of InterfaceBuilder, it complains: there is a red exclamation mark, and hovering over it pops up this error message:

“The Managed Object Context binding expects to be bound to an object of type NSObject, but mac is of type ManagedObjectContext?”

And it fails at run time too.

changing the type to ManagedObjectContext! doesn’t help: IB complains in exactly the same way.

changing the type to a non optional ManagedObjectContext silences the IB error, but now my ViewController class doesn’t compile anymore. The error I get is:

class ViewController has no initialiser

I completely understand this error message. And I can add an initialiser. But I get this new error message:

property ‘self.moc’ not initialised at super.init call.

I understand that one too, but what can I do? At initialiser-time, the managedObjectContext is not yet known. In Objective-C I would set it to nil, which I cannot do since the property is not an optional any more.

Do I really need to allocate a dummy sentinel ManagedObjectContext, just to make the compiler happy?

This would be ugly as hell, far worse than the nil value we use in Objective-C. Swift in that case, would not be safer, but less safe than Obj-C.

I find this idea repulsive. Or did I miss something?

Or is Swift fundamentally incompatible with Cocoa bindings? That would be a pity too.

Thanks,

Jean-Denis


(David Sweeris) #2

Is `moc` declared in a non-"@objc" scope? I think there's a "@IBsomethingerather" that you have to put in front of those to let Interface Builder see them or something. Sorry I can't be more definitive, but I'm not in front of my computer and can't double-check.

HTH
- Dave Sweeris

···

Sent from my iPhone

On Jan 16, 2017, at 10:11, Jean-Denis Muys via swift-users <swift-users@swift.org> wrote:

Hi,

I am exploring the use of Swift for a Mac Cocoa application - using Xcode 8.2.1, and it seems I hit a roadblock regarding Cocoa bindings.

In this toy Core Data document-based project, I added an NSArrayController in the StoryBoard. I need to bind it a NSManagedObjectContext so that my user interface works by itself. I followed the solution outlined in Technical Q&A QA1871 (https://developer.apple.com/library/content/qa/qa1871/_index.html).

So I want to add a property of type ManagedObjectContext to my ViewController class.

I naturally declared it as an optional:

var moc: ManagedObjectContext?

But when I enter the property name in the bindings inspector of InterfaceBuilder, it complains: there is a red exclamation mark, and hovering over it pops up this error message:

“The Managed Object Context binding expects to be bound to an object of type NSObject, but mac is of type ManagedObjectContext?”

And it fails at run time too.

changing the type to ManagedObjectContext! doesn’t help: IB complains in exactly the same way.

changing the type to a non optional ManagedObjectContext silences the IB error, but now my ViewController class doesn’t compile anymore. The error I get is:

class ViewController has no initialiser

I completely understand this error message. And I can add an initialiser. But I get this new error message:

property ‘self.moc’ not initialised at super.init call.

I understand that one too, but what can I do? At initialiser-time, the managedObjectContext is not yet known. In Objective-C I would set it to nil, which I cannot do since the property is not an optional any more.

Do I really need to allocate a dummy sentinel ManagedObjectContext, just to make the compiler happy?

This would be ugly as hell, far worse than the nil value we use in Objective-C. Swift in that case, would not be safer, but less safe than Obj-C.

I find this idea repulsive. Or did I miss something?

Or is Swift fundamentally incompatible with Cocoa bindings? That would be a pity too.

Thanks,

Jean-Denis

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Jean-Denis Muys) #3

moc is declared inside the view controller class, which is a subclass of NSViewController which is an Objective-C class. So I believe the scope is @objc

In any case, I tried to prefix the declaration with “@objc”, but this is has no visible effect.

That being said, prefixing its declaration with “dynamic” sort of fixes the problem: Interface Builder still complains as described, but the program now works fine at runtime.

I have a hard time understanding clearly why: for bindings to work, the bound properties need to be KVO-compliant. But wouldn’t the @objc scope already do that?

What is the exact effect of the dynamic annotation?

JD

PS: I made a zip archive of the project available at http://dl.free.fr/pWkoKQLOc. There is also an equivalent Objective-C project that works fine.

···

On 17 Jan 2017, at 17:43, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

Is `moc` declared in a non-"@objc" scope? I think there's a "@IBsomethingerather" that you have to put in front of those to let Interface Builder see them or something. Sorry I can't be more definitive, but I'm not in front of my computer and can't double-check.

HTH
- Dave Sweeris

Sent from my iPhone

On Jan 16, 2017, at 10:11, Jean-Denis Muys via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

Hi,

I am exploring the use of Swift for a Mac Cocoa application - using Xcode 8.2.1, and it seems I hit a roadblock regarding Cocoa bindings.

In this toy Core Data document-based project, I added an NSArrayController in the StoryBoard. I need to bind it a NSManagedObjectContext so that my user interface works by itself. I followed the solution outlined in Technical Q&A QA1871 (https://developer.apple.com/library/content/qa/qa1871/_index.html).

So I want to add a property of type ManagedObjectContext to my ViewController class.

I naturally declared it as an optional:

var moc: ManagedObjectContext?

But when I enter the property name in the bindings inspector of InterfaceBuilder, it complains: there is a red exclamation mark, and hovering over it pops up this error message:

“The Managed Object Context binding expects to be bound to an object of type NSObject, but mac is of type ManagedObjectContext?”

And it fails at run time too.

changing the type to ManagedObjectContext! doesn’t help: IB complains in exactly the same way.

changing the type to a non optional ManagedObjectContext silences the IB error, but now my ViewController class doesn’t compile anymore. The error I get is:

class ViewController has no initialiser

I completely understand this error message. And I can add an initialiser. But I get this new error message:

property ‘self.moc’ not initialised at super.init call.

I understand that one too, but what can I do? At initialiser-time, the managedObjectContext is not yet known. In Objective-C I would set it to nil, which I cannot do since the property is not an optional any more.

Do I really need to allocate a dummy sentinel ManagedObjectContext, just to make the compiler happy?

This would be ugly as hell, far worse than the nil value we use in Objective-C. Swift in that case, would not be safer, but less safe than Obj-C.

I find this idea repulsive. Or did I miss something?

Or is Swift fundamentally incompatible with Cocoa bindings? That would be a pity too.

Thanks,

Jean-Denis

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users