Designated initializer error in one subclass but not others

I'm working on factoring out some behavior in my view models - specifically, reacting to the user typing in a filter field.

So far, two of the subclasses have been factored out just fine, but a third suddenly has errors complaining about needing a convenience initializer. I can't figure out what's different about this one that's causing the errors.

Here's the new base class:

class FilteringListViewModel: ObservableObject
{
  @Published var filter: String = ""
  var sinks: [AnyCancellable] = []
  
  func sinkFilter()
  {
    sinks.append($filter
      .debounce(for: 0.5, scheduler: DispatchQueue.main)
      .sink {
        [weak self] in
        self?.filterChanged($0)
      }
    )
  }
  
  func filterChanged(_ newFilter: String) {}
}

and one of the subclasses that the compiler does not complain about:

class SubmoduleListModel<Manager: SubmoduleManagement>: FilteringListViewModel
{
  let manager: Manager
  let publisher: any RepositoryPublishing

  var unfilteredList: [any Submodule] = []
  @Published var submodules: [any Submodule] = []

  init(manager: Manager, publisher: any RepositoryPublishing)
  {
    self.manager = manager
    self.publisher = publisher
    super.init()
    
    // etc
  }
  // etc
}

but in this one I'm getting errors:

class TagListViewModel<Tagger: Tagging,
                       Publisher: RepositoryPublishing>: FilteringListViewModel
{
  let tagger: Tagger
  let publisher: Publisher

  @Published var tags: [PathTreeNode<Tagger.Tag>] = []

  init(tagger: Tagger, publisher: Publisher) // Designated initializer for 'TagListViewModel<Tagger, Publisher>' cannot delegate (with 'self.init'); did you mean this to be a convenience initializer?
  {
    self.tagger = tagger // 'let' property 'tagger' may not be initialized directly; use "self.init(...)" or "self = ..." instead
    self.publisher = publisher // 'let' property 'publisher' may not be initialized directly; use "self.init(...)" or "self = ..." instead
    self.init() // Missing arguments for parameters 'tagger', 'publisher' in call

    // etc
  }
  // etc
}

I've been going back and forth and I can't figure out why that second class is having errors and the first doesn't. Is there a significant difference I'm missing that could account for this? Could it possibly be a compiler bug?

The core problem is that you wrote self.init() instead of super.init(). The diagnostics fell out of that in a few ways:

  • Oh, you wrote self.init(). Let’s assume you want that but forgot to write convenience.

  • Wait, there isn’t any such initializer on Self. The only initializer is named init(tagger:publisher:). Maybe you meant that one? (The fact that recursive calls are unlikely is not taken into account.)

  • Oh, and convenience initializers don’t initialize properties directly, the delegation is supposed to take care of that.

This was not ideal for your situation! I don’t know exactly what the compiler should have done better, but it might be worth some consideration. Meanwhile, though, hope that gets you unstuck. :-)

Thanks, I was hoping it was something simple like that, that I just wasn't seeing. I did try super.init(), but only after I had changed it to convenience init(), so that didn't work. I just missed trying the combination of super.init() without convenience. Whew!

1 Like