I've a tree of (different) structs
which I want to show in an NSOutlineView
. I've also written an update function which determines the move/insert/reload operations on the outline view.
To make the update function more generic, I've written a protocol that makes the different structs similar:
protocol Outlinable: Equatable, Identifiable {
associatedtype T: Outlinable
var children: [T]? { get }
}
The children
array is an optional to mark that a node might not have children.
I've made two structs conform to this protocol:
struct ImageWithErrors: Decodable, FetchableRecord {
let imageFile: ImageFile
let imageFileErrors: [ImageFileError]
}
struct LayerImagesListItem: Decodable, FetchableRecord {
let layer: Layer
let imageFiles: [ImageWithErrors]
}
extension LayerImagesListItem: Identifiable, Outlinable {
var id: Int64 { get { layer.id! }}
var children: [ImageWithErrors]? { get { imageFiles }}
}
extension ImageWithErrors: Identifiable, Outlinable {
var id: Int64 { get { -imageFile.id! }}
var children: [Outlinable]? { get { return nil }}
}
The LayerImagesListItem
is a root struct, while the ImageWithErrors
is (currently) a leave struct. But on this last struct I get the errors:
Type 'ImageWithErrors' does not conform to protocol 'Outlinable'
Protocol 'Outlinable' can only be used as a generic constraint because it has Self or associated type requirements
I've tried replacing [Outlinable]
with [Any]
but that doesn't solve anything.
How can I tell Swift that ImageWithErrors
is never going to return any children
?
If ImageWithErrors
can never have children, you could use Never
.
extension Never: Outlinable {
var children: [Never]? { nil }
}
extension ImageWithErrors: Identifiable, Outlinable {
var id: Int64 { get { -imageFile.id! }}
var children: [Never]? { get { return nil }}
}
if let children = ImageWithErrors(imageFile: .init(), imageFileErrors: []).children {
for child in children {
print("there will never be any \(child)")
}
} else {
print("children is always nil")
}
It is meant to be used:
as the return type when declaring a closure, function, or method that unconditionally throws an error, traps, or otherwise does not terminate.
but since ImageWithErrors.children
is of type [Never]
and always return nil
that should not be an issue.