Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-8040] NSNumber cast to UInt64 fails when uint64Value succeeds #3673

Closed
mattneub opened this issue Jun 19, 2018 · 7 comments
Closed

[SR-8040] NSNumber cast to UInt64 fails when uint64Value succeeds #3673

mattneub opened this issue Jun 19, 2018 · 7 comments

Comments

@mattneub
Copy link

Previous ID SR-8040
Radar None
Original Reporter @mattneub
Type Improvement
Status Resolved
Resolution Invalid
Additional Detail from JIRA
Votes 0
Component/s Foundation
Labels Improvement
Assignee None
Priority Medium

md5: 5276f0131a07c88ff9841cb42fbfa00d

Issue Description:

This arises because with MPMediaItem I'm receiving persistent ID values as NSNumber that I'm having trouble converting to a Swift number. When I log the troublesome values to the console, I get big negative numbers like -341037401921622877 even though this is supposed to be a UInt64. So that's the value I'm using in the example:

let i = -341037401921622877
let n = NSNumber(value:i)
let u1 = n.uint64Value // 9223372036854775807, the desired answer
let u2 = n as? UInt64 // nil

My understanding of numerics is a bit shaky, but surely one's instinct is to say that if `uint64Value` can correctly extract the UInt64 value from this NSNumber, then `as? UInt64` should be able to do it as well. And the whole idea of allowing us to cast directly from NSNumber to a Swift numeric type was that it would replace grappling directly with NSNumber methods. Perhaps I've misunderstood https://github.com/apple/swift-evolution/blob/master/proposals/0170-nsnumber_bridge.md but I thought that this was the sort of thing it says ought to work.

@belkadan
Copy link

My understanding is that uint64Value and the other properties always succeed, doing whatever reinterpretation and truncation necessary to cram the value into the type. as?, on the other hand, will actually respect the bounds of the type being used. @phausler, is that a correct description?

@phausler
Copy link
Member

Yup, that is 100% on point.

@belkadan
Copy link

Ah, I see the weirdness: MPMediaEntityPersistentID is a UInt64, but the NSNumber is being created as a signed 64-bit value. Which wouldn't have made a difference back in Objective-C.

@mattneub
Copy link
Author

I'm with you so far, but then how do I convert this thing into a UInt64 correctly using Swift methods rather than calling NSNumber `uint64Value`?

It might help if I describe the use case a little more. I have an MPMediaItem, and I say:

let id = myMediaItem.value(forProperty:MPMediaItemPropertyAlbumPersistentID)

This comes back as an Any?, but it is supposed to be an NSNumber wrapping a CUnsignedLongLong, i.e. a UInt64. I want that number! I used to be able to get it by casting to UInt64 and now I can't.

I noticed this because I was successfully force-casting — and then one day I started crashing instead. I am thinking that this might be because SE-1070 changed the behavior of the cast.

Of course I can fix this by going back to what I did back in Swift 2, namely cast to NSNumber and call `.uint64Value`. But that seems so unSwifty...!

@mattneub
Copy link
Author

Ooooh it looks like you've just answered the question: the issue is buried in the Media Player framework, not in Swift...?

@mattneub
Copy link
Author

Okay, I see that I can get the right answer by saying

let u : UInt64 = i as? UInt64 ?? UInt64.max - UInt64(-i) + 1

or

let u = UInt64.init(bitPattern: Int64(i))

But golly gee.

@phausler
Copy link
Member

FYI your assertion of

UInt64(bitPattern:Int64(i))

Is exactly what uint64Value does under the hood.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 5, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants