[swift-users] Crasher in Swift<->Objective-C Interop!

Charles Srstka cocoadev at charlessoft.com
Mon May 1 02:08:04 CDT 2017

> On Apr 30, 2017, at 4:43 PM, Brent Royal-Gordon <brent at architechies.com> wrote:
>> On Apr 30, 2017, at 11:57 AM, Charles Srstka via swift-users <swift-users at swift.org> wrote:
>> What does the community think? Should I file this as a bug on Swift? Foundation? AppKit? All three?
> I would file it against AppKit. Once it's in Radar, they can kick the can over to Foundation or Swift, but it's trickier to do the opposite.

Thought about it a bit, and it really is two separate issues. AppKit probably *shouldn’t* be using NSCopyObject to copy things, and Swift shouldn’t be crashing if it does. So, I’ve filed a bug report on each:

https://bugs.swift.org/browse/SR-4756 <https://bugs.swift.org/browse/SR-4756>

In the event that anyone with the same problem (which, if anyone’s curious, was implementing a custom field editor, the only customization point for which is on NSCell rather than NSControl) discovers this thread, let me save you a little time on some workarounds that don’t work:

Implementing your own copy(with:) method fails, because you need to call super’s implementation to copy the cell effectively, and the crash will still occur.

Using a weak property to the containing NSControl and putting your stored properties there doesn't work, because NSCopyObject doesn't seem to play nice with weak variables either, and all sorts of errors will be logged to the console.

Using an unowned property to the containing NSControl doesn't work, because unowned properties cannot be null, and the connection will not be made until runtime.

Making a non-Objective-C property and storing your Objective-C properties inside it seemed to work some of the time, and crashed other times, when I tried it. I haven’t studied the low-level layout of Swift objects enough to know why this was.

What works is to use Objective-C associated objects. Use objc_getAssociatedObject in the getter and objc_setAssociatedObject in the setter. Be sure to use withUnsafeMutableBytes on your key property and pass its baseAddress as the key, because the associated object functions take immutable pointers, and since your key property has to be a var to ensure it stays unique, just passing it via & character will cause Swift to make an immutable copy first, and then pass a pointer to *that*, and things won’t work.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20170501/8cf5999e/attachment.html>

More information about the swift-users mailing list