XCode中Swift字典取值为nil:为何键9.0无法获取对应值?
Hey there, let's break down exactly what's going on here and how to fix it.
First, Let's Address the Obvious: 9.0 Isn't in Your Dictionary
Looking at your modeDict, all keys are between 0.8 and 1.2 in 0.1 increments. If your slider's value is actually hitting 9.0, that key simply doesn't exist in the dictionary—so returning nil is expected behavior.
Double-check your slider's minimumValue and maximumValue settings in Xcode. It sounds like you might have accidentally set the max value to 9.0 instead of 1.2, letting the slider go way beyond the range your dictionary covers.
The Likely Hidden Culprit: Float Precision Issues
If that's a typo (and you meant a value like 1.0 is returning nil instead of 9.0), this is a super common pitfall with using Float (or even Double) as dictionary keys.
Here's the problem: Decimal values like 0.1 can't be represented exactly in binary floating-point format. When you calculate round(sender.value / step) * step, the result might look like 1.0 when printed, but under the hood it's actually a value like 0.99999994 or 1.0000001. Since dictionary lookups require an exact match, this tiny discrepancy means your code can't find the matching key in modeDict.
Notice how 0.8 works? That's a coincidence—0.8 can be represented more accurately in binary than values like 1.0 after your rounding calculation.
Fixes to Solve This Problem
Fix 1: Use Integer Keys (Most Reliable)
The simplest way to avoid floating-point precision issues is to convert your speed values to integers. Multiply by 10 to turn 0.8 into 8, 0.9 into 9, etc., then use those integers as your dictionary keys:
// Updated dictionary with integer keys let modeDict: [Int: String] = [ 8: "Pls delete game, you noob", 9: "Pff, girl", 10: "Optimal", 11: "Very Hard", 12: "Almost Unreal" ] @IBAction func sliderAction(_ sender: UISlider) { speed = round(sender.value / step) * step sender.value = speed // Convert speed to integer key let speedKey = Int(speed * 10) speedLabel.text = modeDict[speedKey] print(sender.value) print(speedLabel.text) }
Fix 2: Check for Approximate Matches
If you need to keep using Float keys, loop through the dictionary to find a key within a tiny tolerance (like 0.0001) of your slider value:
@IBAction func sliderAction(_ sender: UISlider) { speed = round(sender.value / step) * step sender.value = speed // Find the closest matching key let matchingEntry = modeDict.first { (key, _) in abs(key - sender.value) < 0.0001 } speedLabel.text = matchingEntry?.value print(sender.value) print(speedLabel.text) }
Fix 3: Use an Enum (Type-Safe Option)
For even more safety, define an enum to represent your speed modes, then map your slider value to the corresponding case:
enum SpeedMode: Float { case noob = 0.8 case girl = 0.9 case optimal = 1.0 case veryHard = 1.1 case almostUnreal = 1.2 var displayText: String { switch self { case .noob: return "Pls delete game, you noob" case .girl: return "Pff, girl" case .optimal: return "Optimal" case .veryHard: return "Very Hard" case .almostUnreal: return "Almost Unreal" } } } @IBAction func sliderAction(_ sender: UISlider) { speed = round(sender.value / step) * step sender.value = speed if let mode = SpeedMode(rawValue: speed) { speedLabel.text = mode.displayText } else { speedLabel.text = "Unknown Mode" // Handle out-of-range values } print(sender.value) print(speedLabel.text) }
Wrap-Up
If you truly are seeing 9.0 in your print output, fix your slider's range settings. Otherwise, the floating-point precision issue is the problem, and any of the fixes above will resolve it.
内容的提问来源于stack exchange,提问作者brain

