iOS 17 Beta app crash when using [obj valueForKey:@"copy"]

I ran across the following crash while using one of our apps. The app crashes since the recent iOS 17 beta builds. The code crashes when using valueForKey on an NSArray with objects that implement NSCopying.

like: [@[[Sample new]] valueForKey:@"copy"];

or: [[Sample new] valueForKey:@"copy"];

header:

@interface Sample : NSObject<NSCopying>

- (Sample *)copy;
- (Sample *)copyWithZone:(nullable NSZone *)zone;

@end

implementation:

@implementation Sample

- (Sample *)copy {
  return [super copy];
}

- (Sample *)copyWithZone:(nullable NSZone *)zone {
  return self;
}

@end

Any idea why this might be happening?

I have created a feedback too: FB12819891

Replies

So it’s throwing [<Sample 0x600000010510> valueForUndefinedKey:]: this class is not key value coding-compliant for the key copy. Which seems reasonable to me. KVC is meant to target properties, and -copy is not a property.

Well…

In the old school Objective-C sense, any getter method — a method with a result and no arguments — could be thought of a read-only property. However, that doesn’t work for -copy, because it returns a +1 ref count object whereas a getter method is meant to return a +0.

I have created a feedback too: FB12819891

Thanks for that. The Foundation folks will take a look. However, my advice is that you change your code. You’re using KVC in a way that runs counter to its design. Honestly, I’m amazed this ever worked (-:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks for the fast and detailed response!

Makes total sense that KVO is meant to access properties only, but until now it was/is not forced for other methods than -copy. If I extend my class and define a method like:

- (Sample *)notCrashing {
  return [self copy];
}

and call it like [@[[Sample new]] valueForKey:@"notCrashing"]; it also returns a +1 ref count object, but it does not crash on iOS 17.

Or do I misunderstand?

Anyway I will change all places where KVC is used in that way before iOS 17 will be released to avoid crashes :-)

it does not crash on iOS 17.

Yes, that’s what I’d expect.

it also returns a +1 ref count object

Are you sure about that? If you’re using ARC, it should add an autorelease to your -notCrashing method so that it returns +0.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Yes, you are right. I checked again and ARC is adding an autorelease to -notCrashing. Thanks for the clarification.