Skip to content

Commit

Permalink
Merge pull request #52 from li3zhen1/observation-retain-cycle-fix
Browse files Browse the repository at this point in the history
[Observation] Fix retain cycle
  • Loading branch information
li3zhen1 authored Mar 21, 2024
2 parents ac3570e + 5bf9552 commit af79ef7
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1500;
LastUpgradeCheck = 1500;
LastUpgradeCheck = 1530;
TargetAttributes = {
B7AFA5562ADF4997009C7154 = {
CreatedOnToolsVersion = 15.0;
Expand Down Expand Up @@ -219,6 +219,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
Expand Down Expand Up @@ -285,6 +286,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
Expand Down Expand Up @@ -335,7 +337,7 @@
SUPPORTS_MACCATALYST = NO;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,7";
};
Expand Down Expand Up @@ -366,6 +368,7 @@
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,7";
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
LastUpgradeVersion = "1530"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
Expand Down Expand Up @@ -33,7 +33,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableAddressSanitizer = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ struct ForceDirectedGraphExampleApp: App {
var body: some Scene {
WindowGroup {
ContentView()
// MyGraph()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ struct MiserableGraph: View {


@State private var stateMixin = ForceDirectedGraphState(
initialIsRunning: false,
initialModelTransform: .identity.scale(by: 1.2)
initialIsRunning: true,
initialModelTransform: .identity.scale(by: 1.4)
)

@State private var opacity = 0.0
// @State private var opacity = 0.0

@ViewBuilder
func getLabel(_ text: String) -> some View {
Expand All @@ -36,7 +36,7 @@ struct MiserableGraph: View {
RoundedRectangle(cornerSize: .init(width: 12, height: 12))
.fill(.foreground)
.shadow(radius: 1.5, y: 1.0)
}
}
.padding()
}

Expand All @@ -48,12 +48,17 @@ struct MiserableGraph: View {

Series(graphData.nodes) { node in
NodeMark(id: node.id)
.symbol(.circle)
.symbolSize(radius: 8.0)
.stroke()
.richLabel(node.id, offset: .zero) {
self.getLabel(node.id)
}
.symbol(.circle)
.symbolSize(radius: 8.0)
.foregroundStyle(colors[node.group % colors.count])
.stroke()
.richLabel(node.id, offset: .zero) {
if (graphData.links.filter({ l in
return l.source == node.id || l.target == node.id}
).count > 12) {
self.getLabel(node.id)
}
}
}

Series(graphData.links) { l in
Expand All @@ -68,12 +73,9 @@ struct MiserableGraph: View {
stiffness: .weightedByDegree(k: { _, _ in 1.0})
)
}
.opacity(opacity)
.animation(.easeInOut, value: opacity)

.ignoresSafeArea()
.toolbar {
MiserableToolbarContent(stateMixin: stateMixin, opacity: $opacity)
GraphStateToggle(graphStates: stateMixin)
}
}
}
Expand All @@ -85,7 +87,7 @@ struct MiserableToolbarContent: View {
var body: some View {
Group {
Button {
stateMixin.modelTransform.scaling(by: 1.1)
stateMixin.modelTransform.scaling(by: 0.9)
} label: {
Image(systemName: "minus")
}
Expand All @@ -96,7 +98,7 @@ struct MiserableToolbarContent: View {
.fontDesign(.monospaced)
}
Button {
stateMixin.modelTransform.scaling(by: 0.9)
stateMixin.modelTransform.scaling(by: 1.1)
} label: {
Image(systemName: "plus")
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Grape/Views/ForceDirectedGraph+Gesture.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ import SwiftUI
static var minimumScaleDelta: CGFloat { 0.001 }

@inlinable
static var minimumScale: CGFloat { 1e-4 }
static var minimumScale: CGFloat { 1e-2 }

@inlinable
static var maximumScale: CGFloat { .infinity }
Expand Down
24 changes: 12 additions & 12 deletions Sources/Grape/Views/ForceDirectedGraphModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ public final class ForceDirectedGraphModel<Content: GraphContent> {
_ graphRenderingContext: _GraphRenderingContext<NodeID>,
_ forceField: SealedForce2D,
stateMixin: ForceDirectedGraphState,
// modelTransform: Binding<ViewportTransform>,
emittingNewNodesWith: @escaping (NodeID) -> KineticState = { _ in
.init(position: .zero)
},
Expand All @@ -191,15 +190,13 @@ public final class ForceDirectedGraphModel<Content: GraphContent> {
)
self.currentFrame = 0
self.stateMixinRef = stateMixin
// self._modelTransform = stateMixin.modelTransform
}

@inlinable
convenience init(
_ graphRenderingContext: _GraphRenderingContext<NodeID>,
_ forceField: SealedForce2D,
stateMixin: ForceDirectedGraphState,
// modelTransform: Binding<ViewportTransform>,
emittingNewNodesWith: @escaping (NodeID) -> KineticState = { _ in
.init(position: .zero)
},
Expand All @@ -209,7 +206,6 @@ public final class ForceDirectedGraphModel<Content: GraphContent> {
graphRenderingContext,
forceField,
stateMixin: stateMixin,
// modelTransform: modelTransform,
emittingNewNodesWith: emittingNewNodesWith,
ticksPerSecond: ticksPerSecond,
velocityDecay: 30 / ticksPerSecond
Expand All @@ -229,9 +225,11 @@ public final class ForceDirectedGraphModel<Content: GraphContent> {

@inlinable
func continuouslyTrackingRunning() {
withObservationTracking {
updateModelRunningState(isRunning: stateMixinRef.isRunning)
} onChange: {
withObservationTracking { [weak self] in
guard let self else { return }
self.updateModelRunningState(isRunning: self.stateMixinRef.isRunning)
} onChange: { [weak self] in
guard let self else { return }
Task { @MainActor [weak self] in
self?.continuouslyTrackingRunning()
}
Expand All @@ -240,11 +238,13 @@ public final class ForceDirectedGraphModel<Content: GraphContent> {

@inlinable
func continuouslyTrackingTransform() {
withObservationTracking {
withObservationTracking { [weak self] in
guard let self else { return }
// FIXME: mutation cycle?
_ = stateMixinRef.modelTransform
_ = self.stateMixinRef.modelTransform
// stateMixinRef.access(keyPath: \.modelTransform)
} onChange: {
} onChange: { [weak self] in
guard let self else { return }
Task { @MainActor [weak self] in
self?.continuouslyTrackingTransform()
}
Expand Down Expand Up @@ -299,8 +299,8 @@ extension ForceDirectedGraphModel {
@inlinable
// @MainActor
func start(minAlpha: Double = 0.6) {
print("Into start")
guard self.scheduledTimer == nil else { return }
print("Simulation started")
if simulationContext.storage.kinetics.alpha < minAlpha {
simulationContext.storage.kinetics.alpha = minAlpha
}
Expand All @@ -325,7 +325,7 @@ extension ForceDirectedGraphModel {
@inlinable
// @MainActor
func stop() {
print("Into stop")
print("Simulation stopped")
self.scheduledTimer?.invalidate()
self.scheduledTimer = nil
}
Expand Down

0 comments on commit af79ef7

Please sign in to comment.