diff --git a/ChangeLog b/ChangeLog index aea743879..dd4b3d58b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2001-05-12 Richard Frith-Macdonald + + * Source/NSObject.m: Removed some unused obsolete code. + * Source/NSProxy.m: Modified ([methodSignatureForSelector:]) and + ([respondsToSelector:]) to work for existing methods and raise + exception for non-existant methods. The MacOS-X docs says they raise + exceptions, but I think it makes sense for them to work for methods + that are actually implemented in the proxy. + 2001-05-11 Adam Fedor * Source/NSArchiver.m ([NSArchiver -encodeValueOfObjCType:at:]): Use diff --git a/Source/NSObject.m b/Source/NSObject.m index 67243c236..7c1d830b6 100644 --- a/Source/NSObject.m +++ b/Source/NSObject.m @@ -1101,14 +1101,7 @@ static BOOL deallocNotifications = NO; - (BOOL) respondsToSelector: (SEL)aSelector { -#if 0 - if (GSObjCIsInstance(self)) - return (class_get_instance_method(GSObjCClass(self), aSelector)!=METHOD_NULL); - else - return (class_get_class_method(GSObjCClass(self), aSelector)!=METHOD_NULL); -#else return __objc_responds_to(self, aSelector); -#endif } - (id) retain diff --git a/Source/NSProxy.m b/Source/NSProxy.m index 05522b614..c32fdad22 100644 --- a/Source/NSProxy.m +++ b/Source/NSProxy.m @@ -30,6 +30,7 @@ #include #include "limits.h" +extern BOOL __objc_responds_to(id, SEL); @implementation NSProxy @@ -54,19 +55,35 @@ return self; } -+ (void) load -{ - /* Do nothing */ -} - + (NSString*) description { return [NSString stringWithFormat: @"<%s>", object_get_class_name(self)]; } -+ (BOOL) respondsToSelector: (SEL)aSelector ++ (void) load { - return (class_get_class_method(self, aSelector) != METHOD_NULL); + /* Do nothing */ +} + ++ (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector +{ + struct objc_method *mth; + + if (aSelector == 0) + { + return nil; + } + mth = class_get_class_method(GSObjCClass(self), aSelector); + if (mth != 0) + { + const char *types = mth->method_types; + + if (types != 0) + { + return [NSMethodSignature signatureWithObjCTypes: types]; + } + } + return nil; } + (void) release @@ -74,6 +91,14 @@ /* Do nothing */ } ++ (BOOL) respondsToSelector: (SEL)aSelector +{ + if (__objc_responds_to(self, aSelector)) + return YES; + else + return NO; +} + + (id) retain { return self; @@ -121,8 +146,8 @@ NSInvocation *inv; inv = AUTORELEASE([[NSInvocation alloc] initWithArgframe: argFrame - selector: aSel]); - [self forwardInvocation:inv]; + selector: aSel]); + [self forwardInvocation: inv]; return [inv returnFrame: argFrame]; } @@ -140,6 +165,9 @@ - (id) init { + [NSException raise: NSGenericException + format: @"subclass %s should override %s", object_get_class_name(self), + sel_get_name(_cmd)]; return self; } @@ -190,10 +218,30 @@ return self; } +/* + * If we respond to the method directly, create and return a method + * signature. Otherwise raise an exception. + */ - (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector { + struct objc_method *mth; + + if (aSelector == 0) + { + return nil; + } + mth = class_get_instance_method(GSObjCClass(self), aSelector); + if (mth != 0) + { + const char *types = mth->method_types; + + if (types != 0) + { + return [NSMethodSignature signatureWithObjCTypes: types]; + } + } [NSException raise: NSInvalidArgumentException format: - @"NSProxy should not implement 'methodSignatureForSelector:'"]; + @"NSProxy should not implement 'methodSignatureForSelector:'"]; return nil; } @@ -252,12 +300,34 @@ #endif } +/* + * If we respond to the method directly, return YES, otherwise + * forward this request to the object we are acting as a proxy for. + */ - (BOOL) respondsToSelector: (SEL)aSelector { - [NSException raise: NSGenericException - format: @"subclass %s should override %s", object_get_class_name(self), - sel_get_name(_cmd)]; - return NO; + if (aSelector == 0) + { + return NO; + } + if (__objc_responds_to(self, aSelector)) + { + return YES; + } + else + { + NSMethodSignature *sig; + NSInvocation *inv; + BOOL ret; + + sig = [self methodSignatureForSelector: _cmd]; + inv = [NSInvocation invocationWithMethodSignature: sig]; + [inv setSelector: _cmd]; + [inv setArgument: &aSelector atIndex: 2]; + [self forwardInvocation: inv]; + [inv getReturnValue: &ret]; + return ret; + } } - (id) retain