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?
@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
}
Most helpful comment
For my own project, I'm adding an extension with an unwrapped version of the values call as below.