Coder Social home page Coder Social logo

swinject / swinjectautoregistration Goto Github PK

View Code? Open in Web Editor NEW
246.0 9.0 43.0 1.71 MB

Swinject extension to automatically register your services

License: MIT License

Ruby 0.45% Swift 98.13% Objective-C 0.32% Makefile 1.10%
swinject auto-registration dependency-injection swift

swinjectautoregistration's Introduction

Swinject

Github Actions Carthage compatible CocoaPods Version License Platforms Swift Version Reviewed by Hound

Swinject is a lightweight dependency injection framework for Swift.

Dependency injection (DI) is a software design pattern that implements Inversion of Control (IoC) for resolving dependencies. In the pattern, Swinject helps your app split into loosely-coupled components, which can be developed, tested and maintained more easily. Swinject is powered by the Swift generic type system and first class functions to define dependencies of your app simply and fluently.

Swinject is maintained by the Faire Wholesale Inc. mobile platform team.

Features

Extensions

Requirements

  • iOS 11.0+ / Mac OS X 10.13+ / watchOS 4.0+ / tvOS 11.0+
  • Xcode 14.3+
  • Swift 4.2+
  • Carthage 0.18+ (if you use)
  • CocoaPods 1.1.1+ (if you use)

Installation

Swinject is available through Carthage, CocoaPods, or Swift Package Manager.

Carthage

To install Swinject with Carthage, add the following line to your Cartfile.

github "Swinject/Swinject"

# Uncomment if you use SwinjectStoryboard
# github "Swinject/SwinjectStoryboard"

Then run carthage update --no-use-binaries command or just carthage update. For details of the installation and usage of Carthage, visit its project page.

CocoaPods

To install Swinject with CocoaPods, add the following lines to your Podfile.

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '11.0' # or platform :osx, '10.13' if your target is OS X.
use_frameworks!

pod 'Swinject'

# Uncomment if you use SwinjectStoryboard
# pod 'SwinjectStoryboard'

Then run pod install command. For details of the installation and usage of CocoaPods, visit its official website.

Swift Package Manager

in Package.swift add the following:

dependencies: [
    // Dependencies declare other packages that this package depends on.
    // .package(url: /* package url */, from: "1.0.0"),
    .package(url: "https://github.com/Swinject/Swinject.git", from: "2.8.0")
],
targets: [
    .target(
        name: "MyProject",
        dependencies: [..., "Swinject"]
    )
    ...
]

Documentation

Basic Usage

First, register a service and component pair to a Container, where the component is created by the registered closure as a factory. In this example, Cat and PetOwner are component classes implementing Animal and Person service protocols, respectively.

let container = Container()
container.register(Animal.self) { _ in Cat(name: "Mimi") }
container.register(Person.self) { r in
    PetOwner(pet: r.resolve(Animal.self)!)
}

Then get an instance of a service from the container. The person is resolved to a pet owner, and playing with the cat named Mimi!

let person = container.resolve(Person.self)!
person.play() // prints "I'm playing with Mimi."

Where definitions of the protocols and classes are

protocol Animal {
    var name: String? { get }
}

class Cat: Animal {
    let name: String?

    init(name: String?) {
        self.name = name
    }
}

and

protocol Person {
    func play()
}

class PetOwner: Person {
    let pet: Animal

    init(pet: Animal) {
        self.pet = pet
    }

    func play() {
        let name = pet.name ?? "someone"
        print("I'm playing with \(name).")
    }
}

Notice that the pet of PetOwner is automatically set as the instance of Cat when Person is resolved to the instance of PetOwner. If a container already set up is given, you do not have to care what are the actual types of the services and how they are created with their dependency.

Where to Register Services

Services must be registered to a container before they are used. The typical registration approach will differ depending upon whether you are using SwinjectStoryboard or not.

The following view controller class is used in addition to the protocols and classes above in the examples below.

class PersonViewController: UIViewController {
    var person: Person?
}

With SwinjectStoryboard

Import SwinjectStoryboard at the top of your swift source file.

import SwinjectStoryboard

Services should be registered in an extension of SwinjectStoryboard if you use SwinjectStoryboard. Refer to the project page of SwinjectStoryboard for further details.

