# Stuck on using structures

**URL:** <https://forums.swift.org/t/stuck-on-using-structures/19716>\
**Category:** Using Swift\
**Created:** [January 23, 2019, 1:34am UTC](https://forums.swift.org/t/stuck-on-using-structures/19716 "2019-01-23T01:34:43Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![twix](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/twix/32/5884_2.png) [@twix](https://forums.swift.org/u/twix)\
**Post date:** [January 23, 2019, 1:34am UTC](https://forums.swift.org/t/stuck-on-using-structures/19716/1 "2019-01-23T01:34:43Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [January 23, 2019, 4:52am UTC](https://forums.swift.org/t/stuck-on-using-structures/19716/2 "2019-01-23T04:52:54Z")

</div>

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`](https://developer.apple.com/documentation/swift/codable) and use appropriate encoder/decoder to read from/write to file.

It might look something like:

```swift
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:

```swift
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.

---

<div class="post-metadata">

**Author:** ![twix](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/twix/32/5884_2.png) [@twix](https://forums.swift.org/u/twix)\
**Post date:** [January 24, 2019, 2:40am UTC](https://forums.swift.org/t/stuck-on-using-structures/19716/3 "2019-01-24T02:40:44Z")

</div>

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",
        		}
    		]
	}
}

```

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [January 24, 2019, 3:15am UTC](https://forums.swift.org/t/stuck-on-using-structures/19716/4 "2019-01-24T03:15:02Z")

</div>

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](https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types) on how to make structure that converts to/from JSON nicely.

---

<div class="post-metadata">

**Author:** ![twix](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/twix/32/5884_2.png) [@twix](https://forums.swift.org/u/twix)\
**Post date:** [January 24, 2019, 6:23pm UTC](https://forums.swift.org/t/stuck-on-using-structures/19716/5 "2019-01-24T18:23:21Z")

</div>

` 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. 😁

```
   {
    "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]()
}

```

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [January 24, 2019, 7:38pm UTC](https://forums.swift.org/t/stuck-on-using-structures/19716/6 "2019-01-24T19:38:53Z")

</div>

In the `addSong` function:

> [@twix](#):
>
> playlist.objectTypes.append(song)

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.

---

<div class="post-metadata">

**Author:** ![twix](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/twix/32/5884_2.png) [@twix](https://forums.swift.org/u/twix)\
**Post date:** [January 25, 2019, 4:54pm UTC](https://forums.swift.org/t/stuck-on-using-structures/19716/7 "2019-01-25T16:54:40Z")

</div>

I have updated my post.
