Revision: 4279
http://skim-app.svn.sourceforge.net/skim-app/?rev=4279&view=rev
Author: hofman
Date: 2008-07-23 09:07:28 +0000 (Wed, 23 Jul 2008)
Log Message:
-----------
Enhance method swizzle API.
Modified Paths:
--------------
trunk/NSObject_SKExtensions.h
trunk/NSObject_SKExtensions.m
Modified: trunk/NSObject_SKExtensions.h
===================================================================
--- trunk/NSObject_SKExtensions.h 2008-07-22 17:14:59 UTC (rev 4278)
+++ trunk/NSObject_SKExtensions.h 2008-07-23 09:07:28 UTC (rev 4279)
@@ -58,4 +58,8 @@
- (IMP)setMethodFromSelector:(SEL)impSelector forSelector:(SEL)aSelector;
+ (IMP)setInstanceMethodFromSelector:(SEL)impSelector
forSelector:(SEL)aSelector;
++ (void)exchangeMethodForSelector:(SEL)aSelector1
withMethodForSelector:(SEL)aSelector2;
+- (void)exchangeMethodForSelector:(SEL)aSelector1
withMethodForSelector:(SEL)aSelector2;
++ (void)exchangeInstanceMethodForSelector:(SEL)aSelector1
withInstanceMethodForSelector:(SEL)aSelector2;
+
@end
Modified: trunk/NSObject_SKExtensions.m
===================================================================
--- trunk/NSObject_SKExtensions.m 2008-07-22 17:14:59 UTC (rev 4278)
+++ trunk/NSObject_SKExtensions.m 2008-07-23 09:07:28 UTC (rev 4279)
@@ -20,24 +20,24 @@
#import <objc/objc-runtime.h>
+#pragma mark Runtime compatibility
// wrappers around 10.5 only functions, use 10.4 API when the function is not
defined
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+#pragma mark 10.4 + 10.5
+
extern void _objc_flush_caches(Class);
-static Class SK_object_getClass(id object)
-{
+static inline Class SK_object_getClass(id object) {
return object_getClass != NULL ? object_getClass(object) : object->isa;
}
-static IMP SK_method_getImplementation(Method aMethod)
-{
+static inline IMP SK_method_getImplementation(Method aMethod) {
return method_getImplementation != NULL ?
method_getImplementation(aMethod) : aMethod->method_imp;
}
-static IMP SK_method_setImplementation(Method aMethod, IMP anImp)
-{
+static inline IMP SK_method_setImplementation(Method aMethod, IMP anImp) {
if (method_setImplementation != NULL) {
return method_setImplementation(aMethod, anImp);
} else {
@@ -47,25 +47,30 @@
}
}
-static const char *SK_method_getTypeEncoding(Method aMethod)
-{
+static inline void SK_method_exchangeImplementations(Method aMethod1, Method
aMethod2) {
+ if (method_exchangeImplementations != NULL) {
+ method_exchangeImplementations(aMethod1, aMethod2);
+ } else {
+ IMP imp = aMethod1->method_imp;
+ aMethod1->method_imp = aMethod2->method_imp;
+ aMethod2->method_imp = imp;
+ }
+}
+
+static inline const char *SK_method_getTypeEncoding(Method aMethod) {
return method_getTypeEncoding != NULL ? method_getTypeEncoding(aMethod) :
aMethod->method_types;
}
-static Class SK_class_getSuperclass(Class aClass)
-{
+static inline Class SK_class_getSuperclass(Class aClass) {
return class_getSuperclass != NULL ? class_getSuperclass(aClass) :
aClass->super_class;
}
-static void SK_class_addMethod(Class aClass, SEL selector, IMP methodImp,
const char *methodTypes)
-{
+static inline void SK_class_addMethod(Class aClass, SEL selector, IMP
methodImp, const char *methodTypes) {
if (class_addMethod != NULL) {
class_addMethod(aClass, selector, methodImp, methodTypes);
} else {
- struct objc_method_list *newMethodList;
+ struct objc_method_list *newMethodList = (struct objc_method_list
*)NSZoneMalloc(NSDefaultMallocZone(), sizeof(struct objc_method_list));
- newMethodList = (struct objc_method_list *)
NSZoneMalloc(NSDefaultMallocZone(), sizeof(struct objc_method_list));
-
newMethodList->method_count = 1;
newMethodList->method_list[0].method_name = selector;
newMethodList->method_list[0].method_imp = methodImp;
@@ -80,47 +85,47 @@
#else
-static Class SK_object_getClass(id object)
-{
+#pragma mark 10.5
+
+static inline Class SK_object_getClass(id object) {
return object_getClass(object);
}
-static IMP SK_method_getImplementation(Method aMethod)
-{
+static inline IMP SK_method_getImplementation(Method aMethod) {
return method_getImplementation(aMethod);
}
-static IMP SK_method_setImplementation(Method aMethod, IMP anImp)
-{
+static inline IMP SK_method_setImplementation(Method aMethod, IMP anImp) {
return method_setImplementation(aMethod, anImp);
}
-static const char *SK_method_getTypeEncoding(Method aMethod)
-{
+static inline void SK_method_exchangeImplementations(Method aMethod1, Method
aMethod2) {
+ method_exchangeImplementations(aMethod1, aMethod2);
+}
+
+static inline const char *SK_method_getTypeEncoding(Method aMethod) {
return method_getTypeEncoding(aMethod);
}
-static Class SK_class_getSuperclass(Class aClass)
-{
+static inline Class SK_class_getSuperclass(Class aClass) {
return class_getSuperclass(aClass);
}
-static void SK_class_addMethod(Class aClass, SEL selector, IMP methodImp,
const char *methodTypes)
-{
+static inline void SK_class_addMethod(Class aClass, SEL selector, IMP
methodImp, const char *methodTypes) {
class_addMethod(aClass, selector, methodImp, methodTypes);
}
#endif
-static Method SK_class_getMethod(Class aClass, SEL aSelector, BOOL isInstance)
-{
+static inline Method SK_class_getMethod(Class aClass, SEL aSelector, BOOL
isInstance) {
return isInstance ? class_getInstanceMethod(aClass, aSelector) :
class_getClassMethod(aClass, aSelector);
}
-static IMP SKSetMethodImplementation(Class aClass, SEL aSelector, IMP anImp,
const char *types, BOOL isInstance)
-{
+#pragma mark Basic functions
+
+static IMP SKSetMethodImplementation(Class aClass, SEL aSelector, IMP anImp,
const char *types, BOOL isInstance) {
+ Method localMethod = SK_class_getMethod(aClass, aSelector, isInstance);
Method superMethod = NULL;
- Method localMethod = SK_class_getMethod(aClass, aSelector, isInstance);
IMP oldImp = NULL;
Class superCls = Nil;
Class realClass = isInstance ? aClass : SK_object_getClass(aClass);
@@ -146,12 +151,44 @@
return oldImp;
}
-static const char *SKGetTypeEncoding(Class aClass, SEL aSelector, BOOL
isInstance)
-{
+static void SKExchangeMethodImplementations(Class aClass, SEL aSelector1, SEL
aSelector2, BOOL isInstance) {
+ Method localMethod1 = SK_class_getMethod(aClass, aSelector1, isInstance);
+ Method localMethod2 = SK_class_getMethod(aClass, aSelector2, isInstance);
+ Method superMethod1 = NULL;
+ Method superMethod2 = NULL;
+ Class superCls = Nil;
+ Class realClass = isInstance ? aClass : SK_object_getClass(aClass);
+
+ if (localMethod1 && localMethod2) {
+ if (superCls = SK_class_getSuperclass(aClass)) {
+ superMethod1 = SK_class_getMethod(superCls, aSelector1,
isInstance);
+ superMethod2 = SK_class_getMethod(superCls, aSelector2,
isInstance);
+ }
+ if (superMethod1 != localMethod1 && superMethod2 != localMethod2) {
+ SK_method_exchangeImplementations(localMethod1, localMethod2);
+ } else {
+ IMP imp1 = SK_method_getImplementation(localMethod1);
+ IMP imp2 = SK_method_getImplementation(localMethod2);
+ const char *types = SK_method_getTypeEncoding(localMethod1);
+ if (superMethod1 == localMethod1)
+ SK_class_addMethod(realClass, aSelector1, imp2, types);
+ else
+ SK_method_setImplementation(localMethod1, imp2);
+ if (superMethod2 == localMethod2)
+ SK_class_addMethod(realClass, aSelector2, imp1, types);
+ else
+ SK_method_setImplementation(localMethod2, imp1);
+ }
+ }
+}
+
+static const char *SKGetTypeEncoding(Class aClass, SEL aSelector, BOOL
isInstance) {
Method method = SK_class_getMethod(aClass, aSelector, isInstance);
return method ? SK_method_getTypeEncoding(method) : NULL;
}
+#pragma mark API
+
@implementation NSObject (SKExtensions)
+ (IMP)setMethod:(IMP)anImp typeEncoding:(const char *)types
forSelector:(SEL)aSelector {
@@ -178,4 +215,16 @@
return SKSetMethodImplementation(self, aSelector, [self
instanceMethodForSelector:impSelector], SKGetTypeEncoding(self, impSelector,
YES), YES);
}
++ (void)exchangeMethodForSelector:(SEL)aSelector1
withMethodForSelector:(SEL)aSelector2 {
+ SKExchangeMethodImplementations(self, aSelector1, aSelector2, NO);
+}
+
+- (void)exchangeMethodForSelector:(SEL)aSelector1
withMethodForSelector:(SEL)aSelector2 {
+ [[self class] exchangeInstanceMethodForSelector:aSelector1
withInstanceMethodForSelector:aSelector2];
+}
+
++ (void)exchangeInstanceMethodForSelector:(SEL)aSelector1
withInstanceMethodForSelector:(SEL)aSelector2 {
+ SKExchangeMethodImplementations(self, aSelector1, aSelector2, YES);
+}
+
@end
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Skim-app-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/skim-app-commit