Is there any Aspect-Oriented Objective-C library that I could perhaps use for iPhone development?
-
4+1 for total madness, isn't this stuff hard enough already. – Gareth Davis Jan 09 '11 at 20:54
-
5@gareth-davis If AOP done right, it simplifies a lot of tasks a typical iOS developer encounter in most of his projects. – Jens Kohl Sep 08 '11 at 08:42
-
@DASKAjA just being (mostly) flippant – Gareth Davis Sep 08 '11 at 13:55
11 Answers
There is an old project called AspectCocoa, this might be what you are searching for.
Otherwise Í would suggest rolling your own. Either proxy based AOP by subclassing NSProxy
for a change. Or you could do some method swizzling with the quite cool Obj-C run-time function method_exchangeImplementations()
.
But unless you are looking for a fun exercise, ask yourself what you want to achieve, and if there is an existing perfectly working Objective-C way to do it.

- 36,742
- 12
- 80
- 99
-
2There's a **warning** on the linked website: AspectCocoa leaks memory, leads to oversized binaries, and generally is not a reliable production quality piece of software (it's best used for debugging and inspection, and then removed before compiling the final version of your software). – Jens Kohl Sep 08 '11 at 08:39
-
The link provided above didn't work for me. You can find it at:[link](http://cocoadev.com/AspectCocoa) – Apan Sep 11 '14 at 16:14
Check out my article about a possible solution: http://codeshaker.blogspot.com/2012/01/aop-delivered.html
The base idea is to make a hook into the message sending mechanism and force it to the message forwarding route:
So A brief explanation about how it works:
At registration of a method call of a specific class it creates a method wrapper (AOPMethod) object and stores every information in it about that specific method along with the block that will be used upon interception.
Changes the implementation of the method to _objc_msgForward or _objc_msgForward_stret respectively using method_setImplementation. This is the point where we route message sending to the forwarding mechanism. The next time the message is called on the base class, it will return the _objc_msgForward implementation as if it not found the implementation. So it starts to resolve it by going through the message forwarding steps. Nice.
We add the forwardingTargetForSelector: method to the base class using class_addMethod to point to our implementation in the AOPAspect class. Also we add the original method implementation and selector (with an extended name to prevent conflicts between classes) to our AOPAspect instance.
In the forwardingTargetForSelector: method we give back our AOPAspect instance. With this we route the message forwarding from the base object to our AOPAspect object.
This forwardingTargetForSelector: method will be called again on AOPAspect as we don't have that selector implemented. This case we return nil, so message forwarding steps further and will check for the methodSignatureForSelector: and forwardInvocation: methods on AOPAspect.
In methodSignatureForSelector: we gave back the correct message signature that is already stored in a dictionary in a method wrapper object.
At the time it arrives to our implementation of forwardInvocation: in AOPAspect we have a fully configured NSInvocation instance and the only thing we have to do is to change the selector to the extended version we added to AOPAspect class. Here we can run the blocks registered for the given method before/after or even instead of the method call. And of course we can run the original method by calling [anInvocation invoke].
For simplicity, we just pass the NSInvocation object to the blocks registered for the method, so they can access all arguments and the return value as well through the getArgument:atIndex: and getReturnValue: methods.
And that's it. It works with all kind of return types, argument types and any variation of arguments.
You can find the concrete example on the above link. Please feel free to use it.

- 366
- 3
- 6
-
http://meta.stackexchange.com/questions/94022/how-can-i-link-to-an-external-resource-in-a-community-friendly-way – Matt Jan 23 '12 at 12:00
-
Edited as requested. I have added the main idea behind it, with it it can be reimplemented easily. – Andras Jan 23 '12 at 12:43
-
@andras Your AOP repo looks nice, very short, simple. You haven't had any commits in a while, does that suggest it's stable enough for production? I'm interested in trying it on something like http://stackoverflow.com/q/16403621/136582 – Greg Combs May 06 '13 at 17:21
The question is old but I discovered this project today and it might be helpful to someone in the future.

- 934
- 6
- 15
Also you might want to check out the library at https://github.com/moszi/AOP-in-Objective-C which is a very simple NSProxy subclass allowing you to intercept the beginning and the end of the method calls.
With this you can even create a proxy class for you objects to make sure messages sent to your object are serialized over one single thread, regardless of the invoking thread.

- 3,236
- 2
- 22
- 20
Check out this one https://github.com/pvantrepote/FlexOC It's an alpha version and uses (for now) the Proxy implementation. It does also dependency injections.

- 11
- 1
All still interested people should take a look at https://github.com/mgebele/MGAOP
This seems to be a new project with future potential.

