Coder Social home page Coder Social logo

injection's Introduction

Injection

example workflow GitHub License SPM compatible

Table of Contents

  1. Introduction
  2. How to use
  3. Testing
  4. Resources
  5. Author

Introduction

This package was developed to address one of the most challenging topics in the Swift community: dependency injection. I often found it difficult to grasp this concept and implement it effectively. Through extensive research, I discovered a straightforward method inspired by the @Environment property wrapper in SwiftUI. A defining feature of this package is its simplicity, making it easily understandable for anyoney.

Key issues addressed by this package include:

  • Simplifying the process of mocking data for tests.
  • Maintaining readability by adhering closely to Swift’s standard APIs.
  • Ensuring compile-time safety to prevent hidden crashes, so if the application builds, all dependencies are correctly configured.
  • Avoiding large initializers caused by dependency injection.
  • Relieving the AppDelegate from being the central point for defining all shared instances.
  • Minimizing potential learning curves.
  • Eliminating the need for force unwrapping.
  • Allowing the definition of standard dependencies without exposing private or internal types within packages.

first start by adding the pacakge to your code base as follow:

.package(url: "https://github.com/EngOmarElsayed/Injection", from: "1.3"),

Alternatively, navigate to the top section labeled 'Files' and click on 'Add Package Dependency':

Screenshot 2024-03-15 at 3 33 08 AM

How to use

Let's say we have a protocol called MotorBike (why motorBike because I love them 😍😅) that contains a funcation called move:

protocol MotorBike {
    func move() -> Int
}

And there is a struct called Ducati that conforms to MotorBike:

struct Ducati: MotorBike {
   func move() -> Int {
       return 5
   }
}

At this point we want to inject this object to another object using dependency injection design pattern to do so, the first step is to make an extension InjectedValues and add the new property that containes the object instance :

@InjecteValues extension InjectedValues {
  var ducatiProvider: MotorBike = Ducati()
}

and that's it...simple right 😉. The InjecteValues macro expand the code to this at compile time:

@InjecteValues extension InjectedValues {
  var ducatiProvider: MotorBike = Ducati()

//Expanded Code
private struct DucatiKey: InjectionKey {
   static var currentValue: MotorBike = Ducati()
}
    var ducatiProvider: MotorBike {
       get { Self[DucatiKey.self] }
       set { Self[DucatiKey.self] = newValue }
   }
}

To be able to use it, you will just write this where ever you need it:

struct Garage {
@Injected(\.ducatiProvider) var ducati: MotorBike
}

And that's it, simple right 🚀.

Note

When ever you call the @Injected you will have the same instance throught the life cycle of the app. To prevent any side effects and weird outcomes from happening due to inconsistent dependency references.

Note

Plus you can easily change the instance by writing:

let garage = Garage()
garage.ducati = Ducati()
//OR
InjectedValues[\.ducatiProvider] = Ducati()

Using the InjectedValues static subscript also affects already injected properties.

Testing

Testing your code is more easier than you think, you will just have to change the injected properties with a mock one using InjectedValues static subscript, like so:

final class MotorBikeTests: XCTestCase {
    override func setUp() {
        InjectedValues[\.ducatiProvider] = DuctiMock()
    }
    
    func test() {
        let garge = Garage()
        
        let result = garge.move()
        
        XCTAssertEqual(10, result)
    }
}

class DuctiMock: MotorBike {
    func move() -> Int {
        return 10
    }
}

that's it for how to test your injected properties. Easey right ? 😎

Resources

Some helpful links for you:

Author

This pacakge was created by Eng.Omar Elsayed to help the iOS comuntity and make there life easir. To contact me email me at [email protected]

injection's People

Contributors

engomarelsayed avatar

Stargazers

 avatar LACHKAR Zakaria avatar  avatar Rakhim Abdullayev avatar An Tran avatar Seif Kobrosly avatar James Sedlacek avatar Dídac Coll Pujals avatar Franklin Byaruhanga avatar Gonzalo avatar

Watchers

 avatar

Forkers

bezig01

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.