Skip to content

Commit 7252f44

Browse files
author
Tom Insam
committed
Migrate from ObservableObject to Observable, requires ios 17
1 parent 8007122 commit 7252f44

File tree

6 files changed

+46
-39
lines changed

6 files changed

+46
-39
lines changed

Flame.xcodeproj/project.pbxproj

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
archiveVersion = 1;
44
classes = {
55
};
6-
objectVersion = 54;
6+
objectVersion = 56;
77
objects = {
88

99
/* Begin PBXBuildFile section */
@@ -18,6 +18,7 @@
1818
57CE3BD3F6B2B4D92F9A6A3A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 71F556B8DB17A95F449EE581 /* Assets.xcassets */; };
1919
6FD6FED5727F258B614E30AF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79D12D8C1B438C8ED270337D /* SceneDelegate.swift */; };
2020
71FE2A8B72FE6D7321886F85 /* CellConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5286FFAD096541FB0D90316A /* CellConfiguration.swift */; };
21+
7298F0C22CEB72F300BE2470 /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7298F0C12CEB72F300BE2470 /* Observable.swift */; };
2122
7FBE0D6360AB8720521C42E0 /* AboutSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E07C6C06E47C6B7C805CF3B /* AboutSceneDelegate.swift */; };
2223
846F1E26FF7B62164ECDC99A /* Credits.rtfd in Resources */ = {isa = PBXBuildFile; fileRef = BD16FB7B7590C4D73E396E5D /* Credits.rtfd */; };
2324
9500515369F22DE05EB7E03F /* AddressCluster.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08AB33DF6763AEB024D41F1B /* AddressCluster.swift */; };
@@ -62,6 +63,7 @@
6263
5FDD9841E5D58F80CA615EE0 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
6364
62B50C7FBF75F734ADACEFCE /* AddressClusterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressClusterTests.swift; sourceTree = "<group>"; };
6465
71F556B8DB17A95F449EE581 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
66+
7298F0C12CEB72F300BE2470 /* Observable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Observable.swift; sourceTree = "<group>"; };
6567
7306B00560119DAAE21BEABE /* HostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostViewController.swift; sourceTree = "<group>"; };
6668
74127D199BC8E926B7584BD7 /* CustomSplitViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomSplitViewController.swift; sourceTree = "<group>"; };
6769
78C3E6E9772AEF11D1D06A60 /* Flame.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Flame.entitlements; sourceTree = "<group>"; };
@@ -185,6 +187,7 @@
185187
children = (
186188
CFE1C5F919065A3372C3843E /* Configurable.swift */,
187189
B54202612EC015AE5196BE21 /* ELog.swift */,
190+
7298F0C12CEB72F300BE2470 /* Observable.swift */,
188191
4009C2CF71D8CA04BC302DE6 /* NetworkMonitor.swift */,
189192
E1A42F35CA11FC87D5EB053E /* PassthroughSubjectExtension.swift */,
190193
);
@@ -323,6 +326,7 @@
323326
9736F332DE8D96D5C6810657 /* DemoServiceBrowser.swift in Sources */,
324327
96E0589895D1A17CEA07D81C /* DeprecatedServiceBrowser.swift in Sources */,
325328
D28EBFBE32F3C2EAA2B7A88C /* ELog.swift in Sources */,
329+
7298F0C22CEB72F300BE2470 /* Observable.swift in Sources */,
326330
B5E165B4C06122538CF0A214 /* Host.swift in Sources */,
327331
DC9651F437C519041467ADED /* HostViewController.swift in Sources */,
328332
D85733E4D4526FE47C32900E /* ModernServiceBrowser.swift in Sources */,
@@ -398,12 +402,12 @@
398402
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = NO;
399403
DEVELOPMENT_TEAM = 76AFK3W7M9;
400404
INFOPLIST_FILE = generated/Info.plist;
401-
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
405+
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
402406
LD_RUNPATH_SEARCH_PATHS = (
403407
"$(inherited)",
404408
"@executable_path/Frameworks",
405409
);
406-
MARKETING_VERSION = 103.3.0;
410+
MARKETING_VERSION = 104.0.0;
407411
PRODUCT_BUNDLE_IDENTIFIER = org.jerakeen.flametouch;
408412
PROVISIONING_PROFILE_SPECIFIER = "Flametouch dev (with multicast)";
409413
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "Flametouch Mac Dev";
@@ -480,12 +484,12 @@
480484
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = NO;
481485
DEVELOPMENT_TEAM = 76AFK3W7M9;
482486
INFOPLIST_FILE = generated/Info.plist;
483-
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
487+
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
484488
LD_RUNPATH_SEARCH_PATHS = (
485489
"$(inherited)",
486490
"@executable_path/Frameworks",
487491
);
488-
MARKETING_VERSION = 103.3.0;
492+
MARKETING_VERSION = 104.0.0;
489493
PRODUCT_BUNDLE_IDENTIFIER = org.jerakeen.flametouch;
490494
PROVISIONING_PROFILE_SPECIFIER = "Flametouch dev (with multicast)";
491495
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "Flametouch Mac Dev";

