Skip to content

Commit 3f85e7a

Browse files
committed
Caching whether methods needs structure return.
1 parent ab4e59a commit 3f85e7a

File tree

3 files changed

+25
-6
lines changed

3 files changed

+25
-6
lines changed

Source/OCMock/NSObject+OCMAdditions.m

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,33 @@
2020

2121
@implementation NSObject(OCMAdditions)
2222

23+
static NSMutableDictionary *_OCMReturnTypeCache;
24+
2325
+ (IMP)instanceMethodForwarderForSelector:(SEL)aSelector
2426
{
25-
// use NSSelectorFromString and not @selector to avoid warning
26-
SEL selectorWithNoImplementation = NSSelectorFromString(@"methodWhichMustNotExist::::");
27+
// use sel_registerName() and not @selector to avoid warning
28+
SEL selectorWithNoImplementation = sel_registerName("methodWhichMustNotExist::::");
2729

2830
#ifndef __arm64__
29-
NSMethodSignature *sig = [self instanceMethodSignatureForSelector:aSelector];
30-
if([sig usesSpecialStructureReturn])
31+
if(_OCMReturnTypeCache == nil)
32+
_OCMReturnTypeCache = [[NSMutableDictionary alloc] init];
33+
34+
BOOL needsStructureReturn;
35+
NSString *cacheKey = [NSString stringWithFormat:@"%p-%p", (void *)self, aSelector];
36+
NSNumber *cachedValue = [_OCMReturnTypeCache objectForKey:cacheKey];
37+
38+
if(cachedValue == nil)
39+
{
40+
NSMethodSignature *sig = [self instanceMethodSignatureForSelector:aSelector];
41+
needsStructureReturn = [sig usesSpecialStructureReturn];
42+
[_OCMReturnTypeCache setObject:[NSNumber numberWithBool:needsStructureReturn] forKey:cacheKey];
43+
}
44+
else
45+
{
46+
needsStructureReturn = [cachedValue boolValue];
47+
}
48+
49+
if(needsStructureReturn)
3150
return class_getMethodImplementation_stret([NSObject class], selectorWithNoImplementation);
3251
#endif
3352

Source/OCMock/OCClassMockObject.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ - (void)setupForwarderForClassMethodSelector:(SEL)selector
142142
const char *types = method_getTypeEncoding(originalMethod);
143143

144144
Class metaClass = object_getClass(mockedClass);
145-
IMP forwarderIMP = [metaClass instanceMethodForwarderForSelector:selector];
145+
IMP forwarderIMP = [originalMetaClass instanceMethodForwarderForSelector:selector];
146146
class_replaceMethod(metaClass, selector, forwarderIMP, types);
147147
class_addMethod(metaClass, aliasSelector, originalIMP, types);
148148
}

Source/OCMock/OCPartialMockObject.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ - (void)setupForwarderForSelector:(SEL)sel
162162
types = ([[mockedClass instanceMethodSignatureForSelector:sel] fullObjCTypes]);
163163

164164
Class subclass = object_getClass([self realObject]);
165-
IMP forwarderIMP = [subclass instanceMethodForwarderForSelector:sel];
165+
IMP forwarderIMP = [mockedClass instanceMethodForwarderForSelector:sel];
166166
class_replaceMethod(subclass, sel, forwarderIMP, types);
167167
class_addMethod(subclass, aliasSelector, originalIMP, types);
168168
}

0 commit comments

Comments
 (0)