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

时间:2018-05-16 09:21:18

标签: ios arrays swift

我正在制作能够播放歌曲播放列表的音乐应用程序,我有两种数据类型代表我项目中的一首歌曲; "轨道"这是用户在设备上保存的歌曲的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

}

处理下一个和上一个选择。我想对由两种不同数据类型表示的两种不同类型的歌曲做同样的事情。

3 个答案:

答案 0 :(得分:1)

使用具有下一个和上一个操作所需的方法/属性的协议。让两种轨道类型都实现协议。让您的阵列具有协议类型。

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

class JSONTrack: Track {
    // implementation
}

class CoreDataTrack: Track {
    // implementation
}

let tracks = [Track]()

答案 1 :(得分:1)

此处为您的问题提供多种解决方案

1。使用协议

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

最佳解决方案

2。使用枚举

创建包含两者的TrackEnum枚举。

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

然后你的数组是TrackEnum的数组,你每次都会提取它。

3。使用任何

您可以执行Any数组,并在运行时检查内容类型。

最糟糕的解决方案。

答案 2 :(得分:0)

使用协议可能是最常见的,但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"