Flame/View Controllers/BrowseViewController.swift

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@ import UIKit
66

77
/// Root view of the app, renders a list of hosts on the local network
88

9-
class BrowseViewModel: ObservableObject {
10-
@Published
9+
@Observable
10+
final class BrowseViewModel {
1111
var hosts: [Host] = []
1212

13-
@Published
1413
var selection: Host?
1514

16-
@Published
1715
var noWifi: Bool = false
1816

1917
var refreshAction: () -> Void = {}
@@ -22,7 +20,7 @@ class BrowseViewModel: ObservableObject {
2220
}
2321

2422
struct BrowseView: View {
25-
@ObservedObject
23+
@Bindable
2624
var viewModel: BrowseViewModel
2725

2826
@State
@@ -104,13 +102,11 @@ class BrowseViewController: UIHostingController<BrowseView> {
104102
navigationItem.largeTitleDisplayMode = .always
105103
navigationItem.backButtonDisplayMode = .minimal
106104

107-
viewModel.$selection
108-
.sink { [weak self] value in
109-
guard let host = value else { return }
110-
let vc = HostViewController(serviceController: serviceController, host: host)
111-
self?.show(vc, sender: self)
112-
}
113-
.store(in: &cancellables)
105+
observeObject(viewModel, keypath: \.selection) { [weak self] selection in
106+
guard let host = selection else { return }
107+
let vc = HostViewController(serviceController: serviceController, host: host)
108+
self?.show(vc, sender: self)
109+
}
114110

115111
viewModel.refreshAction = { [weak self] in
116112
self?.handleTableRefresh(sender: nil)

Flame/View Controllers/HostViewController.swift

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,14 @@ import UIKit
66

77
/// View of a single host - lists the services of that host
88

9-
class HostViewModel: ObservableObject {
10-
@Published
9+
@Observable
10+
class HostViewModel {
1111
var host: Host?
12-
13-
@Published
1412
var selection: Service?
1513
}
1614

1715
struct HostView: View {
18-
@ObservedObject
16+
@Bindable
1917
var viewModel: HostViewModel
2018

2119
var body: some View {
@@ -80,13 +78,11 @@ class HostViewController: UIHostingController<HostView>, UICollectionViewDelegat
8078
}
8179
.store(in: &cancellables)
8280

83-
viewModel.$selection
84-
.compactMap { $0 }
85-
.sink { [weak self] service in
86-
let vc = ServiceViewController(serviceController: serviceController, service: service)
87-
self?.show(vc, sender: self)
88-
}
89-
.store(in: &cancellables)
81+
observeObject(viewModel, keypath: \.selection) { [weak self] service in
82+
guard let service else { return }
83+
let vc = ServiceViewController(serviceController: serviceController, service: service)
84+
self?.show(vc, sender: self)
85+
}
9086
}
9187

9288
@available(*, unavailable)

Flame/View Controllers/ServiceViewController.swift

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,16 @@ import UIKit
66

77
/// Shows the details of a particular service on a particular host
88

9-
class ServiceViewModel: ObservableObject {
10-
@Published
9+
@Observable
10+
class ServiceViewModel {
1111
var service: Service?
12-
13-
@Published
1412
var alive = true
15-
16-
@Published
1713
var highlight = true
18-
1914
var tapAction: (URL) -> Void = { _ in }
2015
}
2116

2217
struct ServiceView: View {
23-
@ObservedObject
18+
@Bindable
2419
var viewModel: ServiceViewModel
2520

2621
var body: some View {

Utils/Observable.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2024 Thomas Insam. All rights reserved.
2+
3+
import Foundation
4+
5+
public func observeObject<T: Observable & AnyObject, S>(_ object: T, keypath: KeyPath<T, S>, onChange: @escaping (S) -> Void) {
6+
withObservationTracking {
7+
_ = object[keyPath: keypath]
8+
} onChange: { [weak object] in
9+
guard let object else { return }
10+
Task { @MainActor in
11+
onChange(object[keyPath: keypath])
12+
observeObject(object, keypath: keypath, onChange: onChange)
13+
}
14+
}
15+
}

project.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ targets:
2424
# - watchOS
2525
# - visionOS
2626

27-
deploymentTarget: "15.0"
27+
deploymentTarget: "17.0"
2828
scheme:
2929
testTargets:
3030
- FlameTests
@@ -40,7 +40,8 @@ targets:
4040
# I messed up and got these backwards once and now every version must be >80.
4141
# This is the human-readable version, xcode cloud generates the build number now
4242
# so it doesn't need to be in the project
43-
MARKETING_VERSION: 103.3.0
43+
# YOU MUST REGENERATE AND COMMIT THE XCODE PROJECT TO BUMP THIS
44+
MARKETING_VERSION: 104.0.0
4445
debug:
4546
release:
4647
sources:

0 commit comments

Comments
 (0)