Swift 5:在实现Equatable with protocol的结构上实现通用数组操作
我的应用程序中有两个符合协议的简单结构,以支持我需要在这两种类型上应用的一些通用操作:Swift 5:在实现Equatable with protocol的结构上实现通用数组操作,swift,swiftui,Swift,Swiftui,我的应用程序中有两个符合协议的简单结构,以支持我需要在这两种类型上应用的一些通用操作: import UIKit protocol Track { var url: URL { get set } } struct TrackFromMediaFile: Track { var url: URL } struct TrackFromAsset: Track { var url: URL } 现在我有了这些结构的列表: var tracks = [Track]()
import UIKit
protocol Track {
var url: URL { get set }
}
struct TrackFromMediaFile: Track {
var url: URL
}
struct TrackFromAsset: Track {
var url: URL
}
现在我有了这些结构的列表:
var tracks = [Track]()
tracks.append(TrackFromMediaFile(url: URL(string: "http://www.remotefile")!))
tracks.append(TrackFromAsset(url: URL(string: "local://localfile")!))
我需要在此曲目列表中查找特定曲目的索引:
// throws:
// Value of protocol type 'Track' cannot conform to 'Equatable'; only struct/enum/class types can conform to protocols
var track = tracks[0]
tracks.firstIndex(of: track)
我试着遵循来自的方法,但没有效果,我无法将这些方法应用到我的示例中
如何实现以通用方式处理曲目数组?不太清楚您想要的是哪种类型的相等。如果要同时检查类型相等性和值相等性,可以这样做:
tracks.firstIndex(where: {
type(of: $0) == type(of: track) && $0.url == track.url
})
tracks.firstIndex(where: { $0.url == track.url })
如果您只想验证url
是否相等,可以这样做:
tracks.firstIndex(where: {
type(of: $0) == type(of: track) && $0.url == track.url
})
tracks.firstIndex(where: { $0.url == track.url })
在Swift中,equalable表示一个值可以与相同类型的其他值进行比较。它不适用于不同类型的值。协议不是类型,它描述类型,所以跟踪本身不能是相等的
如果你打算经常这样做,那么表达“能够检查与协议其他成员的平等性”通常是很方便的。这是不平等的,但肯定是可以表达的。看起来是这样的:
protocol Track {
var url: URL { get set }
func isEqual(to: Track) -> Bool
}
对于已经可均衡的轨迹一致性类型,可以提供默认实现:
extension Track where Self: Equatable {
func isEqual(to other: Track) -> Bool {
guard let other = other as? Self else { return false }
return self == other
}
}
并将您的一致性类型标记为可平衡(swift将自动创建一致性):
这样,代码就更好了:
tracks.firstIndex(where: { $0.isEqual(to: track) })
如果你经常这样做,你当然可以做得更好一点:
extension Collection where Element == Track {
func firstIndex(of track: Track) {
firstIndex(where: { $0.isEqual(to: track) })
}
}
这样,您就可以使用以下语法:
tracks.firstIndex(of: track)
出于好奇,您是否希望
TrackFromMediaFile
和trackfromsete
彼此相等?(我假设它们有你没有在这里列出的属性,是吗?)如果是,你能描述一下你想如何比较它们是否相等吗?我会创建一个带有枚举的公共结构来区分它们。你走错了路。你不应该有一个协议的集合。顺便说一句,如果你真的想遵循这个路径(我不推荐)let index=tracks.firstIndex(其中:{track.url==0.url})
看起来我的问题真的没什么意义(equalable不属于协议)-我只需要使用数组上的where操作符。谢谢!似乎我对协议有错误的理解(我刚开始学习Swift),所以我的问题没有太多意义。您的回答为我指明了正确的方向-我只需要使用一些数组助手方法,如where。