Does Swift support aspect oriented programming?

The foundation of Aspect Oriented Programming is the intercept pattern. We start with a crosscutting requirement - something that needs to occur in many parts of the application. And then using a pointcut expression, modularize it, by identifying all of the places this requirement should be applied. This is done by intercepting a method call and weaving in additional behavior. Therefore, for a language to support AOP, it must support the intercept pattern.

Now, depending on the language, method interception can be applied either at compile-time, run-time or both. Swift is an interesting case in this regard, as it supports the following kinds of method dispatch:

  • Static/vtable, like C++ (faster : in tests accounted for about 1.1 nano-seconds or less of method invocation time)
  • Messaging, like Objective-C (slower : in tests accounted for about 4.9 nano-seconds of method invocation time). Also known as dynamic dispatch or late binding.

If you extend NSObject or use the @objc decoration then messaging will be used. Otherwise Swift will revert to static/vtable method invocations.

  • With the static/vtable type of dispatch, only compile-time interception is possible. In the case of C++ (and Swift) this involves using a preprocessor that generates new source, prior to actual compilation. This is a somewhat cumbersome approach and takes more effort to develop the necessary tools. Although it does give the best possible performance.
  • With the messaging style of method invocation run-time interception is also available. In fact, Objective-C made interception so easy that there was no formal AOP framework. It might've been useful, but "raw materials" were so good no one bothered to make one. Many of Cooca's best features take advantage of Objective-C's dynamic dispatch and the ability to intercept method calls.

Summary:

  • Swift will support runtime AOP if you extend NSObject or use the '@objc' decoration. There are some quirks and limitations to this - Apple's guide on using KVO with Swift will point out most of them.
  • If you don't extend an Objective-C base or use the '@objc' decoration, then only compile-time AOP will be possible. As yet there is no such library to provide compile-time AOP. Furthermore, a disadvantage of compile-time AOP is that it only works with classes that you have the source for.

NB1: Some languages, such as Java uses a static/vtable style of method dispatch and still support runtime method interception. This is possible as they rely on virtual machine, along with a class loader, another hook-in point. In fact Java is still classed as a 'late binding' language because of this.

NB2: Its technically possible to support provide compile time weaving against compiled-to-machine-code binaries with some limitations. The first is there aren't too many tools to support this because implementation effort is high, and must be repeated per-platform. The second is that it limits the available AOP features.


Unfortunately, Swift itself has no runtime support at this time. You have to rely on Objective-C bridging.

Here's a brand new AOP library for iOS, written in Objective-C, with Swift support.

https://github.com/MO-AI/MOAspects

Only 'before advice' and 'after advice' are available, but in the most cases, it's enough to solve your problem. Note that it may be required adding 'dynamic' keyword to your function, when the interception against pure Swift class/method doesn't work correctly.

MOAspects is superior to two most famous AOP library for Objective-C, Aspects and BlockInjection. Aspects doesn't support class method interception and multiple hooking into methods in class hierarchy. BlockInjection has a critical issue not to support 64-bit.

Tags:

Ios

Swift