Swift recently added support for Int128. However, they do need NOT seem to be supported in SwiftData. Now totally possible I'm doing something wrong too.
I have the project set to macOS 15 to use a UInt128 in @Model class as attribute. I tried using a clean Xcode project with Swift Data choosen in the macOS app wizard.
Everything compiles, but it fails at runtime in both my app and "Xcode default" SwiftData:
SwiftData/SchemaProperty.swift:380: Fatal error: Unexpected property within Persisted Struct/Enum: Builtin.Int128
with the only modification to from stock is:
@Model
final class Item {
var timestamp: Date
var ipv6: UInt128
init(timestamp: Date) {
self.timestamp = timestamp
self.ipv6 = 0
}
}
I have tried both Int128 and UInt128. Both fails exactly the same. In fact, so exactly, when using UInt128 it still show a "Int128" in error message, despite class member being UInt128 .
My underlying need is to store an IPv6 addresses with an app, so the newer UInt128 would work to persist it. Since Network Framework IPv6Address is also not compatible, it seems, with SwiftData. So not a lot of good options, other an a String. But for an IPv6 address that suffers from that same address can take a few String forms (i.e. "0000:0000:0000:0000:0000:0000:0000:0000" =="0:0:0:0:0:0:0:0" == "::") which is more annoying than having a few expand Int128 as String separator ":".
Ideas welcomed. But potentially a bug in SwiftData since Int128 is both a Builtin and conforms to Codable, so from my reading it should work.
Ziqiao and I have been talking about this behinds the scenes (-: so I’m going to chime in on this topic from a networking perspective.
IMO it’s best to avoid integer types when storing IP addresses. An IPv4 address is not a UInt32
. Rather, it’s a sequence of 4 bytes. Similarly for an IPv6 address. If you treat IP addresses as integer types, you end up creating more problems for yourself. The classic example of this is the byte ordering behaviour of BSD Sockets, where you have to remember to apply {h,n}to{n,h}{s,l}
in the right places. If in_addr
were defined like this:
struct in_addr {
uint8 s_addr[4];
};
the world would be a much better place.
Coming back to your main issue, I see two ways forward here:
-
Data
-
String
The first is obvious. The second does have the ambiguity problem you’ve described, but there are two easy solutions to that:
-
Always use the canonical textual representation format, as defined in RFC 5952. It’s safe to assume that the string representation of the
IPv6Address
type returns that format. -
Or, if you want sorting to work, render each byte to hex and concatenate the result. If you insert colons [1] the result will even be parseable by
IPv6Address
.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] Like so:
let str = addr.rawValue
.map { [$0 >> 4, $0 & 0x0f] }
.joined()
.map { String($0, radix: 16) }
.chunks(ofCount: 4)
.map { x in x.joined() }
.joined(separator: ":")