{"id":13610251,"url":"https://github.com/atomicobject/objection","last_synced_at":"2025-05-15T04:05:09.980Z","repository":{"id":1220752,"uuid":"1138536","full_name":"atomicobject/objection","owner":"atomicobject","description":"A lightweight dependency injection framework for Objective-C","archived":false,"fork":false,"pushed_at":"2017-09-25T14:19:26.000Z","size":8899,"stargazers_count":1843,"open_issues_count":21,"forks_count":223,"subscribers_count":88,"default_branch":"develop","last_synced_at":"2025-05-14T00:48:52.804Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://www.objection-framework.org","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/atomicobject.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-12-04T17:44:37.000Z","updated_at":"2025-05-09T09:29:19.000Z","dependencies_parsed_at":"2022-07-06T12:41:10.587Z","dependency_job_id":null,"html_url":"https://github.com/atomicobject/objection","commit_stats":null,"previous_names":[],"tags_count":47,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomicobject%2Fobjection","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomicobject%2Fobjection/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomicobject%2Fobjection/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomicobject%2Fobjection/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atomicobject","download_url":"https://codeload.github.com/atomicobject/objection/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254264737,"owners_count":22041791,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T19:01:42.927Z","updated_at":"2025-05-15T04:05:04.967Z","avatar_url":"https://github.com/atomicobject.png","language":"Objective-C","readme":"[![Build Status](https://travis-ci.org/atomicobject/objection.png)](https://travis-ci.org/atomicobject/objection)\n\n## Description\n\nObjection is a lightweight dependency injection framework for Objective-C for MacOS X and iOS. For those of you that have used [Guice](http://code.google.com/p/google-guice/), Objection will feel familiar. Objection was built to stay out of your way and alleviate the need to maintain a large XML container or manually construct objects.\n\n## Features\n\n* \"Annotation\" Based Dependency Injection\n* Seamless support for integrating custom and external dependencies\n  * Custom Object Providers\n  * Meta Class Bindings\n  * Protocol Bindings\n  * Instance Bindings\n  * Named Bindings\n* Lazily instantiates dependencies\n* Eager Singletons\n* Initializer Support\n  * Default and custom arguments\n\n## Using Objection\n\nFor questions, visit the [mailing list](https://groups.google.com/forum/?fromgroups#!forum/objection-framework)\n### Basic Usage\n\nA class can be registered with objection using the macros *objection_register* (optional) or *objection_register_singleton*. The *objection_requires* macro can be used to declare what dependencies objection should provide to all instances it creates of that class. *objection_requires* can be used safely with inheritance.\n\n#### Example\n```objective-c\n@class Engine, Brakes;\n\n@interface Car : NSObject\n{\n  Engine *engine;\n  Brakes *brakes;\n  BOOL awake;  \n}\n\n// Will be filled in by objection\n@property(nonatomic, strong) Engine *engine;\n// Will be filled in by objection\n@property(nonatomic, strong) Brakes *brakes;\n@property(nonatomic) BOOL awake;\n\n@implementation Car\nobjection_requires(@\"engine\", @\"brakes\")\n@synthesize engine, brakes, awake;\n@end\n```\n#### Defining dependencies with selectors\n\nYou can alternatively use selectors to define dependencies. The compiler will generate a warning if a given selector is not visible or cannot be found.\n\n#### Example\n\n```objective-c\n@implementation Car\nobjection_requires_sel(@selector(engine), @selector(brakes))\n@synthesize engine, brakes, awake;\n@end\n```\n\n### Fetching Objects from Objection\n\nAn object can be fetched from objection by creating an injector and then asking for an instance of a particular class or protocol. An injector manages its own object context. Which means that a singleton is per injector and is not necessarily a *true* singleton.\n\n```objective-c\n- (void)someMethod {\n  JSObjectionInjector *injector = [JSObjection createInjector];\n  id car = [injector getObject:[Car class]];\n}\n```\n\nA default injector can be registered with Objection which can be used throughout your application or library.\n\n```objective-c    \n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    \n  JSObjectionInjector *injector = [JSObjection createInjector];\n  [JSObjection setDefaultInjector:injector];\n}\n\n- (void)viewDidLoad {\n  id myModel = [[JSObjection defaultInjector] getObject:[MyModel class]];\n}\n```\n\n#### Injecting dependencies\n\nThere may be instances where an object is allocated outside of the injector's life cycle. If the object's class declared its dependencies using *objection_requires* an injector can satisfy its dependencies via the *injectDependencies:* method.\n\n```objective-c\n@implementation JSTableModel\nobjection_requires(@\"RESTClient\")\n- (void)awakeFromNib {\n  [[JSObjection defaultInjector] injectDependencies:self];\n}\n@end\n```\n\n#### Subscripting\n\nObjection has support for the subscripting operator to retrieve objects from the injection context.\n\n```objective-c\n- (void)someMethod {\n  JSObjectionInjector *injector = [JSObjection createInjector];\n  id car = injector[[Car class]];\n}\n```\n\n### Awaking from Objection\n\nIf an object is interested in knowing when it has been fully instantiated by objection it can implement the method\n*awakeFromObjection*.\n\n#### Example\n```objective-c\n@implementation Car\n//...\nobjection_register_singleton(Car)\n  - (void)awakeFromObjection {\n    awake = YES;\n  }\n@end  \n```  \n\n### Object Factory\n\nA class can get objects from the injector context through an object factory.\n\n### Example\n```objective-c\n@interface RequestDispatcher\n@property(nonatomic, strong) JSObjectFactory *objectFactory\n@end\n\n@implementation RequestDispatcher\n- (void)dispatch:(NSDictionary *)params\n{\n  Request *request = [self.objectFactory getObject:[Request class]];\n  request.params = params;\n  [request send];\n}\n@end\n```\n## Modules\n\nA module is a set of bindings which contributes additional configuration information to the injector. It is especially useful for integrating external depencies and binding protocols to classes or instances.\n\n#### Instance and Protocol Bindings\n\n* Bind a protocol or class to a specific instance of that type\n* Bind a class that is registered with Objection to a protocol\n\n#### Example\n```objective-c\n@interface MyAppModule : JSObjectionModule {\n  \n}\n@end\n\n@implementation MyAppModule\n- (void)configure {\n  [self bind:[UIApplication sharedApplication] toClass:[UIApplication class]];\n  [self bind:[UIApplication sharedApplication].delegate toProtocol:@protocol(UIApplicationDelegate)];\n  [self bindClass:[MyAPIService class] toProtocol:@protocol(APIService)];\n}\n\n@end\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    \n  JSObjectionInjector *injector = [JSObjection createInjector:[[MyAppModule alloc] init]];\n  [JSObjection setDefaultInjector:injector];\n}\n```\n#### Meta Class Bindings\n\nThere are times when a dependency -- usually external -- is implemented using only class methods. Objection can explicitly support binding to\nthe meta class instance through a protocol. This avoids having to unnecessarily create a wrapper class that passes through to the class\nmethods. The catch, of course, is that it requires a protocol definition so that Objection knows how to bind the meta class to objects\nin the injector context.\n\n#### Example\n```objective-c\n@protocol ExternalUtility\n  - (void)doSomething;\n@end\n\n@interface ExternalUtility\n  + (void)doSomething;\n@end\n\n@implementation ExternalUtility\n  + (void)doSomething {...}\n@end\n\n// Module Configuration\n- (void)configure {\n  [self bindMetaClass:[ExternalUtility class] toProtocol:@protocol(ExternalUtility)];    \n}\n\n@interface SomeClass\n{\n  ...\n}\n// Use 'assign' because a meta class is not subject to the normal retain/release lifecycle. \n// It will exist until the application is terminated (Class Initialization -\u003e Application Termination)\n// regardless of the number of objects in the runtime that reference it.\n@property (nonatomic, assign) id\u003cExternalUtility\u003e externalUtility\n@end\n```\n#### Providers\n\nOccasionally you'll want to manually construct an object within Objection. Providers allow you to use a custom mechanism for building objects that are bound to a type. You can create a class that _conforms_ to the ObjectionProvider protocol or you can use a _block_ to build the object.\n      \n#### Example\n```objective-c\n@interface CarProvider : NSObject \u003cJSObjectionProvider\u003e\n@end\n\n@implementation CarProvider\n- (id)provide:(JSObjectionInjector *)context arguments:(NSArray *)arguments {\n  // Manually build object\n  return car;\n}\n@end\n\n@implementation MyAppModule\n- (void)configure {\n    [self bindProvider:[[CarProvider alloc] init] toClass:[Car class]];\n    [self bindBlock:^(JSObjectionInjector *context) {\n      // Manually build object\n      return car;          \n    } toClass:[Car class]];\n}\n@end\n```\n\n### Scopes\n\nA class can be scoped as a singleton in a module. Conversely, a registered singleton can be demoted to a normal lifecycle with in the injector's context.\n\n### Example\n```objective-c\n@implementation MyAppModule\n- (void)configure {\n    [self bindClass:[Singleton class] inScope:JSObjectionScopeNormal];\n    [self bindClass:[Car class] inScope:JSObjectionScopeSingleton];\n}\n@end\n```\n\n### Named Bindings\n\nDependencies of the same class or protocol can be identified using the *objection_requires_names* macro, which takes a dictionary of names to properties as a parameter. \n\n#### Example\n```objective-c\n@interface ShinyCar : NSObject\n@property (nonatomic, strong) Headlight *leftHeadlight;\n@property (nonatomic, strong) Headlight *rightHeadlight;\n@end\n\n@implementation ShinyCar\nobjection_register(ShinyCar)\nobjection_requires_names((@{@\"LeftHeadlight\":@\"leftHeadlight\", @\"RightHeadlight\":@\"rightHeadlight\"}))\n@synthesize leftHeadlight, rightHeadlight;\n@end\n\n@implementation NamedModule\n\n- (void)configure\n{\n    [self bind:[[Headlight alloc]init] toClass:[Headlight class] named:@\"RightHeadlight\"];\n    [self bindClass:[HIDHeadlight class] toClass:[Headlight class] named:@\"LeftHeadlight\"];\n\n}\n@end\n\n```\n\n\n### Eager Singletons\n\nYou can mark registered singleton classes as eager singletons. Eager singletons will be instantiated during the creation of the injector rather than being lazily instantiated.\n\n### Example\n```objective-c\n@implementation MyAppModule\n- (void)configure {\n  [self registerEagerSingleton:[Car class]];\n}\n\n@end\n```  \n\n### Deriving a new injector from an existing injector\n\nA new injector can be created from an existing injector using the *withModule:* method. A new injector will be created containing the same bindings as the injector it was derived from. The new injector will also contain additional bindings provided by the new module. \n\nConversley, if *withoutModuleOfType:* is used the new injector will _not_ contain the bindings of the removed module.\n\n### Example\n```objective-c\ninjector = [otherInjector withModule:[[Level18Module alloc] init]] \n                          withoutModuleOfType:[Level17Module class]];\n                          \n```\n\n## Initializers\n\nBy default, Objection allocates objects with the default initializer \u003ccode\u003einit\u003c/code\u003e. If you'd like to instantiate an object with an alternate ininitializer the \u003ccode\u003eobjection_initializer\u003c/code\u003e macro can be used to do so. The macro supports passing in default arguments (scalar values are not currently supported) as well.\n      \n#### Default Arguments Example\n```objective-c\n@implementation ViewController\nobjection_initializer(initWithNibName:bundle:, @\"ViewController\")\n@end\n```\n\n####  Custom Arguments Example\n```objective-c\n@implementation ConfigurableCar\nobjection_requires(@\"engine\", @\"brakes\")\nobjection_initializer(initWithMake:model:)\n\n@synthesize make;\n@synthesize model;\n\n- (instancetype)initWithMake:(NSString *)make model:(NSString *)model {\n  ...\n}\n@end\n\n- (void)buildCar {\n  ConfigurableCar *car = [self.objectFactory getObjectWithArgs:[ConfigurableCar class], @\"VW\", @\"Passat\", nil];\n  NSLog(@\"Make: %@ Model: %@\", car.make, car.model);\n}\n```\n\n#### Class Method Initializer\n```objective-c\n@implementation Truck\nobjection_requires(@\"engine\", @\"brakes\")\nobjection_initializer(truckWithMake:model:)\n+ (instancetype)truckWithMake:(NSString *) make model: (NSString *)model {\n  ...\n}\n@end\n\n```\n\n#### Ad-Hoc Initializer\n```objective-c\n@implementation ConfigurableCar\n- (instancetype) initWithModel:(NSString *)model {\n    //....\n}\n@end\n\n- (void)buildCar {\n  ConfigurableCar *car = [self.objectFactory getObject:[ConfigurableCar class], \n                                           initializer: @selector(initWithModel:) \n                                           withArgumentList:@[@\"Passat\"]];\n}\n```\n\n## Testing\n\nIf you're using [Kiwi](https://github.com/allending/Kiwi) for testing, checkout [MSSpec](https://github.com/mindsnacks/MSSpec). It provides a convenient way inject mocks into your specs using Objection.\n\n## TODO\n\n* Add a motivation section that speaks to _why_ Objection was created\n\n## Installation\n\n### Static Framework and Linkable Framework\n\nIt can be downloaded [here](https://github.com/atomicobject/objection/releases/download/1.6.1/Objection-1.6.1.tar.gz)\n\n### Building Static Framework\n\n    git clone git://github.com/atomicobject/objection.git\n    git checkout 1.6.1\n    \n#### iOS\n\n\n1. rake artifact:ios\n2. cp -R build/Release-iphoneuniversal/Objection-iOS.framework ${DEST_DIR}\n3. In XCode -\u003e Project Icon -\u003e Your Target -\u003e Build Phases -\u003e Link Binary With Libraries -\u003e Add (+) -\u003e Add Other\n4. Add -ObjC and -all_load to Other Link Flags in your project\n\n#### Include framework\n    #import \u003cObjection-iOS/Objection.h\u003e\n\n#### MacOS X\n\n1. rake artifact:osx\n2. cp -R build/Release/Objection.framework ${DEST_DIR}\n3. In XCode -\u003e Project Icon -\u003e Your Target -\u003e Build Phases -\u003e Link Binary With Libraries -\u003e Add (+) -\u003e Add Other\n\n#### Include framework\n    #import \u003cObjection/Objection.h\u003e\n\n### CocoaPods\n\nEdit your Pofile\n\n    edit Podfile\n    pod 'Objection', '1.6.1'\n\nNow you can install Objection\n    \n    pod install\n\n#### Include framework\n    #import \u003cObjection/Objection.h\u003e\n\nLearn more at [CocoaPods](http://cocoapods.org).\n\n### Ruby Motion\n\nA companion library for Objection was created called [motion-objection](https://github.com/atomicobject/motion-objection)\n\n```bash\ngem install motion-objection\n```\n\n## Requirements\n\n* MacOS X 10.8 +\n* iOS 7.0 +\n\n## Authors\n\n* Justin DeWind (dewind@atomicobject.com, @dewind on Twitter)\n* © 2013 [Atomic Object](http://www.atomicobject.com/)\n* More Atomic Object [open source](http://www.atomicobject.com/pages/Software+Commons) projects\n\n## Other Dependency Injection Libraries\n\nOne only has to [search GitHub](https://github.com/search?l=Objective-C\u0026p=1\u0026q=dependency+injection\u0026repo=\u0026type=Repositories)\n\n## Applications that use Objection\n\n* [Bubble Island](http://www.wooga.com/games/bubble-island/)\n* [Monster World](http://www.wooga.com/games/monster-world/)\n* [Pocket Village](http://www.wooga.com/games/pocket-village/)\n* [SideReel](https://itunes.apple.com/us/app/id417270961?mt=8)\n* [Google Wallet](http://www.google.com/wallet/)\n\n","funding_links":[],"categories":["Objective-C","Objective-C  Stars 1000以内排名整理","etc"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatomicobject%2Fobjection","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatomicobject%2Fobjection","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatomicobject%2Fobjection/lists"}