-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSwiftUIDebugRandomBackgroundColor.swift
93 lines (77 loc) · 2.84 KB
/
SwiftUIDebugRandomBackgroundColor.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//
// SwiftUIDebugRandomBackgroundColor.swift
// SwiftUIDebugRandomBackgroundColor
//
// Created by acevif ([email protected]) on 2023-03-26.
//
import SwiftUI
#if DEBUG
fileprivate let debugBackgroundColors = [
Color.red,
Color.orange,
Color.yellow,
Color.green,
Color.cyan,
Color.blue,
Color.indigo,
Color.purple,
Color.gray,
]
fileprivate let baseRandomSeed: Int = 3_276_482_673_742_026_387
public extension View {
/// A modifier to set random background color to debug SwiftUI's View.
/// Random background colors are equal across different executions of your program.
/// To change background color, set some new random integer to `additionalRandomSeed`
func debugRandomBackgroundColor(
additionalRandomSeed: Int = 1_234_567_890,
filenameAsRandomSeed: String = #file,
lineNumberAsRandomSeed: Int = #line,
columnNumberAsRandomSeed: Int = #column,
functionNameAsRandomSeed: String = #function
) -> some View {
var hasher = DeterministicHasher()
baseRandomSeed.hash(into: &hasher)
filenameAsRandomSeed.hash(into: &hasher)
lineNumberAsRandomSeed.hash(into: &hasher)
columnNumberAsRandomSeed.hash(into: &hasher)
functionNameAsRandomSeed.hash(into: &hasher)
additionalRandomSeed.hash(into: &hasher)
let hash: Int = hasher.finalize()
let randomIndex = ((hash % debugBackgroundColors.count) + debugBackgroundColors.count) % debugBackgroundColors.count
assert(randomIndex >= 0 && randomIndex < debugBackgroundColors.count)
let randomColor = debugBackgroundColors[randomIndex]
return background(randomColor)
}
}
// djb2 hash function (xor version)
// hash(i) = hash(i - 1) * 33 ^ str[i]
struct DeterministicHasher {
private var hash: Int! = 5381 // maybe djb2 magic number
mutating func combine(values: [Int]) {
hash = values
.reduce(hash) { hash, value in
((hash << 5) &+ hash) ^ value
}
}
mutating func finalize() -> Int {
guard let hash else {
fatalError()
}
defer { self.hash = nil }
return hash
}
}
protocol DeterministicHashable {
func hash(into hasher: inout DeterministicHasher)
}
extension Int: DeterministicHashable {
func hash(into hasher: inout DeterministicHasher) {
hasher.combine(values: [self])
}
}
extension String: DeterministicHashable {
func hash(into hasher: inout DeterministicHasher) {
hasher.combine(values: unicodeScalars.map { Int($0.value) })
}
}
#endif