Swift: optional array count

19,249

Solution 1

That looks like the simpler way.

The Objective-C code is shorter only because nil is also a form of 0, being a C-based language.

Since swift is strongly typed you don't have such a shorthand. In this specific case it requires a little more effort, but in general it saves you most of the headaches caused by loose typing.


Concerning the specific case, is there a reason for making the array optional in the first place? You could just have an empty array. Something like this might work for you:

var myArray: Array<String> = []

func numberOfObjectsInMyArray() -> Int {
   return myArray.count
}

(Source for this information)

Solution 2

Try using the nil coalescing operator.

According to the Apple Documentation:

The nil coalescing operator (a ?? b) unwraps an optional a if it contains a value, or returns a default value b if a is nil.

So your function could look like this:

    func numberOfObjectsInMyArray() -> Int {
        return (myArray?.count ?? 0)
    }

I agree with others that this could be a bad idea for a number of reasons (like making it look like there is an array with a count of "0" when there isn't actually an array at all) but hey, even bad ideas need an implementation.

EDIT:

So I'm adding this because two minutes after I posted this answer, I came across a reason for doing exactly what the author wants to do.

I am implementing the NSOutlineViewDataSource protocol in Swift. One of the functions required by the protocol is:

optional func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: AnyObject?) -> Int

That function requires that you return the number of children of the item parameter. In my code, if the item has any children, they will be stored in an array, var children: [Person]?

I don't initialize that array until I actually add a child to the array.

In other words, at the time that I am providing data to the NSOutlineView, children could be nil or it could be populated, or it could have once been populated but subsequently had all objects removed from it, in which case it won't be nil but it's count will be 0. NSOutlineView doesn't care if children is nil - all it wants to know is how many rows it will need to display the item's children.

So, it makes perfect sense in this situation to return 0 if children is nil. The only reason for calling the function is to determine how many rows NSOutlineView will need. It doesn't care whether the answer is 0 because children is nil or because it is empty.

return (children?.count ?? 0) will do what I need. If children is nil it will return 0. Otherwise it will return count. Perfect!

Solution 3

How about using optional for return value?

var myArray: Array<String>?

func numberOfObjectsInMyArray() -> Int? {
    return myArray?.count
}

I think that this way is safer.

(Source for this information)

Share:
19,249
Ashley Mills
Author by

Ashley Mills

Highly experienced Swift / Objective-C iOS developer and consultant: old-school geek

Updated on June 20, 2022

Comments

  • Ashley Mills
    Ashley Mills almost 2 years

    In Objective-C, if I had the following property:

    @property (strong, nonatomic) NSArray * myArray;
    

    A method to return a number of objects in myArray would look like:

    - (NSInteger) numberOfObjectsInMyArray
    {
        return [self.myArray count];
    }
    

    This would return either the number of objects in the array, or 0 if myArray == nil;

    The best equivalent I can think of for doing this in Swift is:

    var myArray: Array<String>?
    
    func numberOfObjectsInMyArray() -> Int
    {
       return myArray ? myArray!.count : 0
    }
    

    So checking the optional array contains a value, and if so unwrap the array and return that value, otherwise return 0.

    Is this the correct way to do this? Or is there something simpler?