Reputation: 45
I'm new to Swift (and iOS programming), and I'm struggling with properly finding whether certain data structures contain elements. More specifically, I have created an empty set into which I want to insert elements after further calculations:
var moviesInItinerary : NSMutableSet? = nil
Then, I want to proceed with the calculations only if the set is empty or if it doesn't contain a given element. I wrote this condition like this:
if((moviesInItinerary?.count == 0) || (!moviesInItinerary!.containsObject(movies[currentMovie.row].title)))
However, when I try to run this code, I'm getting this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
What is the safe way to perform these checks?
Upvotes: 0
Views: 1468
Reputation: 154671
You can simply do:
if !(moviesInItinerary?.containsObject(movies[currentMovie.row].title) == true) {
// When we get here, we know either moviesInItinerary is nil, or the NSMutableSet
// does not contain our movie.
}
This works because optional chaining makes moviesinItinerary?.constainsObject(movies[currentMovie.row].title)
return a value of type Bool?
. If it is nil
because moviesInItinerary
is nil, then it won't compare to true
. If moviesInItinerary
isn't nil
, then containsObject
will either return true
or false
and then the comparison with work if it is true
. It is unnecessary to also check if count
is zero
, because that is redundant. A set with count
zero will obviously not contain your object.
Upvotes: 2
Reputation: 138171
Typing moviesInItinerary
as NSMutableSet?
means that NSMutableSet
can be nil, and it appears that you never assign an object to it.
This line here:
var moviesInItinerary : NSMutableSet? = nil
declares that moviesInItinerary
itself is either an NSMutableSet
, or nil
(and in this specific case, since you never assign it anything other than nil
, it stays like that).
Swift encourages people to use immutable variables and to avoid nullable variables whenever it makes sense to. If you always need moviesInItinerary
to be a valid set, and you don't need to overwrite it with a different set, the best way to declare it would be:
let moviesInItinerary = NSMutableSet()
From the right-hand side of the assignment, Swift knows that the type of moviesInItinerary
should be NSMutableSet
, so there's no need to explicitly type it. It also knows that it cannot be nil
, and that it cannot point to a different object after its initialization.
Since it can't be nil
, you also no longer need to use the .?
operator for it: just .
will be enough.
Upvotes: 1
Reputation: 11341
You should read up on Swift's optional types. Going in blindly without understanding them is bound to lead to programming errors.
var moviesInItinerary : NSMutableSet? = nil
I'd change that to this:
var moviesInItinerary : NSMutableSet = NSMutableSet()
Then, moviesInItinerary cannot be nil. If you really want it to be an optional type (meaning it can possibly be nil), then change your condition to the following:
if let moviesSet = moviesInItineraray? {
// use moviesSet in here. It will not be nil.
}
Upvotes: 4