XAspect 1.0.5

XAspect 1.0.5

测试已测试
语言语言 C++C++
许可证 MIT
发布最新发布2015年8月

Xaree Lee 维护。



XAspect 1.0.5

  • 作者
  • Kang-Yu Xaree Lee

XAspect 是一个 Objective-C 框架,用于实现面向切面编程,使代码更易于 复用维护

它提供了宏和 API,可以将您的切面实现绑定到目标 Objective-C 方法,不管您是否有源代码实现,甚至可以将 Apple 的 SDK 绑定!

XAspect 将切面逻辑(或 横切关注点)从您的项目中分离出来,并封装到独立的切面文件中。一旦程序加载完成,XAspect 将通过 方法交换 自动将这些补丁合并到您的程序中。

如果您已经了解了 XAspect,可以跳过下面的部分,直接跳转到 目录(“更多信息”部分”)

安装

(2) 手动包含源代码

您也可以简单地将 XAspect 硬件加入到您的项目中。只需将 XAspect/ 目录下的所有源文件和文件夹添加到您的项目中。

概览

使用 XAspect 的感觉就像是为源代码编写 补丁插件。通过几行代码创建一个切面上下文,您就可以开始编写补丁实现了。XAspect 将在程序加载完成后自动将这些补丁合并到您的程序中。

例如,假设您想要在每次对象初始化时记录一个消息,您需要观察 -[NSObject init] 的调用。通过 XAspect,您可以轻松地向 -[NSObject init] 添加 NSLog() 语句。

您可以通过以下方式亲自尝试:

  1. 在仓库中的 XAspectDev 项目中找到 Aspect-ObjectAllocation.m 样本代码,并取消注释 AspectPatch() 中的实现,或者

  2. 在您的项目中创建一个 Aspect-ObjectAllocation.m,并添加以下代码(您也应注意安装 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

运行程序。程序加载完成后,您将看到任何对象初始化时的消息

 [Init]: NSUserDefaults
 [Init]: NSProcessInfo
 [Init]: CFPrefsSource
 ...

您也可以向 -dealloc 添加 前置建议 来打印特定类释放的对象。

#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 旨在将切面代码与源代码实现分离,并在程序加载时重新注入。

有关 XAspect 的更多信息,请阅读 介绍文档

使用 XAspect 的好处

使用 XAspect 有一些好处:

  • 不改源码,改行文行为。 XAspect 允许您将切面实现(横切关注点)从类和源文件中解耦。这意味着当您需要修改项目中切面的功能/行为时,它遵循开闭原则(OCP)
  • 将切面实现封装在一个文件中。 XAspect 允许您在一个文件中实现切面实现的补丁。您只需专注于一个文件即可在整个项目中执行面向切面的编程。这意味着您的切面代码更加易于维护可重用。如果您需要,只需将切面文件复制到另一个项目中,稍作修改即可简单重用它们。
  • 易于版本控制。 由于封装,一个切面的更改被封装在一个文件中,您可以提交您的切面补丁到一个文件。这意味着在您通过多个类和文件开发多个切面时,不需要分支您的源代码。
  • 通过安全类别避免替代原始实现。 XAspect 还采用了来自 libextobjc安全类别。使用安全类别,可以保证您的类别实现将成为目标选择器的唯一实现 — 它不会被其他实现替代或被替代。如果存在多个同目标选择器的实现,XAspect 将在程序加载时识别冲突。

如果以下情况适合您,则此框架适合您:

  • 您希望将一个类中的不同切面分开并放置在不同的地方。
  • 您希望将同一切面的跨类更改封装在单个文件中,以简化维护、代码审查和版本控制。这可能降低维护成本。
  • 您同时开发多个切面。您希望解耦它们并将它们分别封装起来以减少开发复杂性。
  • 您希望将切面(概念/功能)打包成一个文件,并使其高度可重用。
  • 您希望在不改动第三方库和您的项目的源代码的情况下,架起两者之间的实现桥梁。

缺点和限制

有一些缺点和限制。请在文档部分“缺点和限制”中阅读‘缺点和限制’

更多信息

  1. 简介
    • 什么是 XAspect:XAspect 的目标
    • 如何使用 XAspect:入门
  2. 文档
    • 切面字段和补丁字段
    • 补丁
    • 缺点和限制

关于

维护策略和开发笔记

任何帮助或贡献都欢迎使用。请阅读开发笔记以找到您可以帮忙的内容。

作者

  • Xaree Lee(李冈諭,Kang-Yu Lee),来自台湾的 iOS 开发者。

许可

XAspect 可在 MIT 许可下使用。有关更多信息,请参阅LICENSE 文件。