Ron Modz
Ron Modz

Reputation: 41

Assign UITableView Cell label text from Swift dictionary

I am trying to get a value from a swift dictionary to display as cell texts. I am getting error:

Type 'Any' has no subscript members

cell.audioLabel.text = audiofiles["filetitle"] <-line producing error

I believe I may have set the variables incorrectly, the value is being passed using segue from another tableview using the didSelectRowAt.

var audios = Array<Any>() <- gets from another controller

This is my current viewcontroller code:

import UIKit

class DetailViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    @IBOutlet weak var audioTable: UITableView!
    @IBOutlet weak var descText: UITextView!
    @IBOutlet weak var clickButton: UIButton!

    var practitle = String()
    var desc = String()
    var hasAudio = Int()
    var audios = Array<Any>()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationItem.title = practitle

        descText.text = desc

        if hasAudio != 0 {
            clickButton.isHidden = false
        }

        print(audios)
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return audios.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "audiocell", for: indexPath) as! DetailViewCell

        let audiofiles = audios[indexPath.row]

        cell.audioLabel.text = audiofiles["filetitle"]

        return cell
    }

When I use

print(audios)

The result that I get is:

[demoApp.Audiofile(id: 1, filetitle: "Sample file one", filename: "breath5mins", fileformat: "mp3"), demoApp.Audiofile(id: 2, filetitle: "Sample file two", filename: "breath10mins", fileformat: "mp3"), demoApp.Audiofile(id: 3, filetitle: "Sample file three", filename: "breath20mins", fileformat: "mp3")]

How can I use the filetitle as the label texts for my cell?

The goal is to display the title and open another view on cell click and allow the user to click a button on the new view and play the mp3 file.

Upvotes: 0

Views: 941

Answers (3)

Stephen O&#39;Connor
Stephen O&#39;Connor

Reputation: 1475

The reason you get the error is Any is an object with no definition. You can cast it into an AudioFile like this:

let audiofiles = audios[indexPath.row] as! AudioFile

If audios is an array of AudioFile only then declare it as such and you can use it the way you described.

Upvotes: -1

vadian
vadian

Reputation: 285180

Apparently the object is not a Swift dictionary, it's a custom class or struct.

You are fighting Swift's strong type system. Don't do that.

Declare audios with the static type

var audios = Array<AudioFile>()

and use dot notation instead of insecure KVC (which does not work anyway in this case).

cell.audioLabel.text = audiofiles.filetitle

Upvotes: 2

Paulw11
Paulw11

Reputation: 114974

You have declared your array as Array<Any> - which means that the array can contain anything; the elements of the array don't even all need to be the same type. As a result, the Swift compiler doesn't know what type of thing it is getting from audios[indexPath.row]; it could be a dictionary, it could be an array or it could be an integer. When you try and use subscripting, the compiler gives you an error because it doesn't know whether the item supports subscripting - i.e. an Int doesn't, and Any could be an Int.

Don't use Any or AnyObject in Swift if you know the actual type; Swift's type safety allows it to eliminate a large number of potential runtime issues at compile time by know what types things are.

From the print statement it appears that your array contains Audiofile instances (presumably a struct or class you have defined, not a dictionary). You should, therefore, declare audios correctly:

var audios = Array<Audiofile>()

You can then access the object's properties in your cellForRow:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "audiocell", for: indexPath) as! DetailViewCell

    let audiofiles = audios[indexPath.row]

    cell.audioLabel.text = audiofiles.filetitle

    return cell
}

Upvotes: 1

Related Questions