swift - Swift 5:在使用协议实现 Equatable 的结构上实现通用数组操作
问题描述
我的应用程序中有 2 个符合协议的简单结构,以启用我需要在这两种类型上应用的一些通用操作:
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)
我尝试遵循https://stackoverflow.com/a/46719045/319905和https://developer.apple.com/videos/play/wwdc2015/408/的方法无济于事,我无法将这些适应我的例子。
如何以通用方式实现处理轨道数组?
解决方案
目前尚不清楚您正在寻找什么样的平等。如果你想检查类型相等和值相等,你可以这样做:
tracks.firstIndex(where: {
type(of: $0) == type(of: track) && $0.url == track.url
})
如果您只想验证url
是否相等,您可以这样做:
tracks.firstIndex(where: { $0.url == track.url })
在 Swift 中,Equatable 意味着一个值可以与其他相同类型的值进行比较。它不适用于不同类型的值。协议不是类型,它描述类型,因此 Track 本身不能是 Equatable。
如果您要经常这样做,表达“能够检查与协议的其他成员是否相等”通常很方便。这不是平等的,但它肯定是你可以表达的东西。它看起来像这样:
protocol Track {
var url: URL { get set }
func isEqual(to: Track) -> Bool
}
对于已经 Equatable 的 Track-conforming 类型,您可以提供默认实现:
extension Track where Self: Equatable {
func isEqual(to other: Track) -> Bool {
guard let other = other as? Self else { return false }
return self == other
}
}
并将您的一致性类型标记为 Equatable (swift 将自动创建一致性):
struct TrackFromMediaFile: Track, Equatable { ... }
struct TrackFromAsset: Track, Equatable { ... }
这样,代码就更好了:
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)
推荐阅读
- ios - UIPasteboard 没有提供价值
- deep-learning - Leaky-ReLU 的缺点是什么?
- android - SFB 文件从 ArCore Android 中的 FBX 文件生成后丢失了 Y 轴值
- go - 如何在一个字段中创建具有 nil 值的地图,然后将其编组为 json?
- google-api - 尝试 Google API 存储桶:特定服务帐户的 testIamPermissions
- python - 使用 Python 从 SFTP 服务器下载超过 5 天的文件
- javascript - 当 x 轴隐藏在 Slider 中时,y 轴溢出
- javascript - 有没有办法打印 PDF 但手动设置值而不是从主 HTML 中获取它们?
- java - 执行准备语句时出现 java.sql.SQLSyntaxErrorException
- api - 消费者只在开始时两次消费相同的消息