Permalink
Browse files

Fleshed out interface for custom initializer support

  • Loading branch information...
1 parent 31a4272 commit 78ebafbc457f2f93c98d96cdbc5e1d6b6fd3e736 @thestoics thestoics committed May 19, 2012
@@ -199,6 +199,10 @@
4B4258DC13F56F45006BC001 /* JSObjectionModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B957EC512ADE03900CBF1EB /* JSObjectionModule.m */; };
4B4258DD13F56F45006BC001 /* JSObjection.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B9D310213DF613500C81C45 /* JSObjection.m */; };
4B4258DF13F56F51006BC001 /* OCHamcrest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B4258DE13F56F51006BC001 /* OCHamcrest.framework */; };
+ 4B4289311567F3EC004F73D3 /* InitializerSpecs.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B4289301567F3EC004F73D3 /* InitializerSpecs.m */; };
+ 4B4289321567F3EC004F73D3 /* InitializerSpecs.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B4289301567F3EC004F73D3 /* InitializerSpecs.m */; };
+ 4B428935156806E6004F73D3 /* InitializerFixtures.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B428934156806E6004F73D3 /* InitializerFixtures.m */; };
+ 4B428936156806E6004F73D3 /* InitializerFixtures.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B428934156806E6004F73D3 /* InitializerFixtures.m */; };
4B496E6C12B0F3E50053F2A3 /* JSObjectionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B496E6A12B0F3E50053F2A3 /* JSObjectionUtils.m */; };
4B496E6D12B0F3E50053F2A3 /* JSObjectionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B496E6A12B0F3E50053F2A3 /* JSObjectionUtils.m */; };
4B4B21A41342B78E00833077 /* JSObjectionEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B4B21A31342B78E00833077 /* JSObjectionEntry.h */; };
@@ -453,6 +457,9 @@
4B42588013F56EA3006BC001 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
4B42588213F56EA3006BC001 /* Specs-OSX-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Specs-OSX-Prefix.pch"; sourceTree = "<group>"; };
4B4258DE13F56F51006BC001 /* OCHamcrest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OCHamcrest.framework; path = Vendor/OCHamcrest.framework; sourceTree = "<group>"; };
+ 4B4289301567F3EC004F73D3 /* InitializerSpecs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InitializerSpecs.m; sourceTree = "<group>"; };
+ 4B428933156806E6004F73D3 /* InitializerFixtures.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InitializerFixtures.h; sourceTree = "<group>"; };
+ 4B428934156806E6004F73D3 /* InitializerFixtures.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InitializerFixtures.m; sourceTree = "<group>"; };
4B496E6A12B0F3E50053F2A3 /* JSObjectionUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSObjectionUtils.m; sourceTree = "<group>"; };
4B4B21A31342B78E00833077 /* JSObjectionEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSObjectionEntry.h; sourceTree = "<group>"; };
4B4B21A71342B79E00833077 /* JSObjectionEntry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSObjectionEntry.m; sourceTree = "<group>"; };
@@ -825,6 +832,7 @@
4BF451E21291AD28006EB2D5 /* InjectionErrorsSpecs.m */,
4B7300D712AA8F3400903427 /* InheritanceSpecs.m */,
4B95819612AE593F00CBF1EB /* ModuleUsageSpecs.m */,
+ 4B4289301567F3EC004F73D3 /* InitializerSpecs.m */,
);
path = Specs;
sourceTree = "<group>";
@@ -842,6 +850,8 @@
4B53482E12F31E93000480AB /* SpecHelper.m */,
4B81F90B135D0ACF00221A88 /* ModuleFixtures.h */,
4B81F90C135D0ACF00221A88 /* ModuleFixtures.m */,
+ 4B428933156806E6004F73D3 /* InitializerFixtures.h */,
+ 4B428934156806E6004F73D3 /* InitializerFixtures.m */,
);
name = Helpers;
sourceTree = "<group>";
@@ -1167,6 +1177,8 @@
4BE78764145647EF00BD705E /* JSObjectFactory.m in Sources */,
D2AAC07E0554694100DB5193 /* CircularDependencySpecs.m in Sources */,
D2AAC07E0554694100DB5196 /* CircularDependencyFixtures.m in Sources */,
+ 4B4289311567F3EC004F73D3 /* InitializerSpecs.m in Sources */,
+ 4B428935156806E6004F73D3 /* InitializerFixtures.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1261,6 +1273,8 @@
4BE78765145647EF00BD705E /* JSObjectFactory.m in Sources */,
D2AAC07E0554694100DB5194 /* CircularDependencySpecs.m in Sources */,
D2AAC07E0554694100DB5197 /* CircularDependencyFixtures.m in Sources */,
+ 4B4289321567F3EC004F73D3 /* InitializerSpecs.m in Sources */,
+ 4B428936156806E6004F73D3 /* InitializerFixtures.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -10,5 +10,5 @@
- (id)initWithContext:(NSDictionary *)theGlobalContext;
- (id)initWithContext:(NSDictionary *)theGlobalContext andModule:(JSObjectionModule *)theModule;
- (id)initWithContext:(NSDictionary *)theGlobalContext andModules:(NSArray *)modules;
-- (id)getObject:(id)classOrProtocol;
+- (id)getObject:(id)classOrProtocol, ...;
@end
@@ -68,7 +68,7 @@ - (id)initWithContext:(NSDictionary *)theGlobalContext andModules:(NSArray *)mod
}
-- (id)getObject:(id)classOrProtocol {
+- (id)getObject:(id)classOrProtocol, ... {
@synchronized(self) {
if (!classOrProtocol) {
return nil;
View
@@ -7,12 +7,13 @@ typedef enum {
} JSObjectionType;
typedef struct objection_property_info {
- void *value;
- JSObjectionType type;
+ void *value;
+ JSObjectionType type;
} JSObjectionPropertyInfo;
extern const struct JSObjectionUtils {
- JSObjectionPropertyInfo (*findClassOrProtocolForProperty)(objc_property_t property);
- objc_property_t (*propertyForClass)(Class klass, NSString *propertyName);
- NSSet* (*buildDependenciesForClass)(Class klass, NSSet *requirements);
+ JSObjectionPropertyInfo (*findClassOrProtocolForProperty)(objc_property_t property);
+ objc_property_t (*propertyForClass)(Class klass, NSString *propertyName);
+ NSSet* (*buildDependenciesForClass)(Class klass, NSSet *requirements);
+ NSDictionary* (*buildInitializer)(SEL selector, NSArray *arguments);
} JSObjectionUtils;
View
@@ -41,8 +41,7 @@ static JSObjectionPropertyInfo FindClassOrProtocolForProperty(objc_property_t pr
return propertyInfo;
}
-static NSSet* BuildDependenciesForClass(Class klass, NSSet *requirements)
-{
+static NSSet* BuildDependenciesForClass(Class klass, NSSet *requirements) {
Class superClass = class_getSuperclass([klass class]);
if([superClass respondsToSelector:@selector(objectionRequires)]) {
NSSet *parentsRequirements = [superClass performSelector:@selector(objectionRequires)];
@@ -53,8 +52,11 @@ static JSObjectionPropertyInfo FindClassOrProtocolForProperty(objc_property_t pr
return requirements;
}
-static objc_property_t GetProperty(Class klass, NSString *propertyName)
-{
+static NSDictionary* BuildInitializer(SEL selector, NSArray *defaultArguments) {
+ return nil;
+}
+
+static objc_property_t GetProperty(Class klass, NSString *propertyName) {
objc_property_t property = class_getProperty(klass, (const char *)[propertyName UTF8String]);
if (property == NULL) {
@throw [NSException exceptionWithName:JSObjectionException reason:[NSString stringWithFormat:@"Unable to find property declaration: '%@'", propertyName] userInfo:nil];
@@ -65,5 +67,6 @@ static objc_property_t GetProperty(Class klass, NSString *propertyName)
const struct JSObjectionUtils JSObjectionUtils = {
.findClassOrProtocolForProperty = FindClassOrProtocolForProperty,
.propertyForClass = GetProperty,
- .buildDependenciesForClass = BuildDependenciesForClass
+ .buildDependenciesForClass = BuildDependenciesForClass,
+ .buildInitializer = BuildInitializer
};
View
@@ -14,21 +14,29 @@
#import "JSObjection.h"
#define objection_register(value) \
- + (void)initialize { \
+ + (void)initialize { \
if (self == [value class]) { \
- [JSObjection registerClass:[value class] lifeCycle: JSObjectionInstantiationRuleNormal]; \
+ [JSObjection registerClass:[value class] lifeCycle: JSObjectionInstantiationRuleNormal]; \
} \
- }
+ }
#define objection_register_singleton(value) \
- + (void)initialize { \
- if (self == [value class]) { \
+ + (void)initialize { \
+ if (self == [value class]) { \
[JSObjection registerClass:[value class] lifeCycle: JSObjectionInstantiationRuleSingleton]; \
- } \
- }
+ } \
+ }
#define objection_requires(args...) \
- + (NSSet *)objectionRequires { \
- NSSet *requirements = [NSSet setWithObjects: args, nil]; \
- return JSObjectionUtils.buildDependenciesForClass(self, requirements); \
- }
+ + (NSSet *)objectionRequires { \
+ NSSet *requirements = [NSSet setWithObjects: args, nil]; \
+ return JSObjectionUtils.buildDependenciesForClass(self, requirements); \
+ }
+
+#define objection_initializer(selectorSymbol, args...) \
+ + (NSDictionary *)objectionInitializer { \
+ id objs[]= {args}; \
+ NSArray *defaultArguments = [NSArray arrayWithObjects: objs count:sizeof(objs)/sizeof(id)]; \
+ return JSObjectionUtils.buildInitializer(@selector(selectorSymbol), defaultArguments); \
+ }
+
@@ -0,0 +1,23 @@
+#import <Foundation/Foundation.h>
+#import "SpecHelper.h"
+#import "Fixtures.h"
+
+@interface ViewController : NSObject
+@property (nonatomic, retain) Car *car;
+@property (nonatomic, copy) NSString *nibName;
+@property (nonatomic, copy) NSBundle *bundle;
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
+@end
+
+@interface ConfigurableCar : NSObject
+@property (nonatomic, retain) Car *car;
+@property (nonatomic, retain) Engine *engine;
+
+@property (nonatomic, copy) NSString *model;
+@property (nonatomic, copy) NSNumber *horsePower;
+@property (nonatomic, copy) NSNumber *year;
+
+- (id)initWithModel:(NSString *)model horsePower:(NSNumber *)horsePower andYear:(NSNumber *)year;
+@end
+
@@ -0,0 +1,54 @@
+#import "InitializerFixtures.h"
+
+@implementation ViewController
+objection_register(ViewController)
+objection_requires(@"car")
+objection_initializer(initWithNibName:bundle:, @"MyNib")
+
+@synthesize car = _car;
+@synthesize nibName = _nibName;
+@synthesize bundle = _bundle;
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+ if ((self = [super init])) {
+ self.nibName = nibNameOrNil;
+ self.bundle = nibBundleOrNil;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [_nibName release];
+ [_car release];
+ [super dealloc];
+}
+@end
+
+@implementation ConfigurableCar
+objection_register(ConfigurableCar)
+objection_requires(@"car", @"engine")
+objection_initializer(initWithModel:horsePower:andYear:)
+
+@synthesize car = _car;
+@synthesize engine = _engine;
+
+@synthesize horsePower = _horsePower;
+@synthesize model = _model;
+@synthesize year = _year;
+
+- (id)initWithModel:(NSString *)model horsePower:(NSNumber *)horsePower andYear:(NSNumber *)year {
+ if ((self = [super init])) {
+ self.model = model;
+ self.horsePower = horsePower;
+ self.year = year;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [_model release];
+ [_horsePower release];
+ [_year release];
+ [super dealloc];
+}
+@end
View
@@ -0,0 +1,31 @@
+#import "SpecHelper.h"
+#import "InitializerFixtures.h"
+
+SPEC_BEGIN(InitializerSpecs)
+__block JSObjectionInjector *injector = nil;
+
+beforeEach(^{
+ injector = [JSObjection createInjector];
+});
+
+it(@"instantiates the object with the default initializer arguments", ^{
+ ViewController *controller = [injector getObject:[ViewController class]];
+
+ [[controller.nibName should] equal:@"MyNib"];
+ assertThat(controller.bundle, nilValue());
+ [[controller.car should] beMemberOfClass:[Car class]];
+});
+
+it(@"will override the default arguments if arguments are passed to the injector", ^{
+ ViewController *controller = [injector getObject:[ViewController class], @"AnotherNib", @"pretendBundle", nil];
+
+ [[controller.nibName should] equal:@"MyNib"];
+ [[controller.bundle should] equal:@"pretendBundle"];
+ [[controller.car should] beMemberOfClass:[Car class]];
+});
+
+it(@"is happy to instantiate an object with a number of initializer arguments", ^{
+
+});
+
+SPEC_END

0 comments on commit 78ebafb

Please sign in to comment.