Skip to content

Commit

Permalink
Merge pull request #126 from AliSoftware/release/5.0.2
Browse files Browse the repository at this point in the history
Release 5.0.2
  • Loading branch information
ilyapuchka authored Oct 9, 2016
2 parents e4545e3 + 0b00e13 commit a1ece4b
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 126 deletions.
10 changes: 3 additions & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
env:
global:
- MODULE_NAME=Dip

matrix:
allow_failures:
- os: linux
Expand All @@ -28,11 +24,11 @@ matrix:
before_install:
- wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import -
- cd ..
- export SWIFT_VERSION=swift-DEVELOPMENT-SNAPSHOT-2016-09-07-a
- wget https://swift.org/builds/development/ubuntu1404/$SWIFT_VERSION/$SWIFT_VERSION-ubuntu14.04.tar.gz
- export SWIFT_VERSION=swift-3.0-RELEASE
- wget https://swift.org/builds/swift-3.0-release/ubuntu1404/$SWIFT_VERSION/$SWIFT_VERSION-ubuntu14.04.tar.gz
- tar xzf $SWIFT_VERSION-ubuntu14.04.tar.gz
- export PATH="${PWD}/${SWIFT_VERSION}-ubuntu14.04/usr/bin:${PATH}"
- cd $MODULE_NAME
- cd Dip

notifications:
email: false
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# CHANGELOG

## 5.0.2

#### Fixed

