Tuesday, April 9, 2019

Implementing [NSCell copyWithZone:] in Swift to Avoid Crashes in AppKit

Corbin Dunn (tweet):

It looks like using a baseline constraint with Autolayout will cause it to copy the cell to determine the baseline. So, if you are using AutoLayout, be aware of implicit copies that might happen behind your back!

The trouble with [NSCell copyWithZone:] is that it uses NSCopyObject, which blindly assigns ivars from one instance to another and doesn’t do any proper memory management. I didn’t think this would still be an issue in Swift, but apparently it is! See my solution at the top where I simply retain the value during the copy.

He writes:

let _ = Unmanaged<NSColor>.passRetained(previousTextColor)

1 Comment RSS · Twitter

Martin Wierschin

NSCell's unfortunate use of NSCopyObject has long been a nuisance. I have some old pre-ARC Objective-C subclasses that bypass it like so:

- (id) copyWithZone:(NSZone*)zone
{
    XXCustomCell* clone = [super copyWithZone:zone];
    [[clone subclassIvar] retain];
    return clone;
}

The static analyzer naturally flags the code as improper, but without the seemingly spurious retain the clone will trigger a crash.

Leave a Comment