Skip to content

Commit 701250b

Browse files
feat: Update reactor logger
1 parent 5a0b808 commit 701250b

7 files changed

Lines changed: 51 additions & 47 deletions

File tree

GoodReactor-Sample/GoodReactor-Sample/Application/AppDelegate.swift

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
2222
UINavigationBar.configureAppearance()
2323

2424
AppCoordinator(window: window).start()
25-
26-
ReactorConfiguration.logger = SampleLogger()
2725

2826
return true
2927
}
3028

3129
}
32-
33-
struct SampleLogger: ReactorLogger {
34-
35-
func logReactorEvent(_ message: Any, level: LogLevel, fileName: String, lineNumber: Int) {
36-
print("[\(level)] \(message) (\(fileName):\(lineNumber))")
37-
}
38-
39-
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// SampleLogger.swift
3+
// goodreactor-swiftui-sample
4+
//
5+
// Created by Matus Klasovity on 23/06/2025.
6+
//
7+
8+
import GoodReactor
9+
10+
struct SampleLogger: ReactorLogger {
11+
12+
func logReactorEvent(_ message: Any, level: GoodReactor.LogLevel, fileName: String, lineNumber: Int) {
13+
print("\(level): \(message) [\(fileName):\(lineNumber)]")
14+
}
15+
16+
}

GoodReactor-Sample/goodreactor-swiftui-sample/Screens/Content/ContentViewModel.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,9 @@ import SwiftUI
7171
func fetchData() async -> Mutation {
7272
return .didFetchData
7373
}
74+
75+
func makeLogger() -> (any ReactorLogger)? {
76+
SampleLogger()
77+
}
7478

7579
}

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ reactor.stateStream
181181

182182
## Logging
183183
```swift
184+
// 1. Create a logger conforming to ReactorLogger protocol
184185
struct SampleLogger: ReactorLogger {
185186

186187
func logReactorEvent(_ message: Any, level: LogLevel, fileName: String, lineNumber: Int) {
@@ -189,7 +190,16 @@ struct SampleLogger: ReactorLogger {
189190

190191
}
191192

192-
ReactorConfiguration.logger = SampleLogger()
193+
// 2. Set the logger to the Reactor
194+
@Observable final class ContentViewModel: Reactor {
195+
196+
// ...
197+
198+
func makeLogger() -> (any ReactorLogger)? {
199+
SampleLogger()
200+
}
201+
202+
}
193203
```
194204

195205
# License

Sources/GoodReactor/Reactor.swift

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ import SwiftUI
101101
associatedtype State
102102

103103
/// Logger used for logging reactor events
104-
static var logger: ReactorLogger? { get }
104+
var logger: ReactorLogger? { get }
105105

106106
/// Initial state of the reactor
107107
///
@@ -117,13 +117,9 @@ import SwiftUI
117117

118118
/// Constructor for this reactor's logger. Gets called only once during the lifetime
119119
/// of a Reactor.
120-
///
121-
/// Default logger is `OSLogLogger` in iOS 14 and newer, or
122-
/// `PrintLogger` in older iOS versions.
123-
///
124-
/// - Returns: Logger used for logging reactor events. See `GoodLogger` package
120+
/// - Returns: Logger used for logging reactor events. See `ReactorLogger` protocol
125121
/// for more information.
126-
static func makeLogger() -> ReactorLogger?
122+
func makeLogger() -> ReactorLogger?
127123

128124
/// Constructor for this reactor's initial state.
129125
///
@@ -235,8 +231,8 @@ public extension Reactor {
235231

236232
typealias Event = GoodReactor.Event<Action, Mutation, Destination>
237233

238-
static var logger: ReactorLogger? {
239-
MapTables.loggers.forceCastedValue(forKey: self, default: makeLogger())
234+
var logger: ReactorLogger? {
235+
MapTables.loggers.optionalCastedValue(forKey: self, default: makeLogger())
240236
}
241237

242238
var state: State {
@@ -252,8 +248,8 @@ public extension Reactor {
252248
MapTables.initialState.forceCastedValue(forKey: self, default: makeInitialState())
253249
}
254250

255-
static func makeLogger() -> ReactorLogger? {
256-
ReactorConfiguration.logger
251+
func makeLogger() -> ReactorLogger? {
252+
nil
257253
}
258254

259255
func transform() {}
@@ -481,7 +477,7 @@ public extension Reactor {
481477
_send(event: event)
482478
}
483479

484-
Self._debugLog(message: "Subscription finished")
480+
self?._debugLog(message: "Subscription finished")
485481
}
486482

487483
subscription.store(in: &MapTables.subscriptions[key: self, default: []])
@@ -526,10 +522,6 @@ private extension Reactor {
526522
}
527523

528524
private func _debugLog(message: String) {
529-
Self._debugLog(message: message)
530-
}
531-
532-
private static func _debugLog(message: String) {
533525
logger?.logReactorEvent("[GoodReactor] \(Self.name) - \(message)", level: .debug, fileName: #file, lineNumber: #line)
534526
}
535527

Sources/GoodReactor/ReactorConfiguration.swift

Lines changed: 0 additions & 17 deletions
This file was deleted.

Sources/GoodReactor/Utilities/WeakMapTable.swift

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ final public class WeakMapTable<Key, Value>: @unchecked Sendable where Key: AnyO
4747
/// - key: The key for which to retrieve the associated value.
4848
/// - default: A closure that provides a default value if the key is not present.
4949
/// - Returns: The value associated with the given key or the default value if the key is not present.
50-
public func value(forKey key: Key, default: @autoclosure () -> Value) -> Value {
50+
public func value(forKey key: Key, default: @autoclosure () -> Value?) -> Value? {
5151
let weakKey = Weak(key)
5252

5353
self.lock.lock()
@@ -73,9 +73,18 @@ final public class WeakMapTable<Key, Value>: @unchecked Sendable where Key: AnyO
7373
/// - default: A closure that returns the default value to be returned if the key is not found.
7474
/// - Returns: The value associated with key, cast to type T, or the default value if the key is not found.
7575
public func forceCastedValue<T>(forKey key: Key, default: @autoclosure () -> T) -> T {
76-
return self.value(forKey: key, default: `default`() as! Value) as! T
76+
return self.value(forKey: key, default: `default`() as? Value) as! T
7777
}
78-
78+
79+
/// Retrieves the value associated with the given key, cast to the desired type T.
80+
/// - Parameters:
81+
/// - key: The key whose associated value is to be retrieved
82+
/// - default: A closure that returns the default value to be returned if the key is not found.
83+
/// - Returns: The value associated with key, cast to type T?, or the default value if the key is not found.
84+
public func optionalCastedValue<T>(forKey key: Key, default: @autoclosure () -> Value?) -> T? {
85+
return (self.value(forKey: key, default: `default`()) as? T)
86+
}
87+
7988
/// This method is used to set the value for a given key in the dictionary.
8089
/// - Parameters:
8190
/// - value: The value to be stored.

0 commit comments

Comments
 (0)