Skip to content

Commit 47a0d6e

Browse files
authored
Merge pull request #3 from MobileUpLLC/UPUP-692-memory-leak
Upup 692 memory leak
2 parents 9f92ad5 + 652cb84 commit 47a0d6e

17 files changed

Lines changed: 381 additions & 59 deletions

ExampleApp/Example-Info.plist

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,22 @@
22
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
33
<plist version="1.0">
44
<dict>
5-
<key>UIApplicationSceneManifest</key>
6-
<dict>
7-
<key>UIApplicationSupportsMultipleScenes</key>
8-
<true/>
9-
<key>UISceneConfigurations</key>
10-
<dict/>
11-
</dict>
5+
<key>UIApplicationSceneManifest</key>
6+
<dict>
7+
<key>UIApplicationSupportsMultipleScenes</key>
8+
<false/>
9+
<key>UISceneConfigurations</key>
10+
<dict>
11+
<key>UIWindowSceneSessionRoleApplication</key>
12+
<array>
13+
<dict>
14+
<key>UISceneConfigurationName</key>
15+
<string>Default Configuration</string>
16+
<key>UISceneDelegateClassName</key>
17+
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
18+
</dict>
19+
</array>
20+
</dict>
21+
</dict>
1222
</dict>
1323
</plist>

