diff --git a/BGSwift/Classes/BGExtent.swift b/BGSwift/Classes/BGExtent.swift index 6ba20ec..5bed5a5 100644 --- a/BGSwift/Classes/BGExtent.swift +++ b/BGSwift/Classes/BGExtent.swift @@ -163,7 +163,7 @@ public class BGExtentBuilderGeneric { return state(value) { lhs, rhs in lhs.bg_unwrapped === rhs.bg_unwrapped } - } + } } public class BGExtentBuilder: BGExtentBuilderGeneric { diff --git a/BGSwift/Classes/BGResource.swift b/BGSwift/Classes/BGResource.swift index d55e77b..c93d5e0 100644 --- a/BGSwift/Classes/BGResource.swift +++ b/BGSwift/Classes/BGResource.swift @@ -249,7 +249,7 @@ public enum BGStateComparison { public enum Identical { case identical } } -public class BGState: BGResource, BGResourceInternal, TransientResource { +public class BGState: BGResource, BGResourceInternal, TransientResource, ObservableObject { var subsequents = Set() weak var supplier: BGBehavior? weak var owner: BGExtent? @@ -257,6 +257,24 @@ public class BGState: BGResource, BGResourceInternal, TransientResource { var _event: BGEvent = .unknownPast var _prevEvent: BGEvent = .unknownPast + // These properties support combine and swiftui + public weak var bindingInput: BGState? // could even be ourselves for two way binding + private var _observableUpdated: BGEvent = .unknownPast + private var _observableAccessed: Bool = false + public var observableValue: Type { + get { + _observableAccessed = true + if _event.sequence > _observableUpdated.sequence { + return traceValue + } else { + return value + } + } + set { + bindingInput?.updateWithAction(newValue) + } + } + var _value: Type var _prevValue: Type? private var comparison: ((Type, Type) -> Bool)? @@ -294,6 +312,14 @@ public class BGState: BGResource, BGResourceInternal, TransientResource { } if !valueEquals(newValue) { + if _observableAccessed { + owner?.sideEffect { [weak self] in + if let self { + self.objectWillChange.send() + self._observableUpdated = self.event + } + } + } _prevValue = _value; _prevEvent = _event; @@ -338,6 +364,7 @@ public class BGState: BGResource, BGResourceInternal, TransientResource { func clearTransientValue() { _prevValue = nil } + } public protocol BGDemandable { @@ -356,3 +383,4 @@ extension BGDemandable { } } } + diff --git a/Example/BGSwift.xcodeproj/project.pbxproj b/Example/BGSwift.xcodeproj/project.pbxproj index 82add4c..f10058a 100644 --- a/Example/BGSwift.xcodeproj/project.pbxproj +++ b/Example/BGSwift.xcodeproj/project.pbxproj @@ -72,6 +72,7 @@ 739FF919270F98F4000DACD1 /* BGExtentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGExtentTests.swift; sourceTree = ""; }; 739FF91B270F9D00000DACD1 /* BGGraphTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGGraphTests.swift; sourceTree = ""; }; 739FF91E270FAF6A000DACD1 /* EventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventTests.swift; sourceTree = ""; }; + 73E0B6492960F75100912A22 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Package.swift; path = ../Package.swift; sourceTree = ""; }; 8A12E8DD9E2CF2B6B45E7835 /* Pods_BGSwift_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BGSwift_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 8A2F667ABE5A14147F7D89E8 /* Pods_BGSwift_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BGSwift_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DBFB91C16E7BCE9F06B08EE1 /* Pods-BGSwift-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BGSwift-Example.debug.xcconfig"; path = "Target Support Files/Pods-BGSwift-Example/Pods-BGSwift-Example.debug.xcconfig"; sourceTree = ""; }; @@ -100,6 +101,7 @@ 5A0BB796270517E40043E632 = { isa = PBXGroup; children = ( + 73E0B6492960F75100912A22 /* Package.swift */, 5AC349BC2705259F00289AD2 /* BGSwift */, 5A0BB7A1270517E40043E632 /* Example */, 5A0BB7B8270517E60043E632 /* Tests */, diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..bff0658 --- /dev/null +++ b/Package.swift @@ -0,0 +1,30 @@ +// swift-tools-version:5.3 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "BGSwift", + platforms: [ + .macOS(.v10_15), // These are where Combine becomes available which we will use in SwiftPM compatibility + .iOS(.v13) + ], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "BGSwift", + targets: ["BGSwift"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "BGSwift", + path: "BGSwift/Classes"), + ], + swiftLanguageVersions: [.v5] +)