그래서 나는 총알에 맞고 내 자신의 프록시 클래스를 만들기로 결정했습니다. 서브 클래 싱하려면 'forwardInvocation :'메시지를 재정의하고 [super forwardInvocation:]
을 호출하기 전에 필요한 코드를 호출하면됩니다. 제발 Nardnvocation Vardic 방법으로 작동하지 않습니다 Vardic 방법으로 작동하지 않습니다 제발.
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <objc/objc.h>
#import <objc/message.h>
@interface RJProxy : NSObject {
@private
NSObject *target;
}
@property(readwrite, retain) NSObject *target;
-(NSObject *) getTarget;
@end
@implementation RJProxy
@synthesize target;
-(NSMethodSignature *) methodSignatureForSelector:(SEL)aSelector
{
if (objc_getAssociatedObject(self, "isProxy"))
{
IMP NSObjectImp = [NSObject instanceMethodForSelector:@selector(methodSignatureForSelector:)];
NSMethodSignature *methodSignature = (NSMethodSignature *) NSObjectImp(self, @selector(methodSignatureForSelector:), aSelector);
if (methodSignature)
return methodSignature;
return [target methodSignatureForSelector:aSelector];
}
else
{
Class subClass = self->isa;
@try {
self->isa = objc_getAssociatedObject(self, "realSuperclass");
return [super methodSignatureForSelector:aSelector];
}
@finally {
self->isa = subClass;
}
}
}
-(void) forwardInvocation:(NSInvocation *)anInvocation
{
if (objc_getAssociatedObject(self, "isProxy"))
{
Class subClass = target->isa;
target->isa = objc_getAssociatedObject(self, "realSuperclass");
[anInvocation invokeWithTarget:target];
target->isa = subClass;
}
else
{
Class realSuperclass = objc_getAssociatedObject(self, "realSuperclass");
Class subclass = self->isa;
self->isa = realSuperclass;
if ([self respondsToSelector:[anInvocation selector]])
{
[anInvocation invokeWithTarget:self];
}
else
{
[self doesNotRecognizeSelector:[anInvocation selector]];
}
self->isa = subclass;
}
}
-(NSObject *) getTarget
{
if (objc_getAssociatedObject(self, "isProxy"))
{
return target;
}
return self;
}
@end
BOOL object_setProxy(NSObject *object, RJProxy *proxy);
BOOL object_setProxy(NSObject *object, RJProxy *proxy)
{
proxy.target = object;
Class objectClass = object_getClass(object);
Class objectSub = objc_allocateClassPair(objectClass, [[NSString stringWithFormat:@"%s_sub%i", class_getName(objectClass), objc_getAssociatedObject(objectClass, "subclassTimes")] UTF8String], 0);
objc_setAssociatedObject(objectClass, "subclassTimes", (id) ((int) objc_getAssociatedObject(objectClass, "subclassTimes") + 1), OBJC_ASSOCIATION_ASSIGN);
objc_registerClassPair(objectSub);
Class proxyClass = object_getClass(proxy);
Class proxySub = objc_allocateClassPair(proxyClass, [[NSString stringWithFormat:@"%s_sub%i", class_getName(proxyClass), objc_getAssociatedObject(proxyClass, "subclassTimes")] UTF8String], 0);
objc_setAssociatedObject(proxyClass, "subclassTimes", (id) ((int) objc_getAssociatedObject(proxyClass, "subclassTimes") + 1), OBJC_ASSOCIATION_ASSIGN);
objc_registerClassPair(proxySub);
object_setClass(object, proxySub);
object_setClass(proxy, proxySub);
objc_setAssociatedObject(object, "isProxy", (id) NO, OBJC_ASSOCIATION_ASSIGN);
objc_setAssociatedObject(proxy, "isProxy", (id) YES, OBJC_ASSOCIATION_ASSIGN);
objc_setAssociatedObject(object, "realSuperclass", objectClass, OBJC_ASSOCIATION_ASSIGN);
objc_setAssociatedObject(proxy, "realSuperclass", proxyClass, OBJC_ASSOCIATION_ASSIGN);
return NO;
}
@interface SynchronizeProxy : RJProxy
@end
@implementation SynchronizeProxy
-(void) forwardInvocation:(NSInvocation *)anInvocation {
@synchronized ([self getTarget])
{
[super forwardInvocation:anInvocation];
}
}
@end
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSArray *arrayToSynchronize = [NSArray arrayWithObjects:@"This, is, a, test!", nil];
SynchronizeProxy *myProxy = [SynchronizeProxy new];
object_setProxy(arrayToSynchronize, myProxy);
// now all calls will be synchronized!
NSLog(@"Array at address 0x%X with count of %lu, and Objects %@ ", (unsigned) arrayToSynchronize, [arrayToSynchronize count], arrayToSynchronize);
[myProxy release];
[arrayToSynchronize release];
}
return 0;
}
그래서 'Some Object'또는 'Some Calling Object'도 제어 할 수 없습니까? – barley
@Barley, 맞습니다. 당신이 iOS 기반 라이브러리에 그다지 액세스 할 수 없다는 것은 부끄러운 일입니다. –
일반적으로 이런 종류의 "모든 스레드는 언제든지 모든 메서드를 호출 할 수 있습니다"동시성 패턴은 병적으로 나쁜 성능을 초래합니다. – bbum