lauNchD
12-19-2008, 08:24 AM
Introduction
I found out a new way to modify/override Objective-C classes! It's (in my opinion) a lot simpler than MobileSubstrate (but is probably worse on the performance aspect) because we can simply make a subclass of any class and redirect all calls to the (super)class to the subclass. In addition, you can easily use it in your SDK apps internally (for instance for debugging purposes), or make a dylib loadable by MobileSubstrate.
Tutorial
Sounds complicated, huh? Actually, it's easy! Let me show you by creating a simple subclass of NSObject that prints out a log message every time an instance is initialized and deallocated. Then, we will make it pose as NSObject.
@interface VerboseObject : NSObject
{ /* You CANNOT set any new instance variables! Posing will FAIL and your app will CRASH! If you need to store temporary data somewhere, use static class-level variables or some shared instance of NS(Mutable)Dictionary */ }
@end
@implementation VerboseObject
- (id) init
{
if (self = [super init])
NSLog(@"Object %@ initializing!", self); // an NSLogged NSObject is displayed with its address and class name, an NSString is displayed with its contents
return self;
}
- (void) dealloc
{
NSLog(@"Deallocating object %@ !", self);
[super dealloc];
}
@end
If you're halfway experienced, nothing new here! But what's the point? How do you pose? By adding this simple line:
[VerboseObject poseAsClass: [NSObject class]];You should add this in before the class is used, probably as one of the first things into your main() function or dylib inititializer. After this line of code, every NSObject subclass will be a VerboseObject subclass. As you know, in a full-fledged application, many objects/instances inheriting from NSObject are created, and together they all will spam your log :p! (Talk about thousands of messages...)
NOTES
This tutorial is just a proof of concept. Actually, it's a stupid idea to pose in place of NSObject, but it could be useful for debugging. This works for nearly any class, so you could also override SpringBoard classes with this (as done by QuickGold, SBSettings, ...).
A few things to keep in mind if you want to pose:
You need to make a direct/concrete subclass pose as its superclass.
You can't declare any new ivars! Since we need to make Objective-C believe that the subclass actually is the superclass, it can't take up more memory than it's supposed to.
Do NOT try to pose while your app is already up and running. It'll cause a great amount of confusion, since you can't just change the class of an instance when it's already been initialized. Put the posing code in your main() function or initializer before UIApplicationMain()!
I hope this could help some of you!
Cheers,
lauNchD.
(Ihr könnt auch auf Deutsch antworten wenn ihr wollt...) ;)
I found out a new way to modify/override Objective-C classes! It's (in my opinion) a lot simpler than MobileSubstrate (but is probably worse on the performance aspect) because we can simply make a subclass of any class and redirect all calls to the (super)class to the subclass. In addition, you can easily use it in your SDK apps internally (for instance for debugging purposes), or make a dylib loadable by MobileSubstrate.
Tutorial
Sounds complicated, huh? Actually, it's easy! Let me show you by creating a simple subclass of NSObject that prints out a log message every time an instance is initialized and deallocated. Then, we will make it pose as NSObject.
@interface VerboseObject : NSObject
{ /* You CANNOT set any new instance variables! Posing will FAIL and your app will CRASH! If you need to store temporary data somewhere, use static class-level variables or some shared instance of NS(Mutable)Dictionary */ }
@end
@implementation VerboseObject
- (id) init
{
if (self = [super init])
NSLog(@"Object %@ initializing!", self); // an NSLogged NSObject is displayed with its address and class name, an NSString is displayed with its contents
return self;
}
- (void) dealloc
{
NSLog(@"Deallocating object %@ !", self);
[super dealloc];
}
@end
If you're halfway experienced, nothing new here! But what's the point? How do you pose? By adding this simple line:
[VerboseObject poseAsClass: [NSObject class]];You should add this in before the class is used, probably as one of the first things into your main() function or dylib inititializer. After this line of code, every NSObject subclass will be a VerboseObject subclass. As you know, in a full-fledged application, many objects/instances inheriting from NSObject are created, and together they all will spam your log :p! (Talk about thousands of messages...)
NOTES
This tutorial is just a proof of concept. Actually, it's a stupid idea to pose in place of NSObject, but it could be useful for debugging. This works for nearly any class, so you could also override SpringBoard classes with this (as done by QuickGold, SBSettings, ...).
A few things to keep in mind if you want to pose:
You need to make a direct/concrete subclass pose as its superclass.
You can't declare any new ivars! Since we need to make Objective-C believe that the subclass actually is the superclass, it can't take up more memory than it's supposed to.
Do NOT try to pose while your app is already up and running. It'll cause a great amount of confusion, since you can't just change the class of an instance when it's already been initialized. Put the posing code in your main() function or initializer before UIApplicationMain()!
I hope this could help some of you!
Cheers,
lauNchD.
(Ihr könnt auch auf Deutsch antworten wenn ihr wollt...) ;)
