5

We have the practice of using safe subscript when accessing any element in a collection. Below is the extension we have.

extension Collection {
    subscript(safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

But when I try to use this with a binding object, it gives me an error saying

Extraneous argument label 'safe:' in subscript

Below is the problematic code

struct MyView: View {
    @ObservedObject var service: service

    var body: some View {
        List {
            ForEach(service.items.indices) { index in
                Toggle(isOn: self.$service.items[safe: index]?.isOn ?? false) {  // Error: Extraneous argument label 'safe:' in subscript
                    Text("isOn")
                }
            }
        }
    }
}
user1366265
  • 1,306
  • 1
  • 17
  • 28
  • Why do you need a “safe subscript” if you know that `index` is from `item.indices`? – Martin R Sep 24 '19 at 14:14
  • 1
    I *assume* that the compiler error is misleading, and the actual problem is that your safe subscript returns an *optional.* – Martin R Sep 24 '19 at 14:16
  • Yes! That was an oversight on my part, but I still get the same error even after chaining. I edited the question above. – user1366265 Sep 24 '19 at 14:55

2 Answers2

5

Two issues:

  1. You don't need to use items[safe: index], because you are given only valid indices by items.indices. You will never have an index that is outsides the bounds of the array.

  2. You can't use items[safe: index], because self.$service.items is a Binding<[Item]>, which is not a Collection, so your extension to Collection doesn't apply.

Just remove the safe: and you're good to go.

See the end of this answer for more detail.

John M.
  • 8,892
  • 4
  • 31
  • 42
  • 1
    I don't agree with point #1 because there are cases in which indices are invalid and will cause an index out of bounds crash which I'm facing right now, so there must be a way to use a safe subscript with a binding array. – JAHelia Feb 22 '20 at 13:56
1

The diagnostic message is confusing, but the problem is that your subscript returns an optional, but you're treating it like a non-optional. You're going to have to handle the case where it returns nil.

Personally I think this approach is fighting the system. You'd be better off using ForEach(service.items). Rather than "safe" subscripts, avoid subscripts entirely.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • ForEach(service.items) did not work unfortunately and I had to use indices. – user1366265 Sep 24 '19 at 14:52
  • Yes! That was an oversight on my part, but I still get the same error even after chaining. I edited the question above. – user1366265 Sep 24 '19 at 14:55
  • In this case, you actually need to use subscripts, and its safe to do so. See this answer: https://stackoverflow.com/a/58070916/3088606 – John M. Sep 24 '19 at 14:58