in RenderCore/View/CKComponentViewAttribute.mm [86:206]
static void performSetter(id object, SEL setter, id value)
{
if ([value isKindOfClass:[NSValue class]]) {
const CachedSetter &set = cachedSetterInvocation(object, setter);
if (set.invocation) {
if ([value isKindOfClass:[NSNumber class]]) {
// We special case NSNumber because getting the correct byte width on both sides
// is either hard (e.g. NSInteger), or impossible (e.g. CGFloat) on all architectures
// simultaneously.
// See https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
// for more information on type encodings
if (set.argumentType == nullptr || strlen(set.argumentType) != 1) {
RCCAssert(NO, @"NSNumber: %@ cannot be used as an argument to a selector requiring '%s'; selector: %@; class %@",
value, set.argumentType ?: "NULL", NSStringFromSelector(setter), [object class]);
return;
}
NSNumber *numValue = (NSNumber *)value;
switch (*set.argumentType) {
case 'c': {
RCCAssertSizeOfEquals(char, set.argumentType, @"");
char charValue = [numValue charValue];
[set.invocation setArgument:&charValue atIndex:2];
break;
}
case 'i': {
RCCAssertSizeOfEquals(int, set.argumentType, @"");
int intValue = [numValue intValue];
[set.invocation setArgument:&intValue atIndex:2];
break;
}
case 's': {
RCCAssertSizeOfEquals(short, set.argumentType, @"");
short shortValue = [numValue shortValue];
[set.invocation setArgument:&shortValue atIndex:2];
break;
}
case 'l': {
// This is inconsistent, from the docs: "l is treated as a 32-bit quantity on 64-bit programs."
RCCAssertSizeOfEquals(int32_t, set.argumentType, @"");
int32_t longValue = [numValue intValue];
[set.invocation setArgument:&longValue atIndex:2];
break;
}
case 'q': {
RCCAssertSizeOfEquals(long long, set.argumentType, @"");
long long longLongValue = [numValue longLongValue];
[set.invocation setArgument:&longLongValue atIndex:2];
break;
}
case 'C': {
RCCAssertSizeOfEquals(unsigned char, set.argumentType, @"");
unsigned char uCharValue = [numValue unsignedCharValue];
[set.invocation setArgument:&uCharValue atIndex:2];
break;
}
case 'I': {
RCCAssertSizeOfEquals(unsigned int, set.argumentType, @"");
unsigned int uIntValue = [numValue unsignedIntValue];
[set.invocation setArgument:&uIntValue atIndex:2];
break;
}
case 'S': {
RCCAssertSizeOfEquals(unsigned short, set.argumentType, @"");
unsigned short uShortValue = [numValue unsignedShortValue];
[set.invocation setArgument:&uShortValue atIndex:2];
break;
}
case 'L': {
// This is also inconsistent, and undocumented
RCCAssertSizeOfEquals(uint32_t, set.argumentType, @"");
uint32_t uLongValue = [numValue unsignedIntValue];
[set.invocation setArgument:&uLongValue atIndex:2];
break;
}
case 'Q': {
RCCAssertSizeOfEquals(unsigned long long, set.argumentType, @"");
unsigned long long uLongLongValue = [numValue unsignedLongLongValue];
[set.invocation setArgument:&uLongLongValue atIndex:2];
break;
}
case 'f': {
RCCAssertSizeOfEquals(float, set.argumentType, @"");
float floatValue = [numValue floatValue];
[set.invocation setArgument:&floatValue atIndex:2];
break;
}
case 'd': {
RCCAssertSizeOfEquals(double, set.argumentType, @"");
double doubleValue = [numValue doubleValue];
[set.invocation setArgument:&doubleValue atIndex:2];
break;
}
case 'B': {
RCCAssertSizeOfEquals(BOOL, set.argumentType, @"");
BOOL boolValue = [numValue boolValue];
[set.invocation setArgument:&boolValue atIndex:2];
break;
}
default:
// This should just be: 'v', '*', '@', '#', ':', '?', none of which should be boxed as NSNumber
RCCAssert(NO, @"NSNumber: %@ cannot be used as an argument to a selector requiring '%s'", value, set.argumentType);
return;
}
} else {
char buf[set.argumentSize];
[value getValue:buf];
[set.invocation setArgument:buf atIndex:2];
}
[set.invocation setSelector:setter];
[set.invocation invokeWithTarget:object];
return;
}
}
// ARC is worried that the selector might have a return value it doesn't know about, or be annotated with ns_consumed.
// Neither is typically the case for setters, so ignore the warning.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[object performSelector:setter withObject:value];
#pragma clang diagnostic pop
}