Fix isa swizzling for Kotlin subclasses of Obj-C classes
Don't rely on indexed ivars of instance's isa since isa swizzling replaces it. Use method instead, it works on the replacement too (if it is a subclass of the original isa). #KT-42482 Fixed.
This commit is contained in:
committed by
Stanislav Erokhin
parent
e1d9a36de3
commit
62272f54c1
@@ -0,0 +1,10 @@
|
||||
#import <Foundation/NSObject.h>
|
||||
|
||||
extern BOOL kt42482Deallocated;
|
||||
extern id kt42482Global;
|
||||
|
||||
@interface KT42482 : NSObject
|
||||
-(int)fortyTwo;
|
||||
@end;
|
||||
|
||||
void kt42482Swizzle(id obj);
|
||||
@@ -0,0 +1,35 @@
|
||||
import kotlin.native.ref.WeakReference
|
||||
import kotlinx.cinterop.*
|
||||
import kotlin.test.*
|
||||
import objcTests.*
|
||||
|
||||
@Test
|
||||
fun testKT42482() {
|
||||
// Attempt to make the state predictable:
|
||||
kotlin.native.internal.GC.collect()
|
||||
|
||||
kt42482Deallocated = false
|
||||
assertFalse(kt42482Deallocated);
|
||||
|
||||
{
|
||||
assertEquals(41, KT42482().fortyTwo())
|
||||
|
||||
val obj: KT42482 = KT42482Impl()
|
||||
assertEquals(42, obj.fortyTwo())
|
||||
|
||||
kt42482Swizzle(obj)
|
||||
assertEquals(43, obj.fortyTwo())
|
||||
|
||||
// Test retain and release on swizzled object:
|
||||
kt42482Global = obj
|
||||
kt42482Global = null
|
||||
}()
|
||||
|
||||
kotlin.native.internal.GC.collect()
|
||||
|
||||
assertTrue(kt42482Deallocated)
|
||||
}
|
||||
|
||||
class KT42482Impl : KT42482() {
|
||||
override fun fortyTwo() = 42
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#import "kt42482.h"
|
||||
#import "assert.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
BOOL kt42482Deallocated = NO;
|
||||
id kt42482Global = nil;
|
||||
|
||||
@implementation KT42482
|
||||
-(int)fortyTwo {
|
||||
return 41;
|
||||
}
|
||||
|
||||
-(void)dealloc {
|
||||
kt42482Deallocated = YES;
|
||||
}
|
||||
@end;
|
||||
|
||||
int fortyTwoSwizzledImp(id self, SEL _cmd) {
|
||||
return 43;
|
||||
}
|
||||
|
||||
void kt42482Swizzle(id obj) {
|
||||
Class oldClass = object_getClass(obj);
|
||||
|
||||
SEL selector = @selector(fortyTwo);
|
||||
|
||||
Class newClass = objc_allocateClassPair(oldClass, "KT42482Swizzled", 0);
|
||||
assert(newClass != nil);
|
||||
objc_registerClassPair(newClass);
|
||||
|
||||
Method method = class_getInstanceMethod([KT42482 class], selector);
|
||||
assert(method != nil);
|
||||
class_addMethod(newClass, selector, (IMP)&fortyTwoSwizzledImp, method_getTypeEncoding(method));
|
||||
|
||||
object_setClass(obj, newClass);
|
||||
}
|
||||
Reference in New Issue
Block a user