Skip to content

Commit d459eae

Browse files
authored
Merge pull request #38 from petermajor/master
Add @OptionalInjected attribute
2 parents b01dc56 + 4980742 commit d459eae

File tree

4 files changed

+57
-1
lines changed

4 files changed

+57
-1
lines changed

Documentation/Annotation.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ class NamedInjectedViewController: UIViewController {
5656
```
5757
If you go this route just make sure you specify the name *before* accessing the injected service for the first time.
5858

59+
### Optional injection
60+
61+
An annotation is available that supports optional resolving. If the service is not registered, then the value will be nil, otherwise it will be not nil:
62+
```
63+
class InjectedViewController: UIViewController {
64+
@OptionalInjected var service: XYZService?
65+
func load() {
66+
service?.load()
67+
}
68+
}
69+
```
70+
5971
### Custom Containers
6072

6173
You can specify and resolve custom containers using Injected. Just define your custom container...

Documentation/Optionals.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,15 @@ This could be helpful if for some reason you wanted to resolve to a specific ins
5454
```swift
5555
var abc: ABCServicing? = Resolver.resolve(ABCService.self)
5656
```
57+
58+
## Optional annotation
59+
60+
An annotation is available that supports optional resolving. If the service is not registered, then the value will be nil, otherwise it will be not nil:
61+
```
62+
class InjectedViewController: UIViewController {
63+
@OptionalInjected var service: XYZService?
64+
func load() {
65+
service?.load()
66+
}
67+
}
68+
```

Sources/Resolver/Resolver.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,25 @@ public struct LazyInjected<Service> {
625625
}
626626
}
627627

628+
@propertyWrapper
629+
public struct OptionalInjected<Service> {
630+
private var service: Service?
631+
public init() {
632+
self.service = Resolver.optional(Service.self)
633+
}
634+
public init(name: String? = nil, container: Resolver? = nil) {
635+
self.service = container?.optional(Service.self, name: name) ?? Resolver.optional(Service.self, name: name)
636+
}
637+
public var wrappedValue: Service? {
638+
get { return service }
639+
mutating set { service = newValue }
640+
}
641+
public var projectedValue: OptionalInjected<Service> {
642+
get { return self }
643+
mutating set { self = newValue }
644+
}
645+
}
646+
628647
/// Immediate injection property wrapper for SwiftUI ObservableObjects. This wrapper is meant for use in SwiftUI Views and exposes
629648
/// bindable objects similar to that of SwiftUI @observedObject and @environmentObject.
630649
///

Tests/ResolverTests/ResolverInjectedTests.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ class LazyInjectedViewController {
3535
@LazyInjected var service: XYZService
3636
}
3737

38+
class OptionalInjectedViewController {
39+
@OptionalInjected var service: XYZService?
40+
@OptionalInjected var notRegistered: NotRegistered?
41+
}
42+
43+
class NotRegistered {
44+
}
45+
3846
class ResolverInjectedTests: XCTestCase {
3947

4048
override func setUp() {
@@ -84,7 +92,12 @@ class ResolverInjectedTests: XCTestCase {
8492
XCTAssertNotNil(vc.service.session)
8593
XCTAssert(!vc.$service.isEmpty)
8694
}
87-
95+
96+
func testOptionalInjection() {
97+
let vc = OptionalInjectedViewController()
98+
XCTAssertNotNil(vc.service)
99+
XCTAssertNil(vc.notRegistered)
100+
}
88101
}
89102

90103
#endif

0 commit comments

Comments
 (0)