* Fixed Swift 3 issues related to reflection and IUO
[#125](https://github.com/AliSoftware/Dip/issues/125), [@ilyapuchka](https://github.com/ilyapuchka)

## 5.0.1

This release is the same as 5.0.0 and only fixes CocoaPods speck pushed to trunk without macOS, tvOS and watchOS deployment targets. Please use this release instead of 5.0.0 if you integrate Dip via Cocoapods.

## 5.0.0

* Migrated to Swift 3.0
Expand Down
2 changes: 1 addition & 1 deletion Dip.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "Dip"
s.version = "5.0.1"
s.version = "5.0.2"
s.summary = "Dependency Injection for Swift made easy."

s.description = <<-DESC
Expand Down
4 changes: 2 additions & 2 deletions Dip/Dip.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 5.0.1;
CURRENT_PROJECT_VERSION = 5.0.2;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
Expand Down Expand Up @@ -434,7 +434,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 5.0.1;
CURRENT_PROJECT_VERSION = 5.0.2;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,7 @@ class ServerImp: Server {
weak var client: ServerClient?
}

//There is currently a bug in Swift that causes runtime crash
//when trying to auto-inject not-NSObject weak property.
//https://bugs.swift.org/browse/SR-2144
class ServerClientImp: NSObject, ServerClient {
class ServerClientImp: ServerClient {
var server: Server?

init(server: Server) {
Expand Down Expand Up @@ -149,10 +146,7 @@ class InjectedServerImp: Server {
var client: ServerClient? { return injectedClient.value }
}

//There is currently a bug in Swift that causes runtime crash
//when trying to auto-inject not-NSObject weak property.
//https://bugs.swift.org/browse/SR-2144
class InjectedClientImp: NSObject, ServerClient {
class InjectedClientImp: ServerClient {
private var injectedServer = Injected<Server>()
var server: Server? { get { return injectedServer.value } }
}
Expand Down
131 changes: 69 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![License](https://img.shields.io/cocoapods/l/Dip.svg?style=flat)](http://cocoapods.org/pods/Dip)
[![Platform](https://img.shields.io/cocoapods/p/Dip.svg?style=flat)](http://cocoapods.org/pods/Dip)
[![Swift Version](https://img.shields.io/badge/Linux-compatible-4BC51D.svg?style=flat)](https://developer.apple.com/swift)
[![Swift Version](https://img.shields.io/badge/Swift-2.2-3.0-F16D39.svg?style=flat)](https://developer.apple.com/swift)
[![Swift Version](https://img.shields.io/badge/Swift-2.2--3.0-F16D39.svg?style=flat)](https://developer.apple.com/swift)
[![Swift Version](https://img.shields.io/badge/Linux-3.0--RELEASE-4BC51D.svg?style=flat)](https://developer.apple.com/swift)

![Animated Dipping GIF](cinnamon-pretzels-caramel-dipping.gif)
_Photo courtesy of [www.kevinandamanda.com](http://www.kevinandamanda.com/recipes/appetizer/homemade-soft-cinnamon-sugar-pretzel-bites-with-salted-caramel-dipping-sauce.html)_
Expand All @@ -17,46 +17,12 @@ _Photo courtesy of [www.kevinandamanda.com](http://www.kevinandamanda.com/recipe

It's aimed to be as simple as possible yet provide rich functionality usual for DI containers on other platforms. It's inspired by `.NET`'s [Unity Container](https://msdn.microsoft.com/library/ff647202.aspx) and other DI containers.

* You start by creating `let container = DependencyContainer()` and **registering your dependencies, by associating a _protocol_ or _type_ to a `factory`**.
* Then you can call `container.resolve()` to **resolve an instance of _protocol_ or _type_** using that `DependencyContainer`.
* You start by creating `let container = DependencyContainer()` and **registering your dependencies, by associating a _protocol_ or _type_ to a `factory`** using `container.register { MyService() as Service }`.
* Then you can call `container.resolve() as Service` to **resolve an instance of _protocol_ or _type_** using that `DependencyContainer`.
* You can easily use Dip along with **Storyboards and Nibs** - checkout **[Dip-UI](https://github.com/AliSoftware/Dip-UI)** extensions. There is also a **[code generator](https://github.com/ilyapuchka/dipgen)** that can help to simplify registering new components.

> You can easily use Dip along with Storyboards and Nibs - checkout [Dip-UI](https://github.com/AliSoftware/Dip-UI) extensions.
## Documentation & Usage Examples

Dip is completely [documented](http://cocoadocs.org/docsets/Dip/5.0.0/) and comes with a Playground that lets you try all its features and become familiar with API. You can find it in `Dip.xcworkspace`.

> Note: it may happen that you will need to build Dip framework before playground will be able to use it. For that select `Dip-iOS` scheme and build.
You can find bunch of usage examples in a [wiki](../../wiki).

If your are using [VIPER](https://www.objc.io/issues/13-architecture/viper/) architecture - [here](https://github.com/ilyapuchka/VIPER-SWIFT) is VIPER demo app that uses Dip instead of manual dependency injection.

There are also several blog posts that describe how to use Dip and some of its implementation details:

- [IoC container in Swift](http://ilya.puchka.me/ioc-container-in-swift/)
- [IoC container in Swift. Circular dependencies and auto-injection](http://ilya.puchka.me/ioc-container-in-swift-circular-dependencies-and-auto-injection/)
- [Dependency injection with Dip](http://ilya.puchka.me/dependency-injecinjection-with-dip/)

File an issue if you have any question.


## Features

- **[Scopes](../../wiki/scopes)**. Dip supports 5 different scopes (or life cycle strategies): _Unique_, _Shared_, _Singleton_, _EagerSingleton_, _WeakSingleton_;
- **[Named definitions](../../wiki/named-definitions)**. You can register different factories for the same protocol or type by registering them with [tags]();
- **[Runtime arguments](../../wiki/runtime-arguments)**. You can register factories that accept up to 6 runtime arguments;
- **[Circular dependencies](../../wiki/circular-dependencies)**. Dip can resolve circular dependencies;
- **[Auto-wiring](../../wiki/auto-wiring)** & **[Auto-injection](../../wiki/auto-injection)**. Dip can infer your components' dependencies injected in constructor and automatically resolve them as well as dependencies injected with properties.
- **[Resolving optionals](../../wiki/resolving-optionals)**. Dip is able to resolve constructor or property dependencies defined as optionals.
- **[Type forwarding](../../wiki/type-forwarding)**. You can register the same factory to resolve different types.
- **[Storyboards integration](../../wiki/storyboards-integration)**. You can easily use Dip along with storyboards and Xibs without ever referencing container in your view controller's code;
- **Weakly typed components**. Dip can resolve weak types when they are unknown at compile time.
- **[Easy configuration](../../wiki/containers-collaboration)**. No complex container hierarchy, no unneeded functionality;
- **Thread safety**. Registering and resolving components is thread safe;
- **Helpful error messages and configuration validation**. You can validate your container configuration. If something can not be resolved at runtime Dip throws an error that completely describes the issue;

## Basic usage
<details>
<summary>Basic usage</summary>

```swift
import Dip
Expand All @@ -82,7 +48,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

```

## More sophisticated example
</details>

<details>
<summary>More sophisticated example</summary>

```swift
import Dip
Expand All @@ -100,6 +69,9 @@ extension DependencyContainer {

static func configure() -> DependencyContainer {
return DependencyContainer { container in
unowned let container = container
DependencyContainer.uiContainers = [container]

container.register(tag: "ViewController") { ViewController() }
.resolvingProperties { container, controller in
controller.animationsFactory = try container.resolve() as AnimatonsFactory
Expand Down Expand Up @@ -137,49 +109,84 @@ class ViewController {

```

</details>

## Documentation & Usage Examples

Dip is completely [documented](http://cocoadocs.org/docsets/Dip/5.0.0/) and comes with a Playground that lets you try all its features and become familiar with API. You can find it in `Dip.xcworkspace`.

> Note: it may happen that you will need to build Dip framework before playground will be able to use it. For that select `Dip` scheme and build for iPhone Simulator.
You can find bunch of usage examples and usfull tips in a [wiki](../../wiki).

If your are using [VIPER](https://www.objc.io/issues/13-architecture/viper/) architecture - [here](https://github.com/ilyapuchka/VIPER-SWIFT) is VIPER demo app that uses Dip instead of manual dependency injection.

There are also several blog posts that describe how to use Dip and some of its implementation details:

- [IoC container in Swift](http://ilya.puchka.me/ioc-container-in-swift/)
- [IoC container in Swift. Circular dependencies and auto-injection](http://ilya.puchka.me/ioc-container-in-swift-circular-dependencies-and-auto-injection/)
- [Dependency injection with Dip](http://ilya.puchka.me/dependency-injecinjection-with-dip/)

File an issue if you have any question. Pull requests are warmly welcome too.


## Features

- **[Scopes](../../wiki/scopes)**. Dip supports 5 different scopes (or life cycle strategies): _Unique_, _Shared_, _Singleton_, _EagerSingleton_, _WeakSingleton_;
- **[Auto-wiring](../../wiki/auto-wiring)** & **[Auto-injection](../../wiki/auto-injection)**. Dip can infer your components' dependencies injected in constructor and automatically resolve them as well as dependencies injected with properties.
- **[Resolving optionals](../../wiki/resolving-optionals)**. Dip is able to resolve constructor or property dependencies defined as optionals.
- **[Type forwarding](../../wiki/type-forwarding)**. You can register the same factory to resolve different types implemeted by a single class.
- **[Circular dependencies](../../wiki/circular-dependencies)**. Dip will be able to resolve circular dependencies if you will follow some simple rules;
- **[Storyboards integration](../../wiki/storyboards-integration)**. You can easily use Dip along with storyboards and Xibs without ever referencing container in your view controller's code;
- **[Named definitions](../../wiki/named-definitions)**. You can register different factories for the same protocol or type by registering them with [tags]();
- **[Runtime arguments](../../wiki/runtime-arguments)**. You can register factories that accept up to 6 runtime arguments (and extend it if you need);
- **[Easy configuration](../../wiki/containers-collaboration)** & **Code generation**. No complex containers hierarchy, no unneeded functionality. Tired of writing all registrations by hand? There is a [cool code generator](https://github.com/ilyapuchka/dipgen) that will create them for you. The only thing you need is to annotate your code with some comments.
- **Weakly typed components**. Dip can resolve "weak" types when they are unknown at compile time.
- **Thread safety**. Registering and resolving components is thread safe;
- **Helpful error messages and configuration validation**. You can validate your container configuration. If something can not be resolved at runtime Dip throws an error that completely describes the issue;


## Installation

Since version 5.0.0 Dip is built with Swift 3.0. For Swift 2.2-2.3 compatible version use "swift2.3" branch.

Dip is available through [CocoaPods](http://cocoapods.org). To install
it, simply add the following line to your Podfile:
You can install Dip using your favorite dependency manager:

<details>
<summary>CocoaPods</summary>

```ruby
pod "Dip"
```
> You need at least 1.1.0.rc.2 version of CocoaPods.
</details>

If you use [Carthage](https://github.com/Carthage/Carthage) add this line to your Cartfile:
<details>
<summary>Carthage</summary>

```
github "AliSoftware/Dip"
```

If you use [Swift Package Manager](https://swift.org/package-manager/) add Dip as dependency to you `Package.swift`:
</details>

<details>
<summary>Swift Package Manager</summary>

```swift
let package = Package(
name: "MyPackage",
dependencies: [
.Package(url: "https://github.com/AliSoftware/Dip.git", "5.0.0")
]
)
.Package(url: "https://github.com/AliSoftware/Dip", majorVersion: 5, minor: 0)
```

## Running tests

On OSX you can run tests from Xcode. On Linux you need to have Swift Package Manager installed and use it to build and run tests:
</details>

```
cd Dip
swift build && swift test
```
## Running tests

> Note: Swift Package Manager is destributed with Swift development snapshots only, so it builds packages using Swift 3. To build Dip you will need to build it with Swift 2.2, for that you need to set [`$SWIFT_EXEC`](https://github.com/apple/swift-package-manager#choosing-swift-version) environment variable.
On OSX you can run tests from Xcode. On Linux you need to have Swift Package Manager installed and use it to build and run tests using this command: `swift build --clean && swift build && swift test`

## Credits

This library has been created by [**Olivier Halligon**]([email protected]).
I'd also like to thank [**Ilya Puchka**](https://twitter.com/ilyapuchka) for his big contribution to it, as he added a lot of great features to it.
This library has been created by [**Olivier Halligon**]([email protected]) and is maintained by [**Ilya Puchka**](https://twitter.com/ilyapuchka).

**Dip** is available under the **MIT license**. See the `LICENSE` file for more info.

Expand Down
2 changes: 2 additions & 0 deletions Sources/AutoInjection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ extension DependencyContainer {
}

private func resolveChild(child: Mirror.Child) throws {
//HOTFIX for https://bugs.swift.org/browse/SR-2282
guard !String(describing: type(of: child.value)).hasPrefix("ImplicitlyUnwrappedOptional") else { return }
guard let injectedPropertyBox = child.value as? AutoInjectedPropertyBox else { return }

let contextKey = DefinitionKey(type: type(of: injectedPropertyBox).wrappedType, typeOfArguments: Void.self, tag: context.tag)
Expand Down
17 changes: 13 additions & 4 deletions Sources/Utils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,16 @@
// THE SOFTWARE.
//

public enum LogLevel {
case Verbose
case Errors
public enum LogLevel: Int {
case None
case Errors
case Verbose
}

public var logLevel: LogLevel = .Errors

func log(_ logLevel: LogLevel, _ message: Any) {
guard case logLevel = Dip.logLevel else { return }
guard logLevel.rawValue <= Dip.logLevel.rawValue else { return }
print(message)
}

Expand Down Expand Up @@ -117,6 +118,14 @@ extension Collection where Index: Comparable, Self.Indices.Index == Index {
}

#if os(Linux)

extension String {
public func hasPrefix(_ prefix: String) -> Bool {
return prefix ==
String(self.characters.prefix(prefix.characters.count))
}
}

import Glibc
class RecursiveLock {
private var _lock = _initializeRecursiveMutex()
Expand Down
16 changes: 8 additions & 8 deletions Tests/DipTests/AutoInjectionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ import XCTest
@testable import Dip

private protocol Server: class {
weak var client: Client? {get}
var anotherClient: Client? {get set}
weak var client: Client! {get}
var anotherClient: Client! {get set}
}

private protocol Client: class {
var server: Server? {get}
var anotherServer: Server? {get set}
var server: Server! {get}
var anotherServer: Server! {get set}
}

private class ServerImp: Server {
Expand All @@ -41,11 +41,11 @@ private class ServerImp: Server {
AutoInjectionTests.clientDidInjectCalled = true
}

var client: Client? {
var client: Client! {
return _client.value
}

weak var anotherClient: Client?
weak var anotherClient: Client!

weak var _optionalProperty = InjectedWeak<AnyObject>(required: false)
}
Expand All @@ -56,11 +56,11 @@ private class ClientImp: Client {
AutoInjectionTests.serverDidInjectCalled = true
}

var server: Server? {
var server: Server! {
return _server.value
}

var anotherServer: Server?
var anotherServer: Server!

var _optionalProperty = Injected<AnyObject>(required: false)

Expand Down
8 changes: 4 additions & 4 deletions Tests/DipTests/AutoWiringTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ private class ServiceImp2: Service { }
private class ServiceImp3 {}

private protocol AutoWiredClient: class {
var service1: Service? { get set }
var service2: Service? { get set }
var service1: Service! { get set }
var service2: Service! { get set }
}

private class AutoWiredClientImp: AutoWiredClient {
var service1: Service?
var service2: Service?
var service1: Service!
var service2: Service!

init(service1: Service?, service2: ServiceImp2) {
self.service1 = service1
Expand Down
Loading

0 comments on commit a1ece4b

Please sign in to comment.