extension SwinjectStoryboard {
    @objc class func setup() {
        defaultContainer.register(Animal.self) { _ in Cat(name: "Mimi") }
        defaultContainer.register(Person.self) { r in
            PetOwner(pet: r.resolve(Animal.self)!)
        }
        defaultContainer.register(PersonViewController.self) { r in
            let controller = PersonViewController()
            controller.person = r.resolve(Person.self)
            return controller
        }
    }
}

Without SwinjectStoryboard

If you do not use SwinjectStoryboard to instantiate view controllers, services should be registered to a container in your application's AppDelegate. Registering before exiting application:didFinishLaunchingWithOptions: will ensure that the services are setup appropriately before they are used.

class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    let container: Container = {
        let container = Container()
        container.register(Animal.self) { _ in Cat(name: "Mimi") }
        container.register(Person.self) { r in
            PetOwner(pet: r.resolve(Animal.self)!)
        }
        container.register(PersonViewController.self) { r in
            let controller = PersonViewController()
            controller.person = r.resolve(Person.self)
            return controller
        }
        return container
    }()

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {

        // Instantiate a window.
        let window = UIWindow(frame: UIScreen.main.bounds)
        window.makeKeyAndVisible()
        self.window = window

        // Instantiate the root view controller with dependencies injected by the container.
        window.rootViewController = container.resolve(PersonViewController.self)

        return true
    }
}

Notice that the example uses a convenience initializer taking a closure to register services to the new instance of Container.

Play in Playground!

The project contains Sample-iOS.playground to demonstrate the features of Swinject. Download or clone the project, run the playground, modify it, and play with it to learn Swinject.

To run the playground in the project, first build the project, then select Editor > Execute Playground menu in Xcode.

Example Apps

Some example apps using Swinject can be found on GitHub.

Blog Posts

The following blog posts introduce the concept of dependency injection and Swinject.

Thanks the authors!

Contribution Guide

A guide to submit issues, to ask general questions, or to open pull requests is here.

Question?

Credits

The DI container features of Swinject are inspired by:

and highly inspired by:

License

MIT license. See the LICENSE file for details.

swinjectautoregistration's People

Contributors

1ucas avatar alexocode avatar andriydruk avatar devxoul avatar glauberl-ciandt avatar jakubvano avatar jilizart avatar karinberg avatar lutzifer avatar maxim-chipeev avatar mpdifran avatar rivukis avatar ryu0118 avatar serg-vinnie avatar swziy avatar tkohout avatar yoichitgy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swinjectautoregistration's Issues

Allow using Optional dependencies

It would be nice if we can use optional dependencies:

PersonOwner(name:String, pet: AnimalType?)

and

PersonOwner(name:String, pet: AnimalType!)

Can we have a resolver that tries to resolve optionals and falls back to nil?

Release Swift5 version

Release SwinjectAutoregistration with Swift Language Version - Swift 5 so it can be picked up by Swift 5 projects without needing to modify project configuration.

How to auto register when init has default arguments?

Is it possible to specify how to resolve a class with a constructor that has a default argument?
Take the following example

init(argument1: Foo, argument2: Bar = Bar())
{
    ...
}

Registering it without specifying the constructor will fail during runtime, as the resolver does not assume the default argument, hence, does not recognize the registry

container.autoregister(MyClass.self, initializer: MyClass.init)

//This will fail
container.resolve(Myclass.Self, argument: Foo())

Registering it specifying a constructor will not work, as it will fail during compile time, as it cannot recognize an init that has only 1 argument

container.autoregister(MyClass.self, initializer: MyClass.init(argument1:))

The only way I could think of, to resolve this issue, is to explicitly create a convenience init that takes argument1 and internally invokes the intended init, passing argument2 with the intended default value.

convenience init(argument1: Foo)
{
    self.init(argument1: argument1, argument2: Bar())
}

init(argument1: Foo, argument2: Bar = Bar())
{
    ...
}

Is there any other way to achieve this?

SwinjectAutoregistration: ambiguous reference when initializer takes 0 parameters

Firstly, I really like Swinject and SwinjectAutoregistration. Nice work!

This might be a bug in the Swift compiler. Using Xcode 9.2, Swift complains of an ambiguous reference when initializer takes zero parameters. Not sure how you can fix this, though.

Example:

protocol Person { }
class PetOwner: Person {
    init() { }
}
let container = Container()
container.autoregister(Person.self, initializer: PetOwner.init) // Swift Error: Ambiguous use of 'autoregister(_:name:initializer:)'

Testing asserts

