Skip to content

Commit 8b0fa66

Browse files

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Source: Point-Free, Swift Composable Architecture, RuntimeWarnings.swift
2+
// https://github.com/pointfreeco/swift-composable-architecture/blob/399bc83dcfc7bdcee99f7f6cc0a687ca29e8494b/Sources/ComposableArchitecture/Internal/RuntimeWarnings.swift
3+
//
4+
// Based on: Point-Free, Unobtrusive runtime warnings for libraries (2022-01-03)
5+
// https://www.pointfree.co/blog/posts/70-unobtrusive-runtime-warnings-for-libraries
6+
7+
#if DEBUG
8+
import os
9+
import XCTestDynamicOverlay
10+
11+
// NB: Xcode runtime warnings offer a much better experience than traditional assertions and
12+
// breakpoints, but Apple provides no means of creating custom runtime warnings ourselves.
13+
// To work around this, we hook into SwiftUI's runtime issue delivery mechanism, instead.
14+
//
15+
// Feedback filed: https://gist.github.com/stephencelis/a8d06383ed6ccde3e5ef5d1b3ad52bbc
16+
private let rw = (
17+
dso: { () -> UnsafeMutableRawPointer in
18+
let count = _dyld_image_count()
19+
for i in 0..<count {
20+
if let name = _dyld_get_image_name(i) {
21+
let swiftString = String(cString: name)
22+
if swiftString.hasSuffix("/SwiftUI") {
23+
if let header = _dyld_get_image_header(i) {
24+
return UnsafeMutableRawPointer(mutating: UnsafeRawPointer(header))
25+
}
26+
}
27+
}
28+
}
29+
return UnsafeMutableRawPointer(mutating: #dsohandle)
30+
}(),
31+
log: OSLog(subsystem: "com.apple.runtime-issues", category: "ComposableArchitecture")
32+
)
33+
#endif
34+
35+
@_transparent
36+
@inline(__always)
37+
func runtimeWarning(
38+
_ message: @autoclosure () -> StaticString,
39+
_ args: @autoclosure () -> [CVarArg] = [],
40+
file: StaticString? = nil,
41+
line: UInt? = nil
42+
) {
43+
#if DEBUG
44+
let message = message()
45+
if _XCTIsTesting {
46+
if let file = file, let line = line {
47+
XCTFail(String(format: "\(message)", arguments: args()), file: file, line: line)
48+
} else {
49+
XCTFail(String(format: "\(message)", arguments: args()))
50+
}
51+
} else {
52+
unsafeBitCast(
53+
os_log as (OSLogType, UnsafeRawPointer, OSLog, StaticString, CVarArg...) -> Void,
54+
to: ((OSLogType, UnsafeRawPointer, OSLog, StaticString, [CVarArg]) -> Void).self
55+
)(.fault, rw.dso, rw.log, message, args())
56+
}
57+
#endif
58+
}

0 commit comments

Comments
 (0)