在 Swift 中使用具有不同数据类型的数组

Posted

技术标签:

【中文标题】在 Swift 中使用具有不同数据类型的数组【英文标题】:Working with array with different data types in Swift 【发布时间】:2018-05-16 09:21:17 【问题描述】:

我正在开发一个能够播放歌曲播放列表的音乐应用程序,我的项目中有两种数据类型代表一首歌曲; “Track”是 NSManagedObject 的,用于用户保存在设备上的歌曲,“JSONTrack”表示可从 json Web 服务解码的歌曲。用户应该能够将这两种类型添加到播放列表数组中。如何使用 Swift 实现这一点,为不同的数据类型创建一个数组并在该数组上工作: 我当前处理其中一种数据类型的代码如下所示:

var playlistTracks = [Track]()

@objc fileprivate func handlePrevTrack() 
    if playlistTracks.isEmpty 
        return
    

    let currentTrackIndex = playlistTracks.index  (tr) -> Bool in
        return self.track?.trackTitle == tr.trackTitle && self.track?.albumTitle == tr.albumTitle
    

    guard let index = currentTrackIndex else  return 

    let prevTrack: Track

    if index == 0 
        let count = playlistTracks.count
        prevTrack = playlistTracks[count - 1]
     else 
        prevTrack = playlistTracks[index - 1]
    

    self.track = prevTrack


@objc func handleNextTrack() 
    if playlistTracks.count == 0 
        return
    

    let currentTrackIndex = playlistTracks.index  (tr) -> Bool in
        return self.track?.trackTitle == tr.trackTitle && self.track?.albumTitle == tr.albumTitle
    

    guard let index = currentTrackIndex else  return 

    let nextTrack: Track
    if index == playlistTracks.count - 1 
        nextTrack = playlistTracks[0]
     else 
        nextTrack = playlistTracks[index + 1]
    

    self.track = nextTrack


处理下一个和上一个选择。我想对由两种不同数据类型表示的两种不同类型的歌曲执行相同的操作。

【问题讨论】:

【参考方案1】:

使用具有下一步和先前操作所需的方法/属性的协议。让您的两种轨道类型都实现该协议。让您的数组具有协议的类型。

protocol Track 
    title: String
    albumTitle: String
    // other method and properties


class JSONTrack: Track 
    // implementation


class CoreDataTrack: Track 
    // implementation


let tracks = [Track]()

【讨论】:

我打算建议这个,甚至是enum,它可能是一种或另一种类型。我想我更喜欢这个协议:D 但是我的CoreDataTrack是NSManagedObject的,Xcode通常不想编辑那些自动生成的文件,我还能让它符合协议吗? 好的,我找到了一种手动生成 CoreData 模型类的方法,这样我就可以自定义它们以使它们采用协议。谢谢【参考方案2】:

这里有多种解决您的问题的方法

1。使用协议

您可以使JSONTrackTrack 都符合名为TrackProtocol 的协议,例如具有通用方法名称。然后你可以无缝地操作你的TrackProtocol 数组。

最佳解决方案

2。使用枚举

创建一个包含两者的TrackEnum 枚举。

enum TrackEnum 
    case json(JSONTrack)
    case coreData(Track)

那么你的数组是TrackEnum 的数组,你每次提取它是哪一个。

3。使用任意

您可以创建一个Any 数组并在运行时检查内容类型。

最坏的解决方案。

【讨论】:

【参考方案3】:

使用协议可能是最常见的,但enum 也很有效。

详细说明enum 选项:

class JSONTrack: NSObject 
class OtherTrack: NSObject 

enum Track 
    case jsonTrack(JSONTrack)
    case otherTrack(OtherTrack)

    // enum can be handy if you want to do type checking
    // and e.g. present specific data for that type
    var label: String 
        switch self 
        case .jsonTrack:
            return "Json track"
        case .otherTrack:
            return "Other track"
        
    


let jsonTrack = JSONTrack()
let otherTrack = OtherTrack()
let tracks: [Track] = [Track.jsonTrack(jsonTrack), Track.otherTrack(otherTrack)]

let labelOfTrack1 = tracks.first!.label
print(labelOfTrack1)
// prints "Json track"

【讨论】:

以上是关于在 Swift 中使用具有不同数据类型的数组的主要内容,如果未能解决你的问题,请参考以下文章

具有自定义类类型的 Swift CoreData 保存属性

Swift 中具有/不同单元格类型的可重用数据源

使用 Swift 将具有相同类型的字典分组到具有完整键和值的数组中

swift 存放多类型的容器

在 Swift 中继承具有自己类型和存储属性的数组

Swift中使用Cocoa数据类型,有哪些操作?