Typhoon:为Cocoa和CocoaTouch打造的强大依赖注入框架

Typhoon:为Cocoa和CocoaTouch打造的强大依赖注入框架

【免费下载链接】typhoon Powerful dependency injection for Objective-C ✨✨ (https://PILGRIM.PH is the pure Swift successor to Typhoon!!)✨✨ 【免费下载链接】typhoon 项目地址: https://gitcode.com/gh_mirrors/ty/typhoon

引言:依赖注入的现代解决方案

还在为iOS/macOS应用中的对象依赖管理而头疼吗?面对复杂的对象关系网、难以维护的初始化代码和脆弱的单元测试,传统的手动依赖管理方式已经无法满足现代应用开发的需求。Typhoon作为专为Cocoa和CocoaTouch生态系统设计的依赖注入框架,提供了轻量级但功能完整的解决方案,让您的应用架构更加清晰、可测试和可维护。

通过本文,您将获得:

  • ✅ Typhoon核心概念和工作原理的深入理解
  • ✅ 多种依赖注入方式的实战示例
  • ✅ 与Storyboard、Core Data等技术的集成指南
  • ✅ 测试驱动开发的最佳实践
  • ✅ 从传统模式迁移到依赖注入的平滑路径

Typhoon框架概述

什么是Typhoon?

Typhoon是一个基于Objective-C运行时(Runtime)的依赖注入框架,专门为Cocoa和CocoaTouch平台设计。它利用Objective-C的动态特性自动收集元数据并实例化对象,为iOS和macOS应用提供强大的依赖管理能力。

mermaid

核心特性对比

特性Typhoon手动依赖管理其他DI框架
自动依赖解析
编译时安全检查
Storyboard集成
运行时配置
轻量级
学习曲线平缓陡峭陡峭

核心概念解析

Assembly(装配器)

Assembly是Typhoon的核心概念,它是一个声明式描述应用架构的类,定义了组件之间的协作关系。

// 示例:用户服务装配器
@interface UserServiceAssembly : TyphoonAssembly

- (UserService *)userService;
- (UserRepository *)userRepository;
- (NetworkManager *)networkManager;

@end

@implementation UserServiceAssembly

- (UserService *)userService {
    return [TyphoonDefinition withClass:[UserService class] 
        configuration:^(TyphoonDefinition *definition) {
        [definition injectProperty:@selector(repository) 
                         with:[self userRepository]];
        [definition injectProperty:@selector(networkManager) 
                         with:[self networkManager]];
        definition.scope = TyphoonScopeSingleton;
    }];
}

- (UserRepository *)userRepository {
    return [TyphoonDefinition withClass:[UserRepository class]];
}

- (NetworkManager *)networkManager {
    return [TyphoonDefinition withClass:[NetworkManager class] 
        configuration:^(TyphoonDefinition *definition) {
        definition.scope = TyphoonScopeSingleton;
    }];
}

@end

Definition(定义)

Definition描述了如何创建和配置组件实例,支持多种配置选项:

mermaid

实战:多种注入方式详解

1. 属性注入(Property Injection)

- (DataManager *)dataManager {
    return [TyphoonDefinition withClass:[DataManager class] 
        configuration:^(TyphoonDefinition *definition) {
        [definition injectProperty:@selector(database) 
                         with:[self database]];
        [definition injectProperty:@selector(cache) 
                         with:[self cacheManager]];
        [definition injectProperty:@selector(apiClient) 
                         with:[self apiClient]];
    }];
}

2. 初始化器注入(Initializer Injection)

- (APIClient *)apiClient {
    return [TyphoonDefinition withClass:[APIClient class] 
        configuration:^(TyphoonDefinition *definition) {
        [definition useInitializer:@selector(initWithBaseURL:timeout:) 
                        parameters:^(TyphoonMethod *initializer) {
            [initializer injectParameterWith:[NSURL URLWithString:@"https://api.example.com"]];
            [initializer injectParameterWith:@(30)];
        }];
    }];
}

3. 方法注入(Method Injection)

- (NotificationService *)notificationService {
    return [TyphoonDefinition withClass:[NotificationService class] 
        configuration:^(TyphoonDefinition *definition) {
        [definition injectMethod:@selector(setUserDefaults:) 
                      parameters:^(TyphoonMethod *method) {
            [method injectParameterWith:[NSUserDefaults standardUserDefaults]];
        }];
        definition.scope = TyphoonScopeSingleton;
    }];
}

高级特性与应用场景

作用域管理(Scoping)

Typhoon提供多种作用域来控制对象的生命周期:

typedef NS_ENUM(NSUInteger, TyphoonScope) {
    TyphoonScopePrototype,      // 每次获取新实例
    TyphoonScopeSingleton,      // 单例模式
    TyphoonScopeWeakSingleton,  // 弱引用单例
    TyphoonScopeObjectGraph,    // 对象图内单例
    TyphoonScopeLazySingleton   // 懒加载单例
};

运行时参数注入

- (ViewController *)viewControllerWithID:(NSString *)viewControllerID {
    return [TyphoonDefinition withClass:[ViewController class] 
        configuration:^(TyphoonDefinition *definition) {
        [definition useInitializer:@selector(initWithViewControllerID:) 
                        parameters:^(TyphoonMethod *initializer) {
            [initializer injectParameterWith:TyphoonRuntimeArgumentForKey(@"viewControllerID")];
        }];
    }];
}

与Storyboard集成

// Storyboard装配器
@interface StoryboardAssembly : TyphoonAssembly

- (UIStoryboard *)mainStoryboard;
- (ViewController *)viewControllerFromStoryboard;

@end

@implementation StoryboardAssembly

- (UIStoryboard *)mainStoryboard {
    return [TyphoonDefinition withClass:[TyphoonStoryboard class] 
        configuration:^(TyphoonDefinition *definition) {
        [definition useInitializer:@selector(storyboardWithName:factory:bundle:) 
                        parameters:^(TyphoonMethod *initializer) {
            [initializer injectParameterWith:@"Main"];
            [initializer injectParameterWith:self];
            [initializer injectParameterWith:[NSBundle mainBundle]];
        }];
    }];
}

- (ViewController *)viewControllerFromStoryboard {
    return [TyphoonDefinition withFactory:[self mainStoryboard] 
                               selector:@selector(instantiateViewControllerWithIdentifier:) 
                            parameters:^(TyphoonMethod *method) {
        [method injectParameterWith:@"MainViewController"];
    }];
}

@end

测试驱动开发实践

单元测试中的依赖注入

// 测试用例示例
- (void)testUserServiceAuthentication {
    // 创建测试装配器
    TestUserServiceAssembly *testAssembly = [TestUserServiceAssembly assembly];
    
    // 替换真实依赖为模拟对象
    TyphoonPatcher *patcher = [TyphoonPatcher new];
    [patcher patchDefinitionWithKey:@"networkManager" 
                  withObject:[[MockNetworkManager alloc] init]];
    
    [testAssembly attachDefinitionPostProcessor:patcher];
    testAssembly = [testAssembly activated];
    
    // 获取测试实例
    UserService *userService = [testAssembly userService];
    
    // 执行测试
    XCTestExpectation *expectation = [self expectationWithDescription:@"Authentication should succeed"];
    [userService authenticateWithUsername:@"test" password:@"password" completion:^(BOOL success, NSError *error) {
        XCTAssertTrue(success);
        XCTAssertNil(error);
        [expectation fulfill];
    }];
    
    [self waitForExpectationsWithTimeout:5 handler:nil];
}

模拟对象配置

// 模拟网络管理器
@interface MockNetworkManager : NetworkManager
@property (nonatomic, strong) NSMutableArray *requestLogs;
@property (nonatomic, strong) NSData *mockResponseData;
@property (nonatomic, assign) NSInteger mockStatusCode;
@end

@implementation MockNetworkManager

- (instancetype)init {
    self = [super init];
    if (self) {
        _requestLogs = [NSMutableArray array];
        _mockStatusCode = 200;
    }
    return self;
}

- (void)sendRequest:(NSURLRequest *)request completion:(void (^)(NSData *, NSHTTPURLResponse *, NSError *))completion {
    [self.requestLogs addObject:request];
    
    // 返回模拟响应
    NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:request.URL 
                                                              statusCode:self.mockStatusCode 
                                                             HTTPVersion:@"1.1" 
                                                            headerFields:nil];
    completion(self.mockResponseData, response, nil);
}

