Skip to content

Commit 95c258f

Browse files
authored
Fix for retain cycles & splitview recreation issue (#1132)
1 parent e009978 commit 95c258f

File tree

9 files changed

+41
-32
lines changed

9 files changed

+41
-32
lines changed

CodeEdit/Features/PathBar/Views/PathBarComponent.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ struct PathBarComponent: View {
107107
func registerForChanges(in menu: NSMenu) {
108108
cancellable = NotificationCenter.default
109109
.publisher(for: NSMenu.didSendActionNotification, object: menu)
110-
.sink { notification in
110+
.sink { [weak self] notification in
111111
if let menuItem = notification.userInfo?["MenuItem"] as? NSMenuItem,
112112
let selection = menuItem as? ItemType {
113-
self.parent.selection = selection
113+
self?.parent.selection = selection
114114
}
115115
}
116116
}

CodeEdit/Features/SplitView/EditorView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ struct EditorView: View {
6565
.transformEnvironment(\.isAtEdge) { belowToolbar in
6666
calcIsAtEdge(current: &belowToolbar, index: index)
6767
}
68-
.environment(\.splitEditor) { edge, newTabGroup in
69-
data.split(edge, at: index, new: newTabGroup)
68+
.environment(\.splitEditor) { [weak data] edge, newTabGroup in
69+
data?.split(edge, at: index, new: newTabGroup)
7070
}
7171
}
7272
}

CodeEdit/Features/SplitView/SplitView.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,20 @@
88
import SwiftUI
99

1010
struct SplitView<Content: View>: View {
11+
var axis: Axis
1112
var content: Content
1213

13-
@State
14-
var viewController: SplitViewController
15-
1614
init(axis: Axis, @ViewBuilder content: () -> Content) {
15+
self.axis = axis
1716
self.content = content()
18-
let vc = SplitViewController(axis: axis)
19-
self._viewController = .init(wrappedValue: vc)
2017
}
2118

19+
@State var viewController: () -> SplitViewController? = { nil }
20+
2221
var body: some View {
2322
VStack {
2423
content.variadic { children in
25-
SplitViewControllerView(children: children, viewController: viewController)
24+
SplitViewControllerView(axis: axis, children: children, viewController: $viewController)
2625
}
2726
}
2827
._trait(SplitViewControllerLayoutValueKey.self, viewController)

CodeEdit/Features/SplitView/SplitViewControllerView.swift

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import SwiftUI
99

1010
struct SplitViewControllerView: NSViewControllerRepresentable {
1111

12+
var axis: Axis
1213
var children: _VariadicView.Children
13-
var viewController: SplitViewController
14+
@Binding var viewController: () -> SplitViewController?
1415

1516
func makeNSViewController(context: Context) -> SplitViewController {
16-
return viewController
17+
context.coordinator
1718
}
1819

1920
func updateNSViewController(_ controller: SplitViewController, context: Context) {
@@ -58,15 +59,21 @@ struct SplitViewControllerView: NSViewControllerRepresentable {
5859
}
5960
}
6061
}
62+
63+
func makeCoordinator() -> SplitViewController {
64+
SplitViewController(parent: self, axis: axis)
65+
}
6166
}
6267

6368
final class SplitViewController: NSSplitViewController {
6469

6570
var items: [SplitViewItem] = []
6671
var axis: Axis
72+
var parentView: SplitViewControllerView
6773

68-
init(axis: Axis = .horizontal) {
74+
init(parent: SplitViewControllerView, axis: Axis = .horizontal) {
6975
self.axis = axis
76+
self.parentView = parent
7077
super.init(nibName: nil, bundle: nil)
7178
}
7279

@@ -77,6 +84,11 @@ final class SplitViewController: NSSplitViewController {
7784
override func viewDidLoad() {
7885
splitView.isVertical = axis != .vertical
7986
splitView.dividerStyle = .thin
87+
DispatchQueue.main.async { [weak self] in
88+
self?.parentView.viewController = { [weak self] in
89+
self
90+
}
91+
}
8092
}
8193

8294
override func splitView(_ splitView: NSSplitView, shouldHideDividerAt dividerIndex: Int) -> Bool {

CodeEdit/Features/SplitView/SplitViewItem.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ class SplitViewItem: ObservableObject {
3030

3131
private func createObservers() -> [NSKeyValueObservation] {
3232
[
33-
item.observe(\.isCollapsed) { item, _ in
34-
self.collapsed.wrappedValue = item.isCollapsed
33+
item.observe(\.isCollapsed) { [weak self] item, _ in
34+
self?.collapsed.wrappedValue = item.isCollapsed
3535
}
3636
]
3737
}

CodeEdit/Features/SplitView/SplitViewModifiers.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import SwiftUI
99

1010
struct SplitViewControllerLayoutValueKey: _ViewTraitKey {
11-
static var defaultValue: SplitViewController?
11+
static var defaultValue: () -> SplitViewController? = { nil }
1212
}
1313

1414
struct SplitViewItemCollapsedViewTraitKey: _ViewTraitKey {

CodeEdit/Features/SplitView/SplitViewReader.swift

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,19 @@ struct SplitViewReader<Content: View>: View {
1111

1212
@ViewBuilder var content: (SplitViewProxy) -> Content
1313

14-
@State private var viewController: SplitViewController?
14+
@State private var viewController: () -> SplitViewController? = { nil }
1515

1616
private var proxy: SplitViewProxy {
17-
.init {
18-
viewController
19-
}
17+
.init(viewController: viewController)
2018
}
2119

2220
var body: some View {
2321
content(proxy)
2422
.variadic { children in
2523
ForEach(children, id: \.id) { child in
2624
child
27-
.task {
28-
if let vc = child[SplitViewControllerLayoutValueKey.self] {
29-
viewController = vc
30-
}
25+
.task(id: child[SplitViewControllerLayoutValueKey.self]()) {
26+
viewController = child[SplitViewControllerLayoutValueKey.self]
3127
}
3228
}
3329
}

CodeEdit/Features/Tabs/TabGroup/WorkspaceTabGroupView.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,9 @@ struct WorkspaceTabGroupView: View {
5151

5252
Divider()
5353
if let file = tabgroup.selected {
54-
PathBarView(file: file) { newFile in
55-
let index = tabgroup.tabs.firstIndex(of: file)
56-
if let index {
57-
tabgroup.openTab(item: newFile, at: index)
54+
PathBarView(file: file) { [weak tabgroup] newFile in
55+
if let index = tabgroup?.tabs.firstIndex(of: file) {
56+
tabgroup?.openTab(item: newFile, at: index)
5857
}
5958
}
6059
Divider()

CodeEdit/Features/Tabs/Views/TabBarView.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -445,10 +445,10 @@ struct TabBarView: View {
445445
if tabManager.tabGroups.findSomeTabGroup(except: tabgroup) != nil {
446446
TabBarAccessoryIcon(
447447
icon: .init(systemName: "multiply"),
448-
action: {
449-
tabgroup.close()
448+
action: { [weak tabgroup] in
449+
tabgroup?.close()
450450
if tabManager.activeTabGroup == tabgroup {
451-
tabManager.activeTabGroupHistory.removeAll { $0() == nil }
451+
tabManager.activeTabGroupHistory.removeAll { $0() == nil || $0() == tabgroup }
452452
tabManager.activeTabGroup = tabManager.activeTabGroupHistory.removeFirst()()!
453453
}
454454
tabManager.flatten()
@@ -565,7 +565,7 @@ struct TabBarView: View {
565565

566566
var splitviewButton: some View {
567567
Group {
568-
switch (tabgroup.parent!.axis, modifierKeys.contains(.option)) {
568+
switch (tabgroup.parent?.axis, modifierKeys.contains(.option)) {
569569
case (.horizontal, true), (.vertical, false):
570570
TabBarAccessoryIcon(icon: Image(systemName: "square.split.1x2")) {
571571
split(edge: .bottom)
@@ -577,6 +577,9 @@ struct TabBarView: View {
577577
split(edge: .trailing)
578578
}
579579
.help("Split Horizontally")
580+
581+
default:
582+
EmptyView()
580583
}
581584
}
582585
.foregroundColor(.secondary)

0 commit comments

Comments
 (0)