简体   繁体   English

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

[英]Working with array with different data types in Swift

I'm working on a music application that is able to play a playlist of songs, I have two data types representing a song in my project; 我正在开发一个能够播放歌曲播放列表的音乐应用程序,我的项目中有两种表示歌曲的数据类型; "Track" which is of NSManagedObject for songs saved on the device by the user, and "JSONTrack" which represents songs decodable from a json web service. “ Track”是NSManagedObject的用户存储在设备上的歌曲,“ JSONTrack”是代表可从json网络服务解码的歌曲。 Users should be able to add both types to a an array of playlist. 用户应该能够将这两种类型添加到播放列表数组中。 How do I achieve this with Swift, making an array for the different data types and work on that array: My current code handling one of the data types looks like this: 如何使用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

}

handling next and previous selection. 处理下一个和上一个选择。 I would like to do the same for two different types of songs which are represented by two different data types. 我想对由两种不同数据类型表示的两种不同类型的歌曲执行相同的操作。

Use a protocol that has the methods/properties necessary for next and previous actions. 使用具有下一个和上一个操作所需的方法/属性的协议。 Have both of your track types implement the protocol. 让两种轨道类型都实现该协议。 Have your array have the type of the protocol. 让您的阵列具有协议的类型。

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

class JSONTrack: Track {
    // implementation
}

class CoreDataTrack: Track {
    // implementation
}

let tracks = [Track]()

Multiple solutions to your problem here 在这里为您的问题提供多种解决方案

1. Use a protocol 1.使用协议

You could make both JSONTrack and Track conforms to a protocol named TrackProtocol for instance with common method names. 您可以使JSONTrackTrack符合名为TrackProtocol的协议,例如具有通用方法名称。 Then you could manipulate your array of TrackProtocol seamlessly. 然后,您可以无缝地操作TrackProtocol数组。

Best solution 最佳解决方案

2. Use an enum 2.使用一个枚举

Create a TrackEnum enum containing both. 创建一个包含两者的TrackEnum枚举。

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

Then your array is array of TrackEnum and you extract every time which one it is. 然后,您的数组就是TrackEnum数组,并且每次提取时都提取它。

3. Use Any 3.使用任何

You can do an array of Any and check at runtime for the content type. 您可以做一个Any数组,并在运行时检查内容类型。

Worst solution. 最糟糕的解决方案。

Using a protocol is probably the most common, but enum also works well. 使用协议可能是最常见的方法,但enum也可以正常工作。

To elaborate on the enum option: 要详细说明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"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM