Stuck on using structures

I was trying since few days ago to encode and read data by types but I'm unable to do it without some help.

Right now I'm able to get count or title with this lines:

playlist?.objects.count ?? 0
playlist?.objects[indexPath.item].title

What I want to archive is something like this.

playlist?.objects.TYPEIWANT.count ?? 0
playlist?.objects.TYPEIWANT[indexPath.item].title

Here is my code:

class Playlist: Equatable, Codable {
    
    init(name: String, objects: [Object] = []) {
        self.name = name
        self.objects = objects
    }
    
    // MARK: Properties
    
    let name: String
    var objects: [Object]
}

func ==(lhs: Playlist, rhs: Playlist) -> Bool {
    return lhs.name == rhs.name && lhs.objects == rhs.objects
}

class Object: Equatable, Codable {

    enum Group: String, Codable {
        case LiveChannel
        case TelevisionShow
        case Movie
        case unsupported
        
        static let allGroups: [Group] = [.LiveChannel, .TelevisionShow, .Movie, .unsupported]
    }
    
    init(type: Group.RawValue, title: String, group: String, url: String, logo: String) {
        
        self.type = type
        self.title = title
        self.group = group
        self.url = url
        self.logo = logo
    }

    // MARK: Properties
    let type: String
    let title: String
    let group: String
    let url: String
    let logo: String
}

func ==(lhs: Object, rhs: Object) -> Bool {
    return lhs.title == rhs.title && lhs.group == rhs.group
}

extension Object {
    
    static func create(type: String, title: String, group: String, url: String, logo: String, playlist: Playlist) {
        let object = Object(type: type, title: title, group: group, url: url, logo: logo)
        ObjectsController.shared.add(object: object, toPlaylist: playlist)
    }
}

When an object is created the type is stored.

Object.create(type: Object.Group.TelevisionShow.rawValue, title: title, group: loadedGroup, url: line, logo: match(for: "\".*tvg-logo=\"([^\"]*)", in: line), playlist: playlist)

But I don't know how to get or manage just one Group type.

It seems you’re trying to read data from string-based file, like JSON or XML. Please correct me if I’m wrong.

If that’s the case you can make the data structure be Codable and use appropriate encoder/decoder to read from/write to file.

It might look something like:

import Foundation

struct Playlist: Equatable, Codable {       
    let name: String
    var songs: [Song]
}

struct Song: Equatable, Codable {
    enum Group: String, CaseIterable, Codable {
        case Scenery, Iceland, Lola, Baby
    }
    
    var type, title: String, group: Group, url, logo: URL
}    

then you can read data like this:

let data = """
{
    "name": "Some Name",
    "songs": [
        {
            "type": "Type One",
            "title": "Song One",
            "group": "Scenery",
            "url": "www.google.com",
            "logo": "www.google.com",
        }, {
            "type": "Type Two",
            "title": "Song Two",
            "group": "Iceland",
            "url": "www.google1.com",
            "logo": "www.google1.com",
        }
    ]
}
""".data(using: .ascii)!

let decoder = JSONDecoder()
let playlist = try? decoder.decode(Playlist.self, from: data)

Note that Swift will synthesize Equatable only for struct and enum but not class. If you need to use class you’ll need to implement == yourself.

1 Like

Thank you for your helpful answer.

I will read a file and will encode to json.

But If I want to struct this way, how should the code look like?

let data = """
{
    "name": "Some Name",
    "group": "classical" -> Songs: [
        		{
           			 "type": "Type One",
           			 "title": "Song One",
           			 "group": "Scenery",
          			  "url": "www.google.com",
          			  "logo": "www.google.com",
       			 }, {
         			   "type": "Type Two",
        			    "title": "Song Two",
        			    "group": "Iceland",
        			    "url": "www.google1.com",
        			    "logo": "www.google1.com",
        		}
    		]

		"ambiance" -> Songs: [
        		{
           			 "type": "Type One",
           			 "title": "Song One",
           			 "group": "Scenery",
          			  "url": "www.google.com",
          			  "logo": "www.google.com",
       			 }, {
         			   "type": "Type Two",
        			    "title": "Song Two",
        			    "group": "Iceland",
        			    "url": "www.google1.com",
        			    "logo": "www.google1.com",
        		}
    		]
	}
}

I’m pretty sure that’s not valid JSON, it could be some of its variance though. If that’s the case, you may need to find the Encoder/Decoder from the internet, or code one yourself.

If it actually JSON, you can check out this on how to make structure that converts to/from JSON nicely.

` Im not 100% sure if this will help me to archive my goal, which is to be able to save and access objects from playlist->objectTypes->Song.name but I try to encode in this format and I hope it will work.

Im just having a month of experience in swift, and didn't coded anything since 2014. :grin:

   {
    "objectTypes":[{
            "Song":[{
                "name":" ",
                "url":" "
            }],
            "TelevisionShow":[{
                "name":" ",
                "url":" "
            }]
        }
    ]
}


class Playlist: Codable {

    init(name: String, objectTypes: [ObjectTypes] = []) {
        self.name = name
        self.objectTypes = objectTypes
    }

    // MARK: Properties

    let name: String
    var objectTypes: [ObjectTypes]
}

class ObjectTypes: Codable {

    init( song: [Song] = [], televisionShow: [TelevisionShow] = [] ) {
        self.song = song
        self.televisionShow = televisionShow
    }

    let song: [Song]
    let televisionShow: [TelevisionShow]
}

class Song: Equatable, Codable {

    init(name: String, artist: String) {
        self.name = name
        self.artist = artist
    }

    // MARK: Properties

    let name: String
    let artist: String
}

func ==(lhs: Song, rhs: Song) -> Bool {
    return lhs.name == rhs.name && lhs.artist == rhs.artist
}
I don't know how to continue from here:

class PlaylistController {

    static let shared = PlaylistController()

    init() {
        playlists = loadFromPersistentStore()
    }

    func add(playlistWithName name: String) {
        let playlist = Playlist(name: name)
        playlists.append(playlist)
        saveToPersistentStore()
    }

    func addSong(song: Song, toPlaylist playlist: Playlist) {
        playlist.objectTypes.append(song) <- Cannot convert value of type 'Song' to expected argument type 'ObjectTypes'
    }

    var playlists = [Playlist]()
}

In the addSong function:

What does objectTypes look like? It seems you’re having array of ObjectType, but you’re trying to insert Song to it. And that Song and ObjectType are different types hence the mismatch, and error.

1 Like

I have updated my post.