朱海文 3e28daaec5 init | 3 years ago | |
---|---|---|
.. | ||
XAspect | 3 years ago | |
LICENSE.md | 3 years ago | |
README.md | 3 years ago |
XAspect is an Objective-C framework for Aspect-Oriented Programming to make your code more reusable and maintainable.
It provides macros and APIs for binding your aspect implementation to the target Objective-C methods whether you have the source implementation or not, even to the Apple's SDK!
XAspect decouples the aspect logic (or cross-cutting concerns) from your project and encapsulates those aspects into separated aspect files. Once the program is loaded, XAspect will automatically merge those patches into your program by method swizzling.
If you already know what XAspect is, you could skip the following sections and jump right into the table of contents (the section 'More Information').
XAspect is distributed via CocoaPods. Add this line in your Podfile and then perform $ pod install
:
pod 'XAspect'
You can also simply include XAspect in your project manually. Just add all of the source files and folders in the XAspect/
directory to your project.
Using XAspect is a little like writing patches or plugins for source code. With a couple of lines to create an aspect context, you could start writing your patch implementation. XAspect will automatically merge those patches into your program when the program finishes loading.
For example, say you want to log a message every time an object is initialized, you need to observe the invocation of -[NSObject init]
. With XAspect, You can easily add NSLog()
statements to -[NSObject init]
.
You could try this by yourself by either
Finding the following sample code in Aspect-ObjectAllocation.m in the XAspectDev project in the repository and uncommenting the AspectPatch()
implementation, or
Creating a Aspect-ObjectAllocation.m in your project and adding the following code (you should also install XAspect):
// In an aspect file you create (.m file).
#import <Foundation/Foundation.h>
#import <XAspect/XAspect.h>
// A aspect namespace for the aspect implementation field (mandatory).
#define AtAspect ObjectLifetime
// Create an aspect patch field for the class you want to add the aspect patches to.
#define AtAspectOfClass NSObject
@classPatchField(NSObject)
// Intercept the target objc message.
AspectPatch(-, instancetype, init)
{
// Add your custom implementation here.
NSLog(@"[Init]: %@", NSStringFromClass([self class]));
// Forward the message to the source implementation.
return XAMessageForward(init);
}
@end
#undef AtAspectOfClass
#undef AtAspect
Run the program. After the program has loaded, you'll see messages when any object is initialized:
...
You could also add before advice to -dealloc
to print the deallocated objects for specific classes.
#import <XAspect/XAspect.h>
#import <UIKit/UIKit.h>
// -----------------------------------------------------------------------------
#define AtAspect DeallocTracker
// -----------------------------------------------------------------------------
#define AtAspectOfClass NSObject
@classPatchField(NSObject)
AspectPatch(-, void, dealloc)
{
static NSArray *klasses;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// Add classes here which you want to track when they were deallocated.
klasses = @[[UITableView class],
[UITableViewController class],
];
});
Class klass = [self class];
if ([klasses containsObject:klass]) {
NSLog(@"--%@ <%p> dealloc", NSStringFromClass(klass), self);
}
XAMessageForwardDirectly(dealloc);
}
@end
#undef AtAspectOfClass
XAspect aims to separate aspect code from the source implementation, and inject them back when the program is loaded.
For more information about XAspect, please read the introduction and the documentation.
Using XAspect has some benefits:
There are some downsides and restrictions. Please read the section 'Downsides and Restrictions' in Documentation.
Any help or contribution is welcome. Please read the Development Notes to find what you can help.
XAspect is available under the MIT license. See the LICENSE file for more info.