- 11
- 1
I made some rudimentary aop pre and post process function on an NSObject category
@implementation NSObject (AOP)
- (void)preprocess:(SEL)sel with:(void (^)(id obj, id param))implementingBlock{
Method m1 = class_getInstanceMethod(self.class, sel);
IMP imp1 = method_getImplementation(m1);
SEL replacement = sel_registerName( [[[NSString stringWithUTF8String:sel_getName(sel)] stringByAppendingString:@"pre"] cStringUsingEncoding:NSUTF8StringEncoding]);
class_addMethod(self.class,replacement, imp1, nil);
method_setImplementation(m1, imp_implementationWithBlock(^(id x, id param){
implementingBlock(x,param);
[x performSelector:replacement withObject:param];
}));
}
- (void)postprocess:(SEL)sel with:(void (^)(id obj, id param))implementingBlock{
Method m1 = class_getInstanceMethod(self.class, sel);
IMP imp1 = method_getImplementation(m1);
SEL replacement = sel_registerName( [[[NSString stringWithUTF8String:sel_getName(sel)] stringByAppendingString:@"post"] cStringUsingEncoding:NSUTF8StringEncoding]);
class_addMethod(self.class,replacement, imp1, nil);
method_setImplementation(m1, imp_implementationWithBlock(^(id x, id param){
[x performSelector:replacement withObject:param];
implementingBlock(x,param);
}));
}
@end

- 681
- 6
- 8
I'm working on a real (it is more than method-swizzling) AOP-Framework for Objective-C. An alpha will be released soon. You can listen to my german presentation on the Macoun'09 conference here: http://www.macoun.de/video2009ts6.php
If you're still interested in AOP for Objective-C you can send me a mail to negm-awad@cocoading.de or simply visit this site: aspective-c.com/index.html in a few weeks. There will be an english version (yup, not translated by me ;-)) of the site and the manual in a few weeks.

- 16,582
- 3
- 35
- 50
https://github.com/eleme/Stinger
Stinger is a high-efficiency library with great compatibility, for aop in Objective-C, using libffi.

- 1
Another one is Aspect Objective-C: https://github.com/tomdalling/AspectObjectiveC

- 242,470
- 58
- 448
- 498
With Objective-C i would suggest to go with the here much used Category- and Delegate-Pattern. These can be more useful than AOP. Don't try and solve your problems with solutions you learned for other languages.

- 6,239
- 2
- 36
- 41
-
Categories are very AOP-ish but they have some limitations compared to traditional aspects. For example, you can't proceed() (over even call the overrided method in general). Also, categories can't hold any state. – Raffi Khatchadourian Feb 10 '12 at 14:15
-
The original method can be called with method swizzling like http://cocoadev.com/index.pl?MethodSwizzling Another option could be class posing. A category can hold arbitrary state by using an existing NSDictionary instance variable in the original class. – MacMark Feb 12 '12 at 10:14
-
All this runtime magic in ObjC looks hacky at first. For example Key-Value Observing uses szwizzling for the "isa" variable to do its work. And utilizing NSDictionary for simple data models is not unusual. – MacMark Feb 15 '12 at 17:14
-
Yes, I've noticed the (over) use of NSDictionary in Objective-C code. To me, dictionaries (and maps in general) should be used to quickly look up things and for caching. I also agree with using dictionaries to represent plist files. I really don't understand the other uses for them, e.g., using them as a data model. We have instance variables and classes for that. – Raffi Khatchadourian Feb 21 '12 at 18:22
-
Dictionary gives looser coupling than subclassing. It also gives extensibility per instance and not only per class. It delays the selection of which data to access until runtime. And it has better runtime storage efficiency. Cocoa avoids subclassing and uses lots of design patterns to do so like composites, associative storage, delegate, decorators. Compare "Cocoa Design Patterns" from Buck/Yacktman for Dictionary and patterns and "iOS Programming" from Conway/Hillegass for using Dictionary for small data models. – MacMark Feb 22 '12 at 10:20
-
And, dictionaries circumvent type safety. Since Objective-C is quite dynamic, it may be more acceptable not to use the static type checker but I personally prefer to use the type checker if it's available to me. – Raffi Khatchadourian Feb 23 '12 at 18:21
-
Objective-C does not care much about types. It only cares if an object understands (can handle) the message. In that case the type is irrelevant. You do not ask for types but for abilities of an object – like "duck typing". Thinking Objective-C is different from Java or C++ and this can make programming in Objective-C much easier and more elegant. – MacMark Feb 24 '12 at 08:33