Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI: Safe subscript for binding array

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")
                }
            }
        }
    }
}
like image 789
user1366265 Avatar asked Sep 24 '19 14:09

user1366265


2 Answers

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.

like image 59
John M. Avatar answered Oct 12 '22 17:10

John M.


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.

like image 30
Rob Napier Avatar answered Oct 12 '22 17:10

Rob Napier