jdmuys
(Jean-Denis Muys)
1
Context: I want to be able to assign/init UInt32 values with four-character strings as in the file type/creator codes of the old days, or magic numbers used in some file formats.
I developed a function that works fine. It calls the max function to make sure to use at most 4 characters from the input string:
let length = max(asciiRepresentation.count, 4)
But this lines doesn't compile when put in an extension to UInt32:
extension UInt32 {
init(asciiRepresentation: String) {
let length = max(asciiRepresentation.count, 4)
var result: UInt32 = 0
var index = asciiRepresentation.startIndex
for _ in 0 ..< length {
let char = asciiRepresentation[index]
let byte: UInt32 = UInt32(char.asciiValue ?? 0)
result = result << 8 + byte
index = asciiRepresentation.index(after:index)
}
self = result
}
}
In my playground (Xcode 11.2.1):
error: CodingDecoding.playground:46:22: error: static member 'max' cannot be used on instance of type 'UInt32'
let length = max(asciiRepresentation.count, 4)
^~~
Self.
My understanding is that the global max function is hidden by the UInt32.max static member that represents the largest possible UInt32 number.
1- Is that correct?
2- Is there a way to call the global max function anyway?
Of course, I can work around that with an if statement easily.
Also feel free to comment on my code: I am a noob, and I guess this code could be written better. I would appreciate the learning experience.
xwu
(Xiaodi Wu)
2
You can disambiguate in such cases using the name of the module. The standard library is named Swift; therefore: Swift.max.
3 Likes
eskimo
(Quinn “The Eskimo!”)
4
Are you sure you want to use max here? If asciiRepresentation has 5 characters, length will be 5 and you’ll index off the end of your string.
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple
ps This is how I’d write your extension:
init?(fourCharCode: String) {
guard
let macRoman = fourCharCode.data(using: .macOSRoman),
macRoman.count == 4
else {
return nil
}
self = macRoman.reduce(0) { soFar, byte in
return soFar << 8 | UInt32(byte)
}
}
Traditional Mac OS four character codes supported non-ASCII values, interpreted as MacRoman.
3 Likes
jdmuys
(Jean-Denis Muys)
5
Duh, of course not max. Typical brain fart (for me). I intended min...
But thank you so much for your rewrite. It brings much value on several levels, for me as a beginner:
- tip about MacRoman (though I am not sure how it applies to a file format such as .MP4)
- failable Initializer
guard
- the use of reduce
- even the use of
| instead of +
Note about String.data(using:):
I had a hard time understanding where this is coming from. This function is nowhere to be found in the Xcode documentation for String. It has a quick help, but that's it. Jumping to definition leads to a page with only imports. Jumping to definition of String leads to a very long file, where this function is missing.
Only googling for it, leads to NSString.data
So this function requires bridging String to NSString. Therefore it requires Foundation. Right?
Overall, I found Xcode documentation difficult to use, of rather little help for reference purposes, and very spotty.
of course, searching for "data" anywhere is not very specific and returns many false positives...
Or perhaps I missed something. Is there documentation on how to use Xcode documentation?
eskimo
(Quinn “The Eskimo!”)
6
though I am not sure how it applies to a file format such as .MP4
That’s an interesting question. MPEG-4’s container format is a ‘child’ of QuickTime, and QuickTime definitely used MacRoman for this. I’m not sure whether they removed that dependency as part of the standardisation process. It’s possible that they didn’t address it at all, and just standardised on the UInt32 values. The only way to know for sure is to look at the MPEG-4 standard itself.
Note about String.data(using:):
I had a hard time understanding where this is coming from.
Indeed. The Quick Help usually has a link to the documentation but that’s not present in this case. I suspect this is because the symbol is implemented in Foundation’s Swift overlay. Regardless, the fact that Xcode won’t take you to the documentation is bugworthy IMO. Please file a bug about that (and post your bug number, just for the record).
… it requires Foundation. Right?
Yes.
So this function requires bridging String to NSString.
If I’m right, and this is part of Foundation’s Swift overlay, the bridging situation is nuanced.
Personally, I don’t lose a lot of sleep worrying about this sort of bridging. If something is slow and I’ve profiled it and the profile shows that bridging is part of the problem, I look into it. Otherwise I just accept it as a part of life.
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple
1 Like
jdmuys
(Jean-Denis Muys)
7
Thanks again. Feedback posted using Feedback Assistant app, with number FB7440716.