@end

性能优化与最佳实践

内存管理策略

mermaid

循环依赖处理

// 处理循环依赖的示例
@interface CircularDependencyAssembly : TyphoonAssembly

- (ClassA *)classA;
- (ClassB *)classB;

@end

@implementation CircularDependencyAssembly

- (ClassA *)classA {
    return [TyphoonDefinition withClass:[ClassA class] 
        configuration:^(TyphoonDefinition *definition) {
        [definition injectProperty:@selector(classB) with:[self classB]];
        definition.scope = TyphoonScopePrototype;
    }];
}

- (ClassB *)classB {
    return [TyphoonDefinition withClass:[ClassB class] 
        configuration:^(TyphoonDefinition *definition) {
        [definition injectProperty:@selector(classA) with:[self classA]];
        definition.scope = TyphoonScopePrototype;
    }];
}

@end

实际项目集成指南

项目结构规划

MyApp/
├── AppDelegate.h
├── AppDelegate.m
├── Assemblies/
│   ├── CoreAssembly.h
│   ├── CoreAssembly.m
│   ├── ServiceAssembly.h
│   ├── ServiceAssembly.m
│   ├── UIAssembly.h
│   └── UIAssembly.m
├── Services/
├── Models/
└── ViewControllers/

应用启动配置

// AppDelegate.m
#import "CoreAssembly.h"
#import "ServiceAssembly.h"
#import "UIAssembly.h"