ExampleApp/Example.xcodeproj/project.pbxproj

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,21 @@
99
/* Begin PBXBuildFile section */
1010
4211F22E2999730F00D13FD0 /* TextInputField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4211F22D2999730F00D13FD0 /* TextInputField.swift */; };
1111
426A30E529E81D5A00C5FB02 /* MyRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 426A30E429E81D5A00C5FB02 /* MyRule.swift */; };
12-
426CF63829850D1A00012FBE /* ExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 426CF63729850D1A00012FBE /* ExampleApp.swift */; };
1312
426CF63A29850D1A00012FBE /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 426CF63929850D1A00012FBE /* ContentView.swift */; };
1413
426CF63C29850D1B00012FBE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 426CF63B29850D1B00012FBE /* Assets.xcassets */; };
1514
426CF63F29850D1B00012FBE /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 426CF63E29850D1B00012FBE /* Preview Assets.xcassets */; };
1615
426CF64929850DD400012FBE /* FormView in Frameworks */ = {isa = PBXBuildFile; productRef = 426CF64829850DD400012FBE /* FormView */; };
16+
7392F4562CF76C8900331B40 /* HostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7392F4552CF76C8900331B40 /* HostingController.swift */; };
17+
7392F45A2CF76D7600331B40 /* StartFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7392F4592CF76D7500331B40 /* StartFactory.swift */; };
18+
7392F45C2CF76FFB00331B40 /* StartCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7392F45B2CF76FFA00331B40 /* StartCoordinator.swift */; };
19+
7392F45E2CF7701B00331B40 /* StartController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7392F45D2CF7701A00331B40 /* StartController.swift */; };
20+
7392F4602CF7709D00331B40 /* StartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7392F45F2CF7709D00331B40 /* StartView.swift */; };
21+
7392F4632CF7710900331B40 /* StartViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7392F4622CF7710800331B40 /* StartViewModel.swift */; };
22+
7392F4652CF7717E00331B40 /* ContentFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7392F4642CF7717D00331B40 /* ContentFactory.swift */; };
23+
7392F4692CF771AB00331B40 /* ContentCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7392F4682CF771AB00331B40 /* ContentCoordinator.swift */; };
24+
7392F46B2CF771C900331B40 /* ContentController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7392F46A2CF771C900331B40 /* ContentController.swift */; };
25+
739E30032CF4A1AF009B795F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 739E30022CF4A1AB009B795F /* AppDelegate.swift */; };
26+
739E30052CF4A1CF009B795F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 739E30042CF4A1CE009B795F /* SceneDelegate.swift */; };
1727
E1DB5A1F2A73BFCF0024C47A /* ContentViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1DB5A1E2A73BFCF0024C47A /* ContentViewModel.swift */; };
1828
E1E8FCDB2A52B8CD0099A852 /* SecureInputField.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E8FCDA2A52B8CD0099A852 /* SecureInputField.swift */; };
1929
/* End PBXBuildFile section */
@@ -22,12 +32,22 @@
2232
4211F22D2999730F00D13FD0 /* TextInputField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextInputField.swift; sourceTree = "<group>"; };
2333
426A30E429E81D5A00C5FB02 /* MyRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyRule.swift; sourceTree = "<group>"; };
2434
426CF63429850D1A00012FBE /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
25-
426CF63729850D1A00012FBE /* ExampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleApp.swift; sourceTree = "<group>"; };
2635
426CF63929850D1A00012FBE /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
2736
426CF63B29850D1B00012FBE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
2837
426CF63E29850D1B00012FBE /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
2938
426CF64629850D9F00012FBE /* FormView */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FormView; path = ..; sourceTree = "<group>"; };
3039
426CF64C29903DBC00012FBE /* Example-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Example-Info.plist"; sourceTree = "<group>"; };
40+
7392F4552CF76C8900331B40 /* HostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingController.swift; sourceTree = "<group>"; };
41+
7392F4592CF76D7500331B40 /* StartFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartFactory.swift; sourceTree = "<group>"; };
42+
7392F45B2CF76FFA00331B40 /* StartCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartCoordinator.swift; sourceTree = "<group>"; };
43+
7392F45D2CF7701A00331B40 /* StartController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartController.swift; sourceTree = "<group>"; };
44+
7392F45F2CF7709D00331B40 /* StartView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartView.swift; sourceTree = "<group>"; };
45+
7392F4622CF7710800331B40 /* StartViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartViewModel.swift; sourceTree = "<group>"; };
46+
7392F4642CF7717D00331B40 /* ContentFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentFactory.swift; sourceTree = "<group>"; };
47+
7392F4682CF771AB00331B40 /* ContentCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentCoordinator.swift; sourceTree = "<group>"; };
48+
7392F46A2CF771C900331B40 /* ContentController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentController.swift; sourceTree = "<group>"; };
49+
739E30022CF4A1AB009B795F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
50+
739E30042CF4A1CE009B795F /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
3151
E1DB5A1E2A73BFCF0024C47A /* ContentViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentViewModel.swift; sourceTree = "<group>"; };
3252
E1E8FCDA2A52B8CD0099A852 /* SecureInputField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecureInputField.swift; sourceTree = "<group>"; };
3353
/* End PBXFileReference section */
@@ -66,10 +86,11 @@
6686
426CF63629850D1A00012FBE /* ExampleApp */ = {
6787
isa = PBXGroup;
6888
children = (
69-
426CF63729850D1A00012FBE /* ExampleApp.swift */,
70-
426CF63929850D1A00012FBE /* ContentView.swift */,
71-
E1DB5A1E2A73BFCF0024C47A /* ContentViewModel.swift */,
89+
739E30022CF4A1AB009B795F /* AppDelegate.swift */,
90+
739E30042CF4A1CE009B795F /* SceneDelegate.swift */,
7291
426A30E429E81D5A00C5FB02 /* MyRule.swift */,
92+
7392F4542CF76C7400331B40 /* Base */,
93+
7392F4572CF76CB500331B40 /* UI */,
7394
E1E8FCDC2A52C61D0099A852 /* InputFields */,
7495
426CF63B29850D1B00012FBE /* Assets.xcassets */,
7596
426CF63D29850D1B00012FBE /* Preview Content */,
@@ -100,6 +121,47 @@
100121
name = Frameworks;
101122
sourceTree = "<group>";
102123
};
124+
7392F4542CF76C7400331B40 /* Base */ = {
125+
isa = PBXGroup;
126+
children = (
127+
7392F4552CF76C8900331B40 /* HostingController.swift */,
128+
);
129+
path = Base;
130+
sourceTree = "<group>";
131+
};
132+
7392F4572CF76CB500331B40 /* UI */ = {
133+
isa = PBXGroup;
134+
children = (
135+
7392F4612CF770E100331B40 /* ContentScreen */,
136+
7392F4582CF76D6300331B40 /* StartScreen */,
137+
);
138+
path = UI;
139+
sourceTree = "<group>";
140+
};
141+
7392F4582CF76D6300331B40 /* StartScreen */ = {
142+
isa = PBXGroup;
143+
children = (
144+
7392F4592CF76D7500331B40 /* StartFactory.swift */,
145+
7392F4622CF7710800331B40 /* StartViewModel.swift */,
146+
7392F45B2CF76FFA00331B40 /* StartCoordinator.swift */,
147+
7392F45D2CF7701A00331B40 /* StartController.swift */,
148+
7392F45F2CF7709D00331B40 /* StartView.swift */,
149+
);
150+
path = StartScreen;
151+
sourceTree = "<group>";
152+
};
153+
7392F4612CF770E100331B40 /* ContentScreen */ = {
154+
isa = PBXGroup;
155+
children = (
156+
E1DB5A1E2A73BFCF0024C47A /* ContentViewModel.swift */,
157+
7392F4642CF7717D00331B40 /* ContentFactory.swift */,
158+
426CF63929850D1A00012FBE /* ContentView.swift */,
159+
7392F46A2CF771C900331B40 /* ContentController.swift */,
160+
7392F4682CF771AB00331B40 /* ContentCoordinator.swift */,
161+
);
162+
path = ContentScreen;
163+
sourceTree = "<group>";
164+
};
103165
E1E8FCDC2A52C61D0099A852 /* InputFields */ = {
104166
isa = PBXGroup;
105167
children = (
@@ -206,11 +268,21 @@
206268
buildActionMask = 2147483647;
207269
files = (
208270
4211F22E2999730F00D13FD0 /* TextInputField.swift in Sources */,
271+
7392F46B2CF771C900331B40 /* ContentController.swift in Sources */,
209272
E1E8FCDB2A52B8CD0099A852 /* SecureInputField.swift in Sources */,
273+
7392F4692CF771AB00331B40 /* ContentCoordinator.swift in Sources */,
274+
7392F45E2CF7701B00331B40 /* StartController.swift in Sources */,
210275
E1DB5A1F2A73BFCF0024C47A /* ContentViewModel.swift in Sources */,
276+
7392F45C2CF76FFB00331B40 /* StartCoordinator.swift in Sources */,
277+
7392F4602CF7709D00331B40 /* StartView.swift in Sources */,
278+
7392F45A2CF76D7600331B40 /* StartFactory.swift in Sources */,
279+
7392F4652CF7717E00331B40 /* ContentFactory.swift in Sources */,
280+
7392F4632CF7710900331B40 /* StartViewModel.swift in Sources */,
211281
426A30E529E81D5A00C5FB02 /* MyRule.swift in Sources */,
282+
739E30032CF4A1AF009B795F /* AppDelegate.swift in Sources */,
212283
426CF63A29850D1A00012FBE /* ContentView.swift in Sources */,
213-
426CF63829850D1A00012FBE /* ExampleApp.swift in Sources */,
284+
7392F4562CF76C8900331B40 /* HostingController.swift in Sources */,
285+
739E30052CF4A1CF009B795F /* SceneDelegate.swift in Sources */,
214286
);
215287
runOnlyForDeploymentPostprocessing = 0;
216288
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//
2+
// AppDelegate.swift
3+
// Example
4+
//
5+
// Created by Victor Kostin on 25.11.2024.
6+
//
7+
8+
import UIKit
9+
10+
@main
11+
class AppDelegate: UIResponder, UIApplicationDelegate {
12+
func application(
13+
_ application: UIApplication,
14+
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
15+
) -> Bool {
16+
17+
return true
18+
}
19+
}
20+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//
2+
// HostingController.swift
3+
// Example
4+
//
5+
// Created by Victor Kostin on 27.11.2024.
6+
//
7+
8+
import SwiftUI
9+
import UIKit
10+
11+
class HostingController<T: View>: UIHostingController<T> {
12+
override init(rootView: T) {
13+
super.init(rootView: rootView)
14+
}
15+
16+
override func viewDidLoad() {
17+
super.viewDidLoad()
18+
19+
view.backgroundColor = .clear
20+
}
21+
22+
override func viewWillAppear(_ animated: Bool) {
23+
super.viewWillAppear(animated)
24+
}
25+
26+
@available(*, unavailable) @MainActor dynamic required init?(coder aDecoder: NSCoder) {
27+
super.init(coder: aDecoder)
28+
}
29+
}

ExampleApp/ExampleApp/ExampleApp.swift

Lines changed: 0 additions & 17 deletions
This file was deleted.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//
2+
// SceneDelegate.swift
3+
// Example
4+
//
5+
// Created by Victor Kostin on 25.11.2024.
6+
//
7+
8+
import UIKit
9+
10+
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
11+
var window: UIWindow?
12+
13+
func scene(
14+
_ scene: UIScene,
15+
willConnectTo session: UISceneSession,
16+
options connectionOptions: UIScene.ConnectionOptions
17+
) {
18+
guard let windowScene = (scene as? UIWindowScene) else {
19+
return
20+
}
21+
22+
window = UIWindow(windowScene: windowScene)
23+
window?.windowScene = windowScene
24+
window?.makeKeyAndVisible()
25+
26+
let rootViewController = StartFactory.createStartController()
27+
28+
window?.rootViewController = rootViewController
29+
}
30+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//
2+
// ContentController.swift
3+
// Example
4+
//
5+
// Created by Victor Kostin on 27.11.2024.
6+
//
7+
8+
import SwiftUI
9+
10+
class ContentController: HostingController<ContentView> {
11+
init(viewModel: ContentViewModel) {
12+
super.init(rootView: ContentView(viewModel: viewModel))
13+
print("init ContentController")
14+
}
15+
16+
deinit {
17+
print("deinit ContentController")
18+
}
19+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// ContentCoordinator.swift
3+
// Example
4+
//
5+
// Created by Victor Kostin on 27.11.2024.
6+
//
7+
8+
import UIKit
9+
10+
class ContentCoordinator {
11+
weak var router: UIViewController?
12+
13+
func pop() {
14+
router?.navigationController?.popViewController(animated: true)
15+
}
16+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//
2+
// ContentFactory.swift
3+
// Example
4+
//
5+
// Created by Victor Kostin on 27.11.2024.
6+
//
7+
8+
import UIKit
9+
10+
enum ContentFactory {
11+
static func createContentController() -> UIViewController {
12+
let coordinator = ContentCoordinator()
13+
let viewModel = ContentViewModel(coordinator: coordinator)
14+
let controller = ContentController(viewModel: viewModel)
15+
16+
coordinator.router = controller
17+
18+
return controller
19+
}
20+
}

ExampleApp/ExampleApp/ContentView.swift renamed to ExampleApp/ExampleApp/UI/ContentScreen/ContentView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,6 @@ struct ContentView: View {
7070

7171
struct ContentView_Previews: PreviewProvider {
7272
static var previews: some View {
73-
ContentView(viewModel: ContentViewModel())
73+
ContentView(viewModel: ContentViewModel(coordinator: ContentCoordinator()))
7474
}
7575
}

0 commit comments

Comments
 (0)