0

After converting the for loop to Swift 3 I got the error "Type 'Any' has no subscript members"

for inputKey in inputKeys where attributes[inputKey]?[kCIAttributeClass] == "NSNumber"
                                .....................^
{

}

I would expect to add something like

for inputKey in inputKeys where attributes[inputKey]as?[String:Any][kCIAttributeClass] == "NSNumber"

but this doesn't work :-( Still have some problems with the Swift syntax.

3ef9g
  • 781
  • 2
  • 9
  • 19
  • Where / how is `attributes` defined? Basically the compiler must know the type of all subscripted objects. – vadian Mar 15 '17 at 16:55
  • Actually, `where` is still supported for `for in` loops. – jlehr Mar 15 '17 at 16:56
  • Possible duplicate of [Type 'Any' Has no Subscript Members in xcode 8 Swift 3](http://stackoverflow.com/questions/39516199/type-any-has-no-subscript-members-in-xcode-8-swift-3) – JAL Mar 15 '17 at 17:09
  • @JAL also AnyObject doesn't help – 3ef9g Mar 15 '17 at 17:14

1 Answers1

2

It looks like you want attributes to actually be [String: [String: String]] - a dictionary of dictionaries.

Either that, or you can cast attributes[inputKey] to [String:String].

I think this would work:

for inputKey in inputKeys where (attributes[inputKey] as? [String:String])?[kCIAttributeClass] == "NSNumber"

Edit per comments:

Since attributes isn't actually guaranteed to be [String: [String: String]], but only [String: [String: Any]] (and maybe not even that), you'll need an extra as? cast to be safe.

With that many casts on one line, I think it would be better to put the test into a guard statement at the beginning of the for body instead of having such a huge where clause.

Uncommon
  • 3,323
  • 2
  • 18
  • 36
  • Thanks, that was exactly what was needed :-) – 3ef9g Mar 15 '17 at 17:22
  • While this will compile, it may not produce the expected results. According to the [documentation](https://developer.apple.com/reference/coreimage/cifilter/1437661-attributes), the dictionaries in `attributes` will probably be of type `[String:Any]`. – Caleb Mar 15 '17 at 17:24
  • 1
    In that case you may need to cast `attributes[inputKey]` to `[String:Any]`, and cast the result of the `[kCIAttributeClass]` subscript with `as? String`. With all that casting, it might be cleaner to use a `guard` statement at the beginning of the loop body instead of such a complex `where` clause. – Uncommon Mar 15 '17 at 17:30
  • 2
    You should probably add the comment as an edit to the original answer as the cast to [String:String] will fail most (if not all) of the time. – Caleb Mar 15 '17 at 17:32
  • If it's set to [String:Any] and comparing to "NSNumber", you'll get the error "Binary operator '==' cannot be applied to operands of type 'Any?' and 'String'" – Chewie The Chorkie Aug 23 '18 at 19:27