2

I need to retrieve a setting (with Swift):

var highScoreNumber: NSInteger = 0
var returnValue: [NSInteger]? = NSUserDefaults.standardUserDefaults().objectForKey("food") as? [NSInteger]

if (returnValue != nil) {
    highScoreNumber = returnValue as NSInteger
}

I tried this and other variations of the code and I always get

'NSInteger?' not convertible to 'NSInteger'

This is my first foray into Swift, so

  1. Am I missing something simple in the conversion?
  2. Is there a better way to retrieve an NSInteger from settings?
nhgrif
  • 61,578
  • 25
  • 134
  • 173
AngryHacker
  • 59,598
  • 102
  • 325
  • 594
  • 3
    You should use Int instead of NSInteger – Leo Dabus May 22 '15 at 22:04
  • possible duplicate of [In Swift, how do I avoid both optionals and nil object references?](http://stackoverflow.com/questions/27622871/in-swift-how-do-i-avoid-both-optionals-and-nil-object-references) – nhgrif May 22 '15 at 22:05
  • 1
    Is there a specific reason you want to use NSInteger instead of Int for example? – Bas May 22 '15 at 22:08
  • `NSInteger` vs `Int` is irrelevant to the question being asked, but I do agree that there's no reason to use `NSInteger` here. – nhgrif May 22 '15 at 22:10

1 Answers1

5

When converting a nullable value to a non-nullable one, there are many good options to choose from.

But in your case, you have two issues. One is the array you’re fetching from NSUserDefaults is an array of integers, so you need to decide which one you want from that array.

If it’s the first one you want, you can use the first property. You can use optional chaining to get it. And since it’s a high score, you probably want to default to zero if it’s not present.

Here’s that in one line:

let returnValue = NSUserDefaults.standardUserDefaults().objectForKey("food") as? [Int]

let highscore = returnValue?.first ?? 0

Things to note about the above: there’s no need to give the type to the left of the = if the type is unambiguously determined by what lies to the right of the =. And it’s better to prefer Int over NSInteger.

The returnValue?.first says “if returnValue is nil, then nil, else the value of first (which, itself, returns nil if the array is empty).” The ?? says “if the left of ?? is nil, then the value on the right of nil, else the unwrapped value from the left”.

That said – do you really mean to store an array? Or do you really just want to store a single integer in the defaults and then get that out directly?

let highscore = NSUserDefaults.standardUserDefaults().integerForKey("food")
// and elsewhere in your code, when saving
NSUserDefaults.standardUserDefaults().setInteger(highscore, forKey: "food")

(integerForKey already returns a 0 default when not present rather than an optional, so no need for any unwrapping)

Community
  • 1
  • 1
Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118