I would like to also test that the extension throws proper assertionFailure if the dependency is not resolved. But these asserts crashes the test suite which is obviously not desirable.

There is a pull request in Nimble that should be solving it but it appears to be dead for some time:
Quick/Nimble#248

There is apparently a way how to test preconditions described here: http://www.cocoawithlove.com/blog/2016/02/02/partial-functions-part-two-catching-precondition-failures.html which you can find either brilliant or ridiculously complicated .

We could use this though, but I am not sure if we want to mess the testing codebase with this code just to test the asserts. What do you think?

API for autoregistration

Ideal API would be

Container.register(service:initiliazer:)

however, as pointed out in this comment it would colide with current usage of Container.register(service:factory:) method.

Options are

  1. come up with a way to work around colision
  2. rename method for autoregistration
  3. swap arguments in autoregistration to Container.register(initiliazer:service:)

More auto extensions

Hi guys, I wrote 2 more autoregstration-like extensions just for fun.

But probably there is something useful in them?

I'll be grateful if you take a look and share your opinion 😊

ERROR ITMS-90056: This bundle is invalid

Hi, Today I try to release my app with SwinjectAutoregistration in dependency (via Carthage) and I receive error like 'ERROR ITMS-90056: This bundle is invalid. The Info.plist file is missing the required key: CFBundleVersion'
In project I found that in CFBundleVersion used parameter $(CURRENT_PROJECT_VERSION). But 'Current Project Version' is not installed in the build settings

Fix please or explain how I should use this.
Thanks.

Operator raise error for implicitly unwrapped optional type.

Hi, I cought some problem on the operator ~> without right hand expression.

When I have container.register(Service0.self) { r in Service0() },

it's ok:

let service: Service0 = container~>

But it raises error if the type is implicitly unwrapped optional:

let service: Service0! = container~>

I think implicitly unwrapped optional type is evil in almost all case.
But I have to use implicitly unwrapped optional for injecting to view controllers with SwinjectStoryboard like below, so I hope to support implicitly unwrapped optional appropriately.

class MyViewController: UIViewController {
    var viewModel: MyViewModel!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Use viewModel here
    }
}
extension SwinjectStoryboard {
    @objc class func setup() {
        defaultContainer.autoregister(MyViewModel.self, initializer: MyViewModel.init)

        defaultContainer.storyboardInitCompleted(MyViewController.self) { r, c in
              c.viewModel = r ~>  // crash!!
        }
}

environment:

  • Xcode 9.4

watchOS deployment target.

iOS deployment target is iOS 8. This is totally fine. But watchOS deployment target is watchOS 4.3. Can we change it to something older let's say watchOS 3?

Framework size

Hi,

I've built framework using Carthage and I've seen thats its size is 7.021.260 bytes.
Swinject size is 5.009.531 bytes
SwinjectStoryboard is 1.253.881 bytes

I think there's an error. How to solve?

Swift 4 Release

Please release new version of the cocoapod with Swift 4 support.

This will allow us to remove branch specification from our Podfile:

pod 'SwinjectAutoregistration', 
:git => '[email protected]:Swinject/SwinjectAutoregistration.git', 
:branch => 'swift4' 

Thank you for wonderful pod!

Mix dependencies with and without arguments

Hi!
Firstly I want to say thank you for your job. SwinjectAutoregistration is a really helpful tool.

The issue I've encountered is that when an object has an argument and several dependencies which may have or not have the same argument the autoregistration does not work because it does not pass the argument of the first object down to its dependencies.

// First class has an argument and 2 dependencies 
// where B also has the argument, but C has not.
class A {
    let b: B
    let c: C
    let argument: String

    init(argument: String, b: B, c: C) {
        self.b = b
        self.c = c
        self.argument = argument
    }

    func report() {
        print("I am A with \(argument)")

        b.report()
        c.report()
    }
}

class B {
    let argument: String

    init(argument: String) {
        self.argument = argument
    }

