jbsf / blindside Goto Github PK
View Code? Open in Web Editor NEWBlindside provides dependency injection capabilities for Objective-C on iOS and OS X
License: MIT License
Blindside provides dependency injection capabilities for Objective-C on iOS and OS X
License: MIT License
We're trying to set up a dependency graph which includes a delegate with a reference back up the graph. When we try to inject all the deps with Blindside we get an exception "Cyclic dependency found on key…".
How can we use BS to inject an object's delegate? The delegate has a weak reference to a protocol going back up the chain, so we'd expect it to be ok.
Would it be possible to add this to the official Cocoapods spec? I would like to use this as a dependency for another Pod but it needs to be 'official'.
Playing around on my machine, it should be as easy as:
1.0.0
as the version (example in my fork)1.0.0
tagpod spec lint
(should pass)pod trunk push Blindside.podspec
Thanks for considering! I would do it on my own but it would have to be under my repo. And then that pod name would be gone.
Right now it only injects the injector if an injector property conforms it only. It will fail if the injector also conforms to <BSInjector, BSBinder> or any other additional protocols.
In the case where a class has a required/designated instance initializer, and the developer hasn't yet provided a BSInitializer, Blindside should raise an appropriate exception with helpful recovery info (e.g. instructions to override +BSInitializer)
Is it possible to inject dependencies into Swift objects? Or, one step away, classes written in Swift but still inheriting from NSObject
?
I can override bsInitializer()
no problem but the "Swiftified" header for BSInitializer
shows no initializer methods. Same goes for BSPropertySet
.
Command-click on
BSPropertySet()
from a Swift file to see the header I am speaking of.
We found ourselves in a situation where we wanted to override a binding; the key was a class which had been previously bound to an instance. The world imploded.
context(@"when the key is a class which has an existing binding", ^{
it(@"should build the class without infinite recursion", ^{
[injector bind:[Address class] toInstance:[NSNull null]];
[injector bind:[Address class] toClass:[Address class]];
id address = [injector getInstance:[Address class]];
expect(address).to(be_instance_of([Address class]));
});
});
Alternatively, is there a recommended way to remove a binding to restore the default behavior? This came up in a testing scenario.
When installing Blindside 1.3.1 in my framework using cocapods 1.2.1 and then attempting to integrate my framework in the application, I get the following error:
dyld: Library not loaded: @rpath/Blindside.framework/Blindside
Referenced from: /Users/tsd036/Library/Developer/CoreSimulator/Devices/13CB5F22-8253-4D2B-A5DE-350D4C50271D/data/Containers/Bundle/Application/27786704-461A-4687-A211-BEF96D83D4DE/aaa-ace-mobile.app/Frameworks/MyFramework.framework/MyFramework
Reason: image not found
This only started happening when I upgraded to cocoapods 1.2.1 because in cocoapods 1.1.1 it allowed "use_frameworks!" to be embeded inside our swift testing target for Quick and Nimble. Cocoapods 1.2.1 requires "use_frameworks!" to also be included in the parent target which is the framework.
Given that you're writing a spec for a class under test (DogPicsViewController
)
Given that you accidentally include ImageFetcher
in your application target (DogPics
) and your test target (DogPicsSpecs
) that calls the main application it's host (DogPics
is the host application of DogPicsSpecs
)
Given than you inject a custom implementation (FakeImageFetcher
) of a dependency of the class under test into the injector
[injector bind:[ImageFetcher class] toInstance: fakeImageFetcher]
Given that you ask for an instance of that class (ImageFetcher
) in the class under test, either through bsinitializer or bsproperties
@interface DogPicsViewController
@property (strong, nonatomic) ImageFetcher *imageFetcher;
@end
When the injector goes to grab the requested ImageFetcher
for the class DogPicsViewController
while running a spec, it will initialize a new instance of ImageFetcher
even though you've faked out and bound an instance in your specs.
This happens because you've included your ImageFetcher
in both your host application and spec bundles.
To somebody who hasn't already encountered this a few times, this behavior is totally impossible to figure out ("why's it not getting the thing I just bound? Aren't these two classes equal?")
The injector should warn the user that this is happening.
For example, in the Swift
section there is a line
let controller = injector.getInstance(MyViewController.self)
which compiles, but doesn't allow you to use the variable controller
because it is an unknown type.
In order for that variable to be recognized as an instance of MyViewController
it should be
let controller = injector.getInstance(MyViewController.self) as! MyViewController
OR
let controller: MyViewController = injector.getInstance(MyViewController.self) as! MyViewController
As someone new to Swift, that bit tripped me up.
It looks like it was accidentally overwritten?
https://github.com/jbsf/blindside/blob/master/LICENSE shows a file containing the following text:
2
1
.5
1
1
2
2
2
2
1
2
1
2
3
1
2
2
.5
.5
.5
4
2
2
1
2
1
2
1
3
1
.5
This is both an RFC as well as a "todo" reminder for myself, or another enterprising contributor.
Objective-C's dynamic nature and the way Blindside interacts with it means that only a limited amount of compile-time checking can be performed on an injector's configuration and classes' dependency declarations. Additionally, runtime validity checking is performed on a just-in-time basis, resulting in the possibility of unexpected exceptions lurking behind every call to ``getInstance:`. I would propose providing opt-in ahead-of-time validity checking, available at the time of injector instantiation, after module configuration has been performed.
I imagine these checks could be run as part of an integration test suite, or even upon standard app launches for debug builds.
I've thought of the following possible checks so far:
BSInitializer
declarations refer to an available initializer method (see -[BSInitializer validate]
BSInitializer
argument keys actually exist (a key can be considered to exist if it either a) is explicitly bound in the injector, or b) is a class which Blindside can construct without binding.)BSPropertySet
declarations refer to usable properties on the class (see -[BSProperty determineReturnType]
)BSPropertySet
bindings refer to keys which actually existI would suggest that the entry point for these checks be a new method introduced on the Blindside
factory class which expands upon the existing methods, adding one or more extra parameters for opting into the configuration validity checking. Using a bit mask option set or a parameter object could be a good way to allow future extensions to this feature without requiring breaking API changes.
In places where the use of a BSPropertySet is unavoidable (for example, a view controller instantiated from a storyboard), it would be helpful if Blindside could call something like a "bsAwakeFromPropertyInjection" method on the object after the properties have been injected. It could be added to the category on NSObject.
I may do a pull request unless there is a compelling reason not to do this.
The last step to supporting Cocoapods is to add Blindside's podspec to Cocoapod's specs repo (more info) so it can actually be added by developers. For example, on my last project Blindside was the only external dependency we needed to add as a submodule instead of a pod dependency.
I'd like to go ahead and add Blindside to the public cocoapods repo since I'm on the beach this week anyway. Let me know if you're good with me handling it.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.