The code is under ARC. When I delete the code NSObject* objc = (NSObject*)object;
the program runs fine, but I didn't have access to the pointer objc
. When I keep the code NSObject* objc = (NSObject*)object;
I am prompted EXC_BAD_ACCESS (code=1, address=0x20)
. Is the system accessing the objc
pointer after the block function body ends?
-(void)resetDeallocMethodWithInstance:(NSObject*)obj
{
Class targetClass = obj.class;
@synchronized (swizzledClasses()) {
NSString *className = NSStringFromClass(obj.class);
if ([swizzledClasses() containsObject:className]) return;
SEL deallocSel = sel_registerName("dealloc");
__block void (*deallocBlock)(__unsafe_unretained id, SEL) = NULL;
id block = ^(__unsafe_unretained id object){
NSObject* objc = (NSObject*)object;
NSUInteger hash = ((NSObject*)object).hash;
[self removeAllTargetWitSuffixKey:[NSString stringWithFormat:@"%lu",(unsigned long)hash]];
if (deallocBlock == NULL) {
struct objc_super superInfo = {
.receiver = object,
.super_class = class_getSuperclass(targetClass)
};
void (*msgSend)(struct objc_super *, SEL) = (__typeof__(msgSend))objc_msgSendSuper;
msgSend(&superInfo, deallocSel);
} else {
deallocBlock(object, deallocSel);
}
};
IMP blockImp = imp_implementationWithBlock(block);
if (!class_addMethod(obj.class, deallocSel, blockImp, "v@:")) {
Method deallocMethod = class_getInstanceMethod(obj.class, deallocSel);
deallocBlock = (__typeof__(deallocBlock))method_getImplementation(deallocMethod);
deallocBlock = (__typeof__(deallocBlock))method_setImplementation(deallocMethod, blockImp);
}
[swizzledClasses() addObject:className];
}
return;
}
Note: This answer is being directly typed in, your code has not been tested, indeed no code has been tested. Therefore that the issues below are causing your issues is being inferred.
There area number of issues with your design:
dealloc
is not recommended. Thedealloc
method is called automatically by the system when it is in the process of destroying an object, as such using the partly destroyed object inappropriately (whatever that might be) could lead to issues - as you have found!objc
is unused. However by default a local variable has the attributestrong
so you are creating a strong reference to an object in the process of destruction. Any strong reference made by the block in this way will be released by ARC when the block has finished, this is almost certainly not good as your error indicates.You appear to be trying to call your
removeAllTargetWithSuffixKey:
method when a particular object is destroyed (appear as you swizzle [and can only swizzle] the class but are using thehash
of a particular object). A better way to do this avoiding swizzling is to use associated objects.The runtime function
objc_setassociatedobject()
allows you to attach an object to a particular instance of another object and have that object be destroyed automatically when its host is destroyed (use anobjc_AssociationPolicy
ofOBJC_ASSOCIATION_RETAIN
).Design a class which has an instance property of your required
hash
value and adealloc
method which calls yourremoveAllTargetWithSuffixKey:
then rather than swizzle the class simply create and associate an instance of your class with the target object.HTH