You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This does so by introducing a RegistryBuilder that custom units must be attached to, and is used for all Unit lookups. This was (rightfully) required by Swift 6 memory safety, since the existing implementation had issues with shared mutable state. I attempted to minimize breaking changes, but some were required.
Copy file name to clipboardExpand all lines: README.md
+24-35Lines changed: 24 additions & 35 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -118,40 +118,57 @@ For a list of the default units and their conversion factors, see the [`DefaultU
118
118
119
119
## Custom Units
120
120
121
-
To extend this package, users can define their own custom units using `Unit.define`:
121
+
The unit system is backed by a `Registry` that maps unit symbols to their metadata. To add new units, use `RegistryBuilder`, and pass it to any operation that converts from a `String` to a `Unit`:
122
122
123
123
```swift
124
-
let centifoot =try Unit.define(
124
+
let registryBuilder =RegistryBuilder()
125
+
registryBuilder.addUnit(
125
126
name: "centifoot",
126
127
symbol: "cft",
127
128
dimension: [.Length:1],
128
129
coefficient: 0.003048// This is the conversion to meters
129
130
)
131
+
let registry = registryBuilder.registry()
132
+
let centifoot =tryUnit(fromSymbol: "cft", registry: registry)
130
133
131
134
let measurement =Measurement(value: 5, unit: centifoot)
For "non-scientific" units, it is typically appropriate to use the `Amount` quantity. Through this approach, you can easily build up an impromptu conversion system on the fly. For example:
140
153
141
154
```swift
142
-
let apple =try Unit.define(
155
+
let registryBuilder =RegistryBuilder()
156
+
try registryBuilder.addUnit(
143
157
name: "apple",
144
158
symbol: "apple",
145
159
dimension: [.Amount:1],
146
160
coefficient: 1
147
161
)
148
-
149
-
let carton =try Unit.define(
162
+
try registryBuilder.addUnit(
150
163
name: "carton",
151
164
symbol: "carton",
152
165
dimension: [.Amount:1],
153
166
coefficient: 48
154
167
)
168
+
let registry = registryBuilder.registry()
169
+
170
+
let apple =tryUnit(fromSymbol: "apple", registry: registry)
171
+
let carton =tryUnit(fromSymbol: "carton", registry: registry)
155
172
156
173
let harvest =288.measured(in: apple)
157
174
print(harvest.convert(to: carton)) // Prints '6.0 carton'
@@ -160,48 +177,20 @@ print(harvest.convert(to: carton)) // Prints '6.0 carton'
160
177
We can extend this example to determine how many cartons a group of people can pick in a week:
161
178
162
179
```swift
163
-
let person =tryUnit.define(
180
+
tryregistryBuilder.addUnit(
164
181
name: "person",
165
182
symbol: "person",
166
183
dimension: [.Amount:1],
167
184
coefficient: 1
168
185
)
186
+
let person =tryUnit(fromSymbol: "person", registry: registryBuilder.registry())
169
187
170
188
let personPickRate =600.measured(in: apple / .day/ person)
171
189
let workforce =4.measured(in: person)
172
190
let weeklyCartons =try (workforce * personPickRate).convert(to: carton / .week)
173
191
print(weeklyCartons) // Prints '350.0 carton/week'
174
192
```
175
193
176
-
### Adding custom units to the Registry
177
-
178
-
To support deserialization and runtime querying of available units, this package keeps a global registry of the default units. The `Unit.define` method does not insert new definitions into this registry. While this avoids conflicts and prevents race conditions, it also means that units created using `Unit.define` cannot be deserialized correctly or looked up using `Unit(fromSymbol:)`
179
-
180
-
If these features are absolutely needed, and the implications are understood, custom units can be added to the registry using `Unit.register`:
181
-
182
-
```swift
183
-
let centifoot =try Unit.register(
184
-
name: "centifoot",
185
-
symbol: "cft",
186
-
dimension: [.Length:1],
187
-
coefficient: 0.003048// This is the conversion to meters
188
-
)
189
-
```
190
-
191
-
Note that you may only register the unit once globally, and afterwards it should be accessed either by the assigned variable or using `Unit(fromSymbol: String)`.
192
-
193
-
To simplify access, `Unit` may be extended with a static property:
0 commit comments