Eureka: values() returns double optionals?

Created on 11 Nov 2015  路  3Comments  路  Source: xmartlabs/Eureka

It looks like calling values() on a form returns a dictionary of the form [String: Any??] where the values in the dictionary are actually optional wrapped twice. Is that the intent?

I'm making a form like this:

     form +++ Section("New Class")       
            <<< TextRow(labelTag){ $0.title = "Class Name" }

            <<< PushRow<ClassGroup>(groupTag) { row in
                row.title = "Age Group"
                ...
            }

and later accessing the values...

               let values = form.values()
               let label = values[self.labelTag]!     // label is still an optional
               let group = values[self.groupTag]!     // group is still an optional

If I explicitly unwrap labelTag, it's still an optional. This seems awkward. Is there a reason that this is nest this way, or is this a bug?

Most helpful comment

For my own project, I'm adding an extension with an unwrapped version of the values call as below.

public func unwrappedValues(includeHidden includeHidden: Bool = false) -> [String: Any]{
        let wrapped = self.values(includeHidden: includeHidden)

        var unwrapped = [String:Any]()

        for (k,v) in wrapped {
            unwrapped[k] = v ?? nil
        }

        return unwrapped
    }

All 3 comments

@jaylyerly in swift if we subscript a dictionary with a key it returns an optional type, since the value type of the values() dictionary is Any? it returns a Any??.

I agree that this is not the most elegant solution but i don't have an alternative in the case we add the nil values to the values() result as we are doing now.
You can use form["tagValue"]! if you are completely sure that the form contains a row with "tagValue" as tag value.

Let me know if we can improve that in some way.

Regards

Is there a use case where it's important to store 'nil' in the values() result? I can see how that would allow you to differentiate between "there's no matching key" and "the value for that key is nil", but is that an important distinction? In practice, I haven't run into a case where that's important.

Would it be acceptable to just unwrap the values as the dictionary is being built? Then you'd only get one level of wrapping on the results, which is more in line with general dictionary behavior.

With XLForms, I found checking form values for nil and NSNull to be the most cumbersome part of the process. This is pretty much the swift version of the same problem. I'd love to see that wrinkle go away.

For my own project, I'm adding an extension with an unwrapped version of the values call as below.

public func unwrappedValues(includeHidden includeHidden: Bool = false) -> [String: Any]{
        let wrapped = self.values(includeHidden: includeHidden)

        var unwrapped = [String:Any]()

        for (k,v) in wrapped {
            unwrapped[k] = v ?? nil
        }

        return unwrapped
    }
Was this page helpful?
0 / 5 - 0 ratings