diff --git a/Sources/OpenSwiftUICore/View/Graph/ViewGraph.swift b/Sources/OpenSwiftUICore/View/Graph/ViewGraph.swift index 47259a7d6..e29d0548a 100644 --- a/Sources/OpenSwiftUICore/View/Graph/ViewGraph.swift +++ b/Sources/OpenSwiftUICore/View/Graph/ViewGraph.swift @@ -90,8 +90,8 @@ package final class ViewGraph: GraphHost { private var mainUpdates: Int = 0 - // MARK: - ViewGraph + NextUpdate - + // MARK: - ViewGraph + NextUpdate [6.5.4] + package struct NextUpdate { package private(set) var time: Time = .infinity @@ -101,6 +101,8 @@ package final class ViewGraph: GraphHost { _interval.isFinite ? _interval : .zero } + private var _defaultIntervalWasRequested: Bool = false + package private(set) var reasons: Set = [] package mutating func at(_ next: Time) { @@ -113,18 +115,23 @@ package final class ViewGraph: GraphHost { } let interval = velocity < 320 ? 1 / 80.0 : 1 / 120.0 let highFrameRateReason: UInt32 = _HighFrameRateReasonMake(0) - _interval = min(interval, _interval) + var newInterval = min(interval, _interval) + if _defaultIntervalWasRequested && newInterval > 1 / 60.0 { + newInterval = .infinity + } + _interval = newInterval reasons.insert(highFrameRateReason) } package mutating func interval(_ interval: Double, reason: UInt32? = nil) { if interval == .zero { - if _interval > 1 / 60 { - _interval = .infinity - } + _defaultIntervalWasRequested = true } else { _interval = min(interval, _interval) } + if _defaultIntervalWasRequested && _interval > 1 / 60 { + _interval = .infinity + } if let reason { reasons.insert(reason) } diff --git a/Tests/OpenSwiftUICoreTests/View/Graph/ViewGraphTests.swift b/Tests/OpenSwiftUICoreTests/View/Graph/ViewGraphTests.swift index 3853cdc68..71a99c1d7 100644 --- a/Tests/OpenSwiftUICoreTests/View/Graph/ViewGraphTests.swift +++ b/Tests/OpenSwiftUICoreTests/View/Graph/ViewGraphTests.swift @@ -10,10 +10,32 @@ struct ViewGraphTests { struct NextUpdateTests { typealias Update = ViewGraph.NextUpdate - @Test - func interval() { - let update = Update() - #expect(update.interval == .zero) + @Test(arguments: [ + (0.0, Double.zero, Set()), + (159.0, Double.zero, Set()), + (160.0, 1 / 80.0, [0x27_0000]), + (319.0, 1 / 80.0, [0x27_0000]), + (320.0, 1 / 120.0, [0x27_0000]), + (1000.0, 1 / 120.0, [0x27_0000]), + ] as [(Double, Double, Set)]) + func maxVelocity(velocity: Double, expectedInterval: Double, expectedReasons: Set) { + var update = Update() + update.maxVelocity(velocity) + #expect(update.interval == expectedInterval) + #expect(update.reasons == expectedReasons) + } + + @Test(arguments: [ + (0.05, nil, 0.05, Set()), + (0.025, nil, 0.025, Set()), + (0.025, 1 as UInt32?, 0.025, [1] as Set), + (0.0, nil, Double.zero, Set()), + ] as [(Double, UInt32?, Double, Set)]) + func intervalWithReason(interval: Double, reason: UInt32?, expectedInterval: Double, expectedReasons: Set) { + var update = Update() + update.interval(interval, reason: reason) + #expect(update.interval == expectedInterval) + #expect(update.reasons == expectedReasons) } } }