    func report() {
        print("I am B with \(argument)")
    }
}

class C {
    func report() {
        print("I am C")
    }
}

// And the usage
let container = Container()

container.autoregister(A.self, argument: String.self, initializer: A.init)

container.autoregister(B.self, argument: String.self, initializer: B.init)

container.autoregister(C.self, initializer: C.init)

// will fail in current implementation
container.resolve(A.self, argument: "1")?.report()

I've figured out that if your Resolver extension and auto-registration code will be updated to try resolutions with arguments like this: (Obviously it should be applied to all the combinations)

func resolve<Service, Arg1>(argument  arg1: Arg1) -> Service? {
   return (arg1 as? Service) ?? self.resolve(Service.self) ?? self.resolve(Service.self, argument: arg1)
}

@discardableResult
func autoregister<Service, A, B, C, Arg1>(_ service: Service.Type, name: String? = nil, argument  arg1: Arg1.Type, initializer: @escaping ((A, B, C)) -> Service) -> ServiceEntry<Service> {
   return self.register(service.self, name: name, factory: { res, arg1 in 
           let a: A? = res.resolve() ?? res.resolve(argument: arg1)
           let b: B? = res.resolve() ?? res.resolve(argument: arg1)
           let c: C? = res.resolve() ?? res.resolve(argument: arg1)
           checkResolved(initializer: initializer, services: a, b, c)
           return initializer((a!, b!, c!))

   } as (Resolver, Arg1) -> Service)
}

Than the auto-registration will work fine except that Swinject will write some scary logs about failed resolutions.

Do you know how to deal with the resolution failed logs? Should we deal with them or leave to warn developers in case the arguments passing was not expected?

What do you think about such an approach overall? I can make a PR if you think it is the right way to go.

Resolve operators

We want to add resolve operators for more concise and readable syntax - typically they would be used where autoregistration cannot be, e.g. when you need to define explicit types / names.

Various versions are discussed here, most fitting operator seems to be ~> with usage:

MyService(dependencyA: r~>)
MyService(dependencyA: r ~> (DependencyA.self, name: "name"))
MyService(dependencyA: r ~> (DependencyA.self, arguments: (arg1, arg2)))

Alternative for simple resolve would be <~ with usage

MyService(dependencyA: <~r)

Prefix form is however not usable for more complex cases, and having multiple operators is inconsistent and confusing.

Auto-register on resolve

To be completely honest I haven't used this library yet. I was just reading the documentation and then I saw this line of code:

container.autoregister(MyService.self, initializer: MyService.init)

And then I thought, well in that particular case why would you need to register the service at all? I come from a PHP background and in the Laravel framework the container has this feature that you can ask it to resolve a concrete class that you haven't even registered in it, because it can just auto-resolve all the bindings on the fly.

Wouldn't that be possible here too?

Xcode 10.2 Support

When I'm trying to rebuild framework for new Xcode 10.2, it allways fails.

Is it possible to support new Xcode 10.2?

Many thanks!

Init methods can be called multiple times even with .container scope

With the following registration, I would expect that the init method for A is called once because I marked A as .container (Singleton) scope, but it seems to be called multiple times. Is this the expected behavior or is there something that I'm missing?

container.autoregister(
      A.self,
      initializer: A.init)
      .inObjectScope(.container)
container.register(B.self) { r in r.resolve(A.self)! }
container.register(C.self) { r in r.resolve(A.self)! }

A.init is still called twice even if I mark B and C as container scope

container.autoregister(
      A.self,
      initializer: A.init)
      .inObjectScope(.container)
container.register(B.self) { r in r.resolve(A.self)! }      .inObjectScope(.container)
container.register(C.self) { r in r.resolve(A.self)! }      .inObjectScope(.container)

And multiple instances of A is actually created.

I'm on ver 2.0.1

Autoregistration for property injection

SwinjectAutoregistration is awesome and is a perfect showcase of Swift's generics capabilities. But sadly it omits property injection 😕.

I've got a couple of use cases for such a feature in my codebase, so I decided to try and extend Container myself. It turned out quite straightforward actually.

@discardableResult
    func autoregister<Service, T>(initializer: @escaping () -> Service,
                                  property: WritableKeyPath<Service, T>) -> ServiceEntry<Service> {
        return register(Service.self, factory: { res in
            let arg = res.resolve(T.self)!
            var service = initializer()
            service[keyPath: property] = arg
            return service
        })
    }

What do you think? Should I turn this into a full-fledged PR with methods for more properties?

[Update] Here's the use case:

/// Registration
container.autoregister(initializer: PinViewController.init, property: \.viewModel)

/// Resolving
@objc private func handleLogoTap() {
    let vc = DI.shared.container.resolve(PinViewController.self)!
    present(UINavigationController(rootViewController: vc), animated: true)
}

Is it possible to have more detail error logs when there is circular dependency?

Currently when there is circular dependency, the injection will fail with this error message: "fatal error: Infinite recursive call for circular dependency has been detected. To avoid the infinite call...,". Is it possible to include in the log information that is good to determine what classes cause the circular dependency?

Swinject crash on iOS 14

Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x0000000102de8360
Termination Signal: Trace/BPT trap: 5
Termination Reason: Namespace SIGNAL, Code 0x5
Terminating Process: exc handler [664]
Triggered by Thread: 0

Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 found 0x0000000102de8360 0x102be4000 + 2114400
1 found 0x0000000102de82e0 0x102be4000 + 2114272
2 found 0x000000010323059c 0x102be4000 + 6604188
3 found 0x00000001032308a8 0x102be4000 + 6604968
4 Swinject 0x00000001088ce40c partial apply for thunk for @escaping @callee_guaranteed (@in_guaranteed Resolver) -> (@out A) + 74764 (:0)
5 Swinject 0x00000001088ce468 partial apply for closure #1 in Container.resolve(:name:) + 74856 (:0)
6 Swinject 0x00000001088ce374 partial apply for thunk for @escaping @callee_guaranteed (@unowned @callee_guaranteed (@in_guaranteed B) -> (@out Any)) -> (@out Any) + 74612 (:0)
7 Swinject 0x00000001088ce39c partial apply for thunk for @callee_guaranteed (@guaranteed @escaping @callee_guaranteed (@in_guaranteed B) -> (@out Any)) -> (@out Any) + 74652 (:0)
8 Swinject 0x00000001088c9204 Container.resolve<A, B>(entry:invoker:) + 53764 (Container.swift:309)
9 Swinject 0x00000001088c8ab8 Container.resolve<A, B>(name:option:invoker:) + 51896 (Container.swift:190)
10 Swinject 0x00000001088ca0dc Container.resolve
(:) + 57564 (Container.swift:271)
11 Swinject 0x00000001088ca70c protocol witness for Resolver.resolve(
:) in conformance Container + 59148 (:0)
12 found 0x0000000103230b0c 0x102be4000 + 6605580
13 Swinject 0x00000001088ce40c partial apply for thunk for @escaping @callee_guaranteed (@in_guaranteed Resolver) -> (@out A) + 74764 (:0)
14 Swinject 0x00000001088ce468 partial apply for closure #1 in Container.resolve(_:name:) + 74856 (:0)
15 Swinject 0x00000001088ce374 partial apply for thunk for @escaping @callee_guaranteed (@unowned @callee_guaranteed (@in_guaranteed B) -> (@out Any)) -> (@out Any) + 74612 (:0)
16 Swinject 0x00000001088ce39c partial apply for thunk for @callee_guaranteed (@guaranteed @escaping @callee_guaranteed (@in_guaranteed B) -> (@out Any)) -> (@out Any) + 74652 (:0)
17 Swinject 0x00000001088c9204 Container.resolve<A, B>(entry:invoker:) + 53764 (Container.swift:309)
18 Swinject 0x00000001088c8ab8 Container.resolve<A, B>(name:option:invoker:) + 51896 (Container.swift:190)
19 Swinject 0x00000001088ca0dc Container.resolve
(:) + 57564 (Container.swift:271)
20 灵感 0x000000010323007c 0x102be4000 + 6602876
21 libdispatch.dylib 0x0000000191a61ac8 0x191a5e000 + 15048
22 libdispatch.dylib 0x0000000191a63250 0x191a5e000 + 21072
23 libswiftCore.dylib 0x0000000195ce74d0 0x195951000 + 3761360

Showing Ambiguous use of 'init' when opening the project on Xcode version 12.0 +

Showing Ambiguous use of 'init' when opening the project on Xcode version 12.0 +

Background

Currently, a project for my company is using VIPER architeture.

When the Xcode version is 11.7, everything is fine. However, when Xcode version is 12.0+ and opening the same project

, it shows an error Ambiguous use of 'init'

Here's some related example

Sample Code

// RandomServiceAssembly.swift
import Swinject
import SwinjectAutoregistration

func assemble(container: Container) {
  // ....
        container.autoregister(RandomServiceViewProtocol.self, initializer: (RandomServiceView.init) // Ambiguous use of 'init'
  // ...
}
// RandomServiceView.swift

protocol RandomServiceViewProtocol {
    // ...
}
final class RandomServiceView: UIView {
  override init(frame: CGRect) {						// 1. Found this candidate
        super.init(frame: frame)
        // ....
 }
   required init?(coder aDecoder: NSCoder) {
          fatalError("init(coder:) has not been implemented")
   }
}

 extension RandomServiceView: RandomServiceViewProtocol {
  // ....
 } 
// UIView+Utility.swift
extension UIView {
  // ....
    public convenience init(backgroundColor: UIColor) {      // 2. Found this candidate
            self.init()
            self.backgroundColor = backgroundColor
     }
  // ....
}

Things I have done

  1. Checked documentation

When a service has multiple initializers, swift compiler can't be sure which should be used and you will get a ambigious use of init(x: y: z:). This can also happen if the service is extending another class that have initializer with the same number of arguments.

// After implementing the below code  
// Xcode was crashed and shut when building the project.
// After crash, when opening Xcode, it got crashed and closed again and again. Need to change back to Xcode 11.7 to open the 	project 
container.autoregister(RandomServiceViewProtocol.self, initializer: (RandomServiceView.init(frame:))  // error gone but crashed on buildtime

                       
container.autoregister(RandomServiceViewProtocol.self, initializer: (RandomServiceView.init as () -> RandomServiceView ) //same
// Crash Thread message
Thread 21 Crashed:: Dispatch queue: XCBuild.XCBBuildOperation.buildOperationHandlerQueue
0   com.apple.dt.IDE.XCBuildSupport	0x000000012fc8a28c specialized IDEXCBuildServiceBuildOperation.buildOperation(_:didEndTask:result:signalled:info:) + 5452
1   com.apple.dt.IDE.XCBuildSupport	0x000000012fc80c29 IDEXCBuildServiceBuildOperation.buildOperationDidEnd(_:metricsData:) + 617
2   com.apple.dt.IDE.XCBuildSupport	0x000000012fc82ef0 protocol witness for XCBBuildOperationDelegate.buildOperationDidEnd(_:metricsData:) in conformance IDEXCBuildServiceBuildOperation + 16
3   com.apple.dt.XCBuild          	0x000000012ddbd32a closure #15 in XCBBuildOperation.handleMessage(_:) + 1210
4   com.apple.dt.XCBuild          	0x000000012ddff2fe thunk for @escaping @callee_guaranteed () -> () + 14
5   libdispatch.dylib             	0x00007fff731a16c4 _dispatch_call_block_and_release + 12
6   libdispatch.dylib             	0x00007fff731a2658 _dispatch_client_callout + 8
7   libdispatch.dylib             	0x00007fff731a7c44 _dispatch_lane_serial_drain + 597
8   libdispatch.dylib             	0x00007fff731a85d6 _dispatch_lane_invoke + 363
9   libdispatch.dylib             	0x00007fff731b1c09 _dispatch_workloop_worker_thread + 596
10  libsystem_pthread.dylib       	0x00007fff733fca3d _pthread_wqthread + 290
11  libsystem_pthread.dylib       	0x00007fff733fbb77 start_wqthread + 15
  1. Update the swinject version

I updated Swinject and SwinjectAutoregistration version from 2.6 to 2.7 but it seems not help

Right now we could only open and build the project using Xcode 11.7 , there's no way to run and build the project on Xcode 12.0 +.

Does anyone have the issue? If yes, how did you solve it?

Thanks for your help!

arm64 is missing from ARCHS

Swinject itself builds for M1 Macs, but for some reason SwinjectAutoregistration doesn't:

SwinjectAutoregistration on  master
❯ grep ARCHS .
./Configurations/Base/Common.xcconfig
11:ARCHS = $(ARCHS_STANDARD)

./Configurations/Mac OS X/Mac-Base.xcconfig
19:VALID_ARCHS = x86_64

Could you please fix that?

Fail earlier at registration, not resolve

I see that the call to
checkResolved(...)
is done at resolve time. If the registered initializer contains an optional, for example, it would fail long after its been registered.

Is there anyway the failure could occur at registration time, which is by definition going to occur earlier in the application life cycle?

This would decrease bugs I believe.

Remove submodules

We should remove submodules, similar to what we did for SwinjectStoryboard here: Swinject/SwinjectStoryboard#44

Submodules prevent Carthage from sharing Swinject when using multiple Swinject dependencies, and can lead to build errors when including Carthage dependency projects as sub-projects.

Build fails on Carthage without xcframeworks

Version 2.7 works, but 2.8.1 fails with:

error: There is no XCFramework found at '.../Carthage/Checkouts/SwinjectAutoregistration/Carthage/Build/Swinject.xcframework'. (in target 'SwinjectAutoregistration-iOS' from project 'SwinjectAutoregistration')

carthage build --platform iOS --cache-builds SwinjectAutoregistration

carthage 0.38
xcode 13.1

Possible Limitation of SwinjectAutoregistration Involving Initializers

Am I correct that, when I use SwinjectAutoregistration, no component initializer may be private?

In my app, I have a service/protocol, GameCenterable, with two components that implement that protocol, RealGameCenter and TestGameCenter. RealGameCenter has a private initializer, which takes no arguments. TestGameCenter has an internal initializer which takes a Bool argument, isAuthenticated. For context, I show in the snippets below registration and use of TestGameCenter and RealGameCenter. To make the latter work, I had to change the initializer of RealGameCenter from private to internal.

Vanilla Swinject does not have this limitation, but I would prefer to use SwinjectAutoregistration so I don't get Optionals from the container.

// registration and use of TestGameCenter component
container.autoregister(
  GameCenterable.self,
  argument: Bool.self,
  initializer: TestGameCenter.init(isAuthenticated:)
)

let gameCenter = container ~> (GameCenterable.self, argument: false)

// registration and use of RealGameCenter component
container.autoregister(
  GameCenterable.self,
  initializer: RealGameCenter.init
)
                           
let gameCenter = container ~> (GameCenterable.self)

Error installing using Carthage

Trying to install SwinjectAutoregistration by adding

github "Swinject/Swinject" "2.0.0"
github "Swinject/SwinjectAutoregistration" "2.0.0"

to the Cartfile. Then calling carthage update --platform iOS fails with

*** Checking out SwinjectAutoregistration at "2.0.0"iff
Failed to write to /Users/igorkulman/Projects/Teamwire/iOS/Teamwire/Carthage/Checkouts/SwinjectAutoregistration/Carthage/Checkouts/Swinject: Error Domain=NSCocoaErrorDomain Code=516 "The file “Swinject” couldn’t be saved in the folder “Checkouts” because a file with the same name already exists." UserInfo={NSFilePath=/Users/igorkulman/Projects/Teamwire/iOS/Teamwire/Carthage/Checkouts/SwinjectAutoregistration/Carthage/Checkouts/Swinject, NSUnderlyingError=0x7fb79f10c1d0 {Error Domain=NSPOSIXErrorDomain Code=17 "File exists"}}

pod install fails with SwinjectAutoregistration

trying to do pod install

to get SwinjectAutoregistration, after we already had pod SwinjectStoryboard cause this failure:

[!] Unable to satisfy the following requirements:

- `Swinject (= 2.1.0)` required by `Podfile.lock`
- `Swinject (~> 2.0)` required by `SwinjectStoryboard (1.1.1)`
- `Swinject (~> 2.0.0)` required by `SwinjectAutoregistration (2.0.0)`

Podfile:

    pod 'SwinjectStoryboard'
    pod 'SwinjectAutoregistration'

Does SwinjectAutoregistration works with Swinject (= 2.1.0)? or only with 2.0.0?

Allow dynamic in Package.swift

Would it be possible to create a new version which contains the changes made in the Package.swift file?
I wanna use it as a dynamic library

Xcode 9b3 support

Currently using autoregister in Xcode9b3 generates error Ambiguous use of 'autoregister(_:name:initializer:)' for code

container.autoregister(ServiceType.self, initializer: Service.init)

where

protocol ServiceType {}

final class Service: ServiceType {
  private let dependecy: DependecyType

  init(dependency: DependencyType) {
    self.dependecy = dependecy
  }
}

From what I've gathered currently Xcode can't distinguish different autoregister functions, so adding only this function to the project works

func autoregister<Service, A>(_ service: Service.Type, name: String? = nil, initializer: @escaping (A) -> Service) -> ServiceEntry<Service>

but adding another like

func autoregister<Service, A, B>(_ service: Service.Type, name: String? = nil, initializer: @escaping (A, B) -> Service) -> ServiceEntry<Service>

generates error.

Publish new dot release

Could someone with repo permissions publish a new dot release? The current release 2.8.1 depends on Swinject 2.7.1 rather than the current Swinject 2.8.2

Thank you!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.