mirror of
https://github.com/kean/Pulse.git
synced 2026-05-30 21:07:33 +00:00
NetworkTaskEntity.session is declared @NSManaged var session: UUID
(non-optional), but the matching attribute in LoggerStore+Model.swift
is created without explicitly setting isOptional = false:
Attribute("session", .UUIDAttributeType),
NSAttributeDescription.isOptional defaults to true, so Core Data
permits NULL for session. Rows that end up with a NULL session (e.g.
data persisted under an older schema and carried through lightweight
migration) trap on read: the implicit ObjC->Swift UUID bridge calls
UUID._unconditionallyBridgeFromObjectiveC, which fires SIGTRAP on nil.
The only PulseUI read site is FileViewModelContext.swift:52, hit
transitively from ConsoleFormatter.status(for:store:) while rendering
ConsoleTaskCell.
Switch that read to value(forKey:) so a NULL stored value is surfaced
as Optional.none instead of trapping the bridge. Semantics are preserved:
- For valid rows, the comparison behaves exactly as before.
- For NULL-session rows, the cast yields nil, the comparison nil != sessionID
is true, and the function returns nil — matching the existing doc
comment ("returns nil if the task is an unknown state ... from the
previous app run").
64 lines
2.3 KiB
Swift
64 lines
2.3 KiB
Swift
// The MIT License (MIT)
|
|
//
|
|
// Copyright (c) 2020-2026 Alexander Grebenyuk (github.com/kean).
|
|
|
|
import Pulse
|
|
import Foundation
|
|
|
|
package struct FileViewerViewModelContext {
|
|
package var contentType: NetworkLogger.ContentType?
|
|
package var originalSize: Int64
|
|
package var metadata: [String: String]?
|
|
package var isResponse = true
|
|
package var error: NetworkLogger.DecodingError?
|
|
package var sourceURL: URL?
|
|
|
|
package init(contentType: NetworkLogger.ContentType? = nil, originalSize: Int64, metadata: [String : String]? = nil, isResponse: Bool = true, error: NetworkLogger.DecodingError? = nil, sourceURL: URL? = nil) {
|
|
self.contentType = contentType
|
|
self.originalSize = originalSize
|
|
self.metadata = metadata
|
|
self.isResponse = isResponse
|
|
self.error = error
|
|
self.sourceURL = sourceURL
|
|
}
|
|
}
|
|
|
|
extension NetworkTaskEntity {
|
|
package var requestFileViewerContext: FileViewerViewModelContext {
|
|
FileViewerViewModelContext(
|
|
contentType: originalRequest?.contentType,
|
|
originalSize: requestBodySize,
|
|
metadata: metadata,
|
|
isResponse: false,
|
|
error: nil
|
|
)
|
|
}
|
|
|
|
package var responseFileViewerContext: FileViewerViewModelContext {
|
|
FileViewerViewModelContext(
|
|
contentType: response?.contentType,
|
|
originalSize: responseBodySize,
|
|
metadata: metadata,
|
|
isResponse: true,
|
|
error: decodingError,
|
|
sourceURL: currentRequest?.url.flatMap(URL.init)
|
|
)
|
|
}
|
|
|
|
/// - returns `nil` if the task is an unknown state. It may happen if the
|
|
/// task is pending, but it's from the previous app run.
|
|
package func state(in store: LoggerStoreProtocol?) -> NetworkTaskEntity.State? {
|
|
let state = self.state
|
|
if state == .pending, let sessionID = store?.currentSessionID {
|
|
// Read via KVC so a NULL stored value (allowed by Core Data because
|
|
// `session` is implicitly optional in the model) is surfaced as
|
|
// `nil` instead of trapping the ObjC->Swift UUID bridge.
|
|
let taskSession = value(forKey: "session") as? UUID
|
|
if taskSession != sessionID {
|
|
return nil
|
|
}
|
|
}
|
|
return state
|
|
}
|
|
}
|