Skip to content

Commit 4d9f64b

Browse files
authored
Address potential preview warnings (#378)
* Address potential preview warnings We currently allow folks to use `prepareDependencies` in the body of a preview, which works great. It does appear that previews have gotten fancier, especially in Xcode 26, where a preview session stays live even during changes to view code. These changes cause the preview body to re-evaluate, triggering `prepareDependencies` all over again, and spitting out a large purple warning into the preview console. The behavior of `prepareDependencies` is to ignore future calls and surface warnings in to catch misuse, but maybe we should only emit these warnings in the application. Preview environments are a bit treacherous as is, with app entry point code leaking into them, and preview trait code executing across multiple previews in a file. And so this branch proposes silencing this warning in previews entirely. Alternatives: - We could shorten the warning to a one-liner. Something like "Xcode Preview: 'prepareDependencies' already called this session. Ignoring." - We could stop showing 'prepareDependencies' as a legit tool for previews and instead push people towards 'withDependencies', though this is not great for ergonomics, especially in non-single entry point systems. Bonus change: This PR also updates the warning about ignoring app entry point dependencies in previews with instructions on how to suppress. But given the above, maybe we actually want to suppress this warning entirely? * Remove preview warning It's not super helpful in practice.
1 parent 4bfe7da commit 4d9f64b

File tree

1 file changed

+43
-42
lines changed

1 file changed

+43
-42
lines changed

Sources/Dependencies/DependencyValues.swift

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,6 @@ public struct DependencyValues: Sendable {
286286
if DependencyValues.isPreparing {
287287
#if canImport(SwiftUI)
288288
if context == .preview, Thread.isPreviewAppEntryPoint {
289-
reportIssue("Ignoring dependencies prepared in preview app entry point")
290289
return
291290
}
292291
#endif
@@ -295,56 +294,58 @@ public struct DependencyValues: Sendable {
295294
let cacheKey = CachedValues.CacheKey(id: TypeIdentifier(key), context: context)
296295
guard !cachedValues.cached.keys.contains(cacheKey) else {
297296
if cachedValues.cached[cacheKey]?.preparationID != DependencyValues.preparationID {
298-
reportIssue(
299-
{
300-
var dependencyDescription = ""
301-
if let fileID = DependencyValues.currentDependency.fileID,
302-
let line = DependencyValues.currentDependency.line
297+
if context != .preview {
298+
reportIssue(
303299
{
300+
var dependencyDescription = ""
301+
if let fileID = DependencyValues.currentDependency.fileID,
302+
let line = DependencyValues.currentDependency.line
303+
{
304+
dependencyDescription.append(
305+
"""
306+
Location:
307+
\(fileID):\(line)
308+
309+
"""
310+
)
311+
}
304312
dependencyDescription.append(
305-
"""
306-
Location:
307-
\(fileID):\(line)
308-
309-
"""
310-
)
311-
}
312-
dependencyDescription.append(
313-
Key.self == Key.Value.self
313+
Key.self == Key.Value.self
314314
? """
315-
Dependency:
316-
\(typeName(Key.Value.self))
317-
"""
315+
Dependency:
316+
\(typeName(Key.Value.self))
317+
"""
318318
: """
319-
Key:
320-
\(typeName(Key.self))
321-
Value:
322-
\(typeName(Key.Value.self))
323-
"""
324-
)
325-
var argument: String {
326-
"\(function)" == "subscript(key:)"
319+
Key:
320+
\(typeName(Key.self))
321+
Value:
322+
\(typeName(Key.Value.self))
323+
"""
324+
)
325+
var argument: String {
326+
"\(function)" == "subscript(key:)"
327327
? "\(typeName(Key.self)).self"
328328
: "\\.\(function)"
329-
}
330-
return """
331-
@Dependency(\(argument)) has already been accessed or prepared.
329+
}
330+
return """
331+
@Dependency(\(argument)) has already been accessed or prepared.
332332
333-
\(dependencyDescription)
333+
\(dependencyDescription)
334334
335-
A global dependency can only be prepared a single time and cannot be accessed \
336-
beforehand. Prepare dependencies as early as possible in the lifecycle of your \
337-
application.
335+
A global dependency can only be prepared a single time and cannot be accessed \
336+
beforehand. Prepare dependencies as early as possible in the lifecycle of your \
337+
application.
338338
339-
To temporarily override a dependency in your application, use 'withDependencies' \
340-
to do so in a well-defined scope.
341-
"""
342-
}(),
343-
fileID: DependencyValues.currentDependency.fileID ?? fileID,
344-
filePath: DependencyValues.currentDependency.filePath ?? filePath,
345-
line: DependencyValues.currentDependency.line ?? line,
346-
column: DependencyValues.currentDependency.column ?? column
347-
)
339+
To temporarily override a dependency in your application, use \
340+
'withDependencies' to do so in a well-defined scope.
341+
"""
342+
}(),
343+
fileID: DependencyValues.currentDependency.fileID ?? fileID,
344+
filePath: DependencyValues.currentDependency.filePath ?? filePath,
345+
line: DependencyValues.currentDependency.line ?? line,
346+
column: DependencyValues.currentDependency.column ?? column
347+
)
348+
}
348349
} else {
349350
cachedValues.cached[cacheKey] = CachedValues.CachedValue(
350351
base: newValue,

0 commit comments

Comments
 (0)