Why Xcode 12.5 errs when using Class as a key in NSDictionary?

I downloaded Xcode 12.5 Beta and now an existing project does not compile with errors telling I can't use Class as a key in NSDictionary.

Code Block
Cannot initialize a parameter of type 'id<NSCopying>  _Nonnull const __unsafe_unretained' with an rvalue of type 'Class'

I have assumes so far that while Class does not conform to NSCopying, it is safe to use as a dictionary key because it implements copy and copyWithZone:.

Did anything change with that regard in the compiler/runtime shipped with Xcode 12.5? Is it safe (and endorsed practice) to cast to id<NSCopying> to silence these errors?


  • 1

Can you post a snippet of code that triggers this issue?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Code Block
NSArray<id<FBObjectReference>> *FBGetObjectStrongReferences(id obj,
                              NSMutableDictionary<Class, NSArray<id<FBObjectReference>> *> *layoutCache) {
 NSMutableArray<id<FBObjectReference>> *array = [NSMutableArray new];
 __unsafe_unretained Class previousClass = nil;
 __unsafe_unretained Class currentClass = object_getClass(obj);
 while (previousClass != currentClass) {
  NSArray<id<FBObjectReference>> *ivars;
   
  if (layoutCache && currentClass) {
   ivars = layoutCache[currentClass];
  }
   
  if (!ivars) {
   ivars = FBGetStrongReferencesForClass(currentClass);
   if (layoutCache && currentClass) {
    layoutCache[currentClass] = ivars;
   }
  }
  [array addObjectsFromArray:ivars];
  previousClass = currentClass;
  currentClass = class_getSuperclass(currentClass);
 }
 return [array copy];
}

Same issue here. This won't compile on Xcode 12.5

Yes, apparently Xcode 12.5 are using Clang 10 that require you to cast it to id<NSCopying>
Example: https://github.com/facebook/FBRetainCycleDetector/pull/95/files

And if you are using Cocoapods, FBRetainCycleDetector makes that error, you need to specify the commit hash to make sure it using the latest version

Code Block ruby
pod 'FBRetainCycleDetector', { :git => 'https://github.com/facebook/FBRetainCycleDetector.git', :commit => '32c4afc1' }

Code Block          if ( !animationOperation.isCanceled ) {
          if ( !period.startValue ) {
            [period setStartValueFromObject:animationOperation.boundObject propertyGetter:animationOperation.boundGetter];
          }
          Class valueClass = period.valueClass;
          CGFloat progress = timingFunction(currentTime - startTime, duration);
          CPTDictionary *parameters = @{
            CPTAnimationOperationKey: animationOperation,
            CPTAnimationValueKey: [period tweenedValueForProgress:progress],
            CPTAnimationValueClassKey: valueClass ? valueClass : [NSNull null], /* this line won't compile in xcode 12.5 the error message is: Incompatible operand types ('Class' and 'NSNull * _Nonnull')*/
            CPTAnimationStartedKey: @(started),
            CPTAnimationFinishedKey: @(currentTime >= endTime)
          };
          // Used -performSelectorOnMainThread:... instead of GCD to ensure the animation continues to run in all run loop common modes.
          [self performSelectorOnMainThread:@selector(updateOnMainThreadWithParameters:)
                      withObject:parameters
                    waitUntilDone:NO
                        modes:runModes];
          if ( currentTime >= endTime ) {
            [expiredOperations addObject:animationOperation];
          }
        }

Upgraded today to Xcode 12.5, existing project build failed.
The code snippet source is from CorePlot: https://github.com/core-plot/core-plot/blob/master/framework/Source/CPTAnimation.m line 339

What should i do to avoid from this fail?
(without changing the source code)

Thank you!
Has anyone found a solution yet? I really do not want to modify a 3rd party library in order to make my project work.
Why Xcode 12.5 errs when using Class as a key in NSDictionary?
 
 
Q