6

I'm trying to deny access to a certain view controller if the userDefault is empty, but the code doesn't seem to work. To be a bit more clear, I'm saving a favorite-list to a userDefault. This is my code:

 if UserDefaults.standard.array(forKey: "favorites") == nil {

        navigationController?.popToRootViewController(animated: true)
        return
    }

The error is Index out of range, which means that the whole block is ignored (the code after this block runs and since the user default is empty it crashes when trying to retrieve information that isn't there).

The funny thing is, the code works the first time I try to enter the viewController (it denies me access). But if I favorite mark an object (save to userDefault), then un-favorite the same object (userDefault becomes empty), and enter the viewController, the program crashes.

I have tried:

if let favExist = UserDefaults.standard.array(forKey: "favorites") {
        print("")
        print("FAV EXISTS")
        print("")

    }else {
        print("")
        print("NOPE")
        print("")
        navigationController?.popToRootViewController(animated: true)
        return
    }

...and the same problem persists. In print() the log tells me FAV EXISTS after I favorite mark, then un-favorite mark, then try accessing the page (even though the userDefault now should be empty).

I have also tried code from other threads. The suggested code to solve my problem from the other thread was:

let defaults = UserDefaults.standard

    if (!defaults.bool(forKey: "favorites")) {
        defaults.set(true, forKey: "favorites")
    }

I'm not really sure how to implement it though? Where do I use this? And what does it do?

Any idea what's wrong?

Joakim Sjöstedt
  • 824
  • 2
  • 9
  • 18
  • 1
    Possible duplicate of [How to check a single time if UserDefaults is empty](https://stackoverflow.com/questions/38340958/how-to-check-a-single-time-if-userdefaults-is-empty) – Konstantinos Natsios Oct 21 '17 at 19:41
  • Don't you mean `if UserDefaults.standard.array(forKey: "favorites") != nil {` ? if the root controller needs that array stored in user defaults you should check it is NOT nil – Leo Dabus Oct 21 '17 at 20:20
  • You should a look also at the nil coalescing operator and registering defaults https://developer.apple.com/documentation/foundation/userdefaults/1417065-register – Leo Dabus Oct 21 '17 at 21:42
  • Make sure the array saved has enough elements when accessing its elements using subscript. You should always iterate the array using its indices. `for index in yourArray.indices {`or check if the array.indices contais the index before subscripting your array with that index – Leo Dabus Oct 21 '17 at 21:51
  • You should edit your question and show the code that it is throwing the error – Leo Dabus Oct 21 '17 at 21:55

4 Answers4

13

It´s enough to do this:

if let favorites = UserDefaults.standard.array(forKey: "favorites") {
     // userDefault has a value
} else {
     // userDefault is nil (empty)
}

Update:
You need to make a check within the if-statement if your arrat has any values too:

if let favorites = UserDefaults.standard.array(forKey: "favorites") {
    print("Favorites exists")

    if favorites.isEmpty {
        print("Favorites is empty")
    } else {
        print("Favorites is not empty, it has \(favorites.count) items")
    }
} else {
    print("Favorites is nil")
}
Tapas Pal
  • 7,073
  • 8
  • 39
  • 86
Rashwan L
  • 38,237
  • 7
  • 103
  • 107
1

When you set the UserDefaults Array also set a BOOL to UserDefaults. When you recover the Bool it won't crash even if it hasn't been set.

var favouritesset = UserDefaults.standard.bool(forKey: "favoritesset")

if favouritesset == true {
//Then Recover the Array
var array = UserDefaults.standard.array(forKey: "favorites")
}
Niall Kehoe
  • 416
  • 5
  • 17
  • array(forKey:) already returns an optional value. Why would he need to have a different key for storing a boolean only for that? – Leo Dabus Oct 21 '17 at 21:40
  • I don't understand. When the `favouriteset` is false it won't look for the array and when it is true it will look. And since the bool is true the array must be set. – Niall Kehoe Oct 22 '17 at 11:27
0

OK, Rashwan L solved it for me. Thing was, my code (and suggested code by others) checked whether or not userDefault existed or not - it didn't bother whether there was a value stored or not. To work around the problem, I had to test if favExist.count == 0 was true. If true, user is blocked from the page and prevented from accessing the rest of the code. Se below:

if let favExist = UserDefaults.standard.array(forKey: "favorites") {
        if(favExist.count == 0)
        {
            navigationController?.popToRootViewController(animated: true)
            return
        }

    }else {
        navigationController?.popToRootViewController(animated: true)
        return
    }
Joakim Sjöstedt
  • 824
  • 2
  • 9
  • 18
0

You do like this:

    if UserDefaults.standard.array(forKey: "favs") != nil {
     // userDefault has a value
    } else {
     // userDefault is nil (empty)
    }
nanospeck
  • 3,388
  • 3
  • 36
  • 45