@interface AppDelegate ()
@property (nonatomic, strong) CoreAssembly *coreAssembly;
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // 初始化装配器
    self.coreAssembly = [[CoreAssembly assembly] activated];
    ServiceAssembly *serviceAssembly = [[ServiceAssembly assembly] activatedWithCollaboratingAssemblies:@[self.coreAssembly]];
    UIAssembly *uiAssembly = [[UIAssembly assembly] activatedWithCollaboratingAssemblies:@[serviceAssembly, self.coreAssembly]];
    
    // 设置根视图控制器
    UIViewController *rootViewController = [uiAssembly rootViewController];
    self.window.rootViewController = rootViewController;
    [self.window makeKeyAndVisible];
    
    return YES;
}

@end

常见问题与解决方案

问题1:循环依赖检测

// 检测循环依赖的工具方法
- (BOOL)hasCircularDependencyBetween:(Class)classA and:(Class)classB {
    TyphoonComponentFactory *factory = [self activated];
    @try {
        id instanceA = [factory componentForType:classA];
        id instanceB = [factory componentForType:classB];
        
        // 尝试相互注入
        if ([instanceA respondsToSelector:@selector(setDependency:)]) {
            [instanceA setDependency:instanceB];
        }
        if ([instanceB respondsToSelector:@selector(setDependency:)]) {
            [instanceB setDependency:instanceA];
        }
        
        return NO;
    }
    @catch (NSException *exception) {
        if ([exception.name isEqualToString:TyphoonCircularDependencyException]) {
            return YES;
        }
        @throw;
    }
}

问题2:性能监控

// 性能监控装饰器
@interface PerformanceMonitor : NSProxy
@property (nonatomic, weak) id target;
@property (nonatomic, strong) NSMutableDictionary *performanceMetrics;
@end

@implementation PerformanceMonitor

- (void)forwardInvocation:(NSInvocation *)invocation {
    NSDate *startTime = [NSDate date];
    [invocation invokeWithTarget:self.target];
    NSDate *endTime = [NSDate date];
    
    NSTimeInterval duration = [endTime timeIntervalSinceDate:startTime];
    NSString *selectorName = NSStringFromSelector(invocation.selector);
    
    @synchronized (self.performanceMetrics) {
        NSMutableArray *durations = self.performanceMetrics[selectorName] ?: [NSMutableArray array];
        [durations addObject:@(duration)];
        self.performanceMetrics[selectorName] = durations;
    }
}

@end

总结与展望

Typhoon作为Cocoa和CocoaTouch生态系统中成熟的依赖注入框架,为iOS和macOS应用开发提供了强大的架构支持。通过本文的详细讲解,您应该已经掌握了:

  1. 核心概念:Assembly、Definition、各种注入方式的作用和用法
  2. 实战技巧:属性注入、初始化器注入、方法注入的具体实现
  3. 高级特性:作用域管理、运行时参数、Storyboard集成
  4. 测试实践:单元测试中的依赖替换和模拟对象使用
  5. 性能优化:内存管理策略和循环依赖处理

随着Swift语言的普及,Typhoon团队也推出了纯Swift的继任者Pilgrim(https://pilgrim.ph),为现代Swift应用开发提供了更先进的依赖注入解决方案。对于现有的Objective-C项目,Typhoon仍然是稳定可靠的选择;对于新项目,建议评估Pilgrim框架。

依赖注入不仅仅是技术选择,更是架构哲学的体现。通过合理运用Typhoon,您可以构建出更加模块化、可测试、可维护的高质量应用。


下一步行动建议

  1. 在现有项目中挑选一个模块尝试引入Typhoon
  2. 编写相应的单元测试验证依赖注入的正确性
  3. 逐步将整个应用的架构迁移到依赖注入模式
  4. 关注Pilgrim框架的发展,为Swift迁移做准备

希望本文能为您的iOS/macOS开发之旅提供有价值的参考和指导!

【免费下载链接】typhoon Powerful dependency injection for Objective-C ✨✨ (https://PILGRIM.PH is the pure Swift successor to Typhoon!!)✨✨ 【免费下载链接】typhoon 项目地址: https://gitcode.com/gh_mirrors/ty/typhoon

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值