Home > OS >  'subscript(_:)' is unavailable: cannot subscript String with an Int, use a String.Index in
'subscript(_:)' is unavailable: cannot subscript String with an Int, use a String.Index in

Time:09-17

I'm trying to pass the data and got this error: 'subscript(_:)' is unavailable: cannot subscript String with an Int, use a String.Index instead. Here is my code:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: CustomLoopsCell = beatTableView.dequeueReusableCell(withIdentifier: "firstLoopCell", for: indexPath) as! CustomLoopsCell
        
        let beatLoop = overtunePacks[indexPath.row]

        // On the lines which is down I'm getting this error
        let beatDesc = loopsDesc[indexPath.row]
        let beatProd = loopsProd[indexPath.row]
        let beatAudio = loopsAudio[indexPath.row] 
        let beatInst = loopsInst[indexPath.row]
        
        cell.loopNameLabel.text = beatDesc
        cell.producerLabel.text = beatProd
        cell.instrumentLabel.text = beatInst

Here is the code from another view controller, from where I'm passing the data:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let vc = storyboard?.instantiateViewController(identifier: "BeatViewID") as? BeatPackViewController
    vc?.beatInfoCollectName = beatInfoCollect[indexPath.row].name
    vc?.beatProducerName = beatInfoCollect[indexPath.row].producer
    vc?.imageBeat = beatInfoCollect[indexPath.row].imagename
    vc?.loopsAudio = beatAudioCollect[indexPath.row].loopPath
    vc?.loopsDesc = beatAudioCollect[indexPath.row].name
    vc?.loopsInst = beatAudioCollect[indexPath.row].instrument
    vc?.loopsProd = beatAudioCollect[indexPath.row].producer
    self.navigationController?.pushViewController(vc!, animated: true)
}

Here is my variables in second view controller, where I'm passing data:

var loopsAudio = ""
    var loopsDesc = ""
    var loopsInst = ""
    var loopsProd = ""

Here is what I want to display:

struct BeatLoops: Decodable {
        let name: String
        let instrument: String
        let loopPath: String
        let producer: String
        
        var songURL : URL {
            let components = loopPath.components(separatedBy: ".")
            guard components.count == 2,
                  let url = Bundle.main.url(forResource: components[0], withExtension: components[1]) else { fatalError("Audio file is missing") }
            return url
        }
    }

I'm parsing this data and have instance: var beatAudioCollect = [BeatLoops]()

CodePudding user response:

Seems that you are trying to get Substring from a loopsDesc String here

let beatDesc = loopsDesc[indexPath.row]
...
let beatInst = loopsInst[indexPath.row]

The point is that you can't just get String's characters using subscription index.

If you want to get a character from a String, you should get it's Substring with a specified range.

Like that:

let index = loopsDesc.index(loopsDesc.startIndex, offsetBy: 1)
let mySubstring = loopsDesc[..<index]

Or another way:

1 - add this extension to a String:

extension StringProtocol {
subscript(offset: Int) -> Character {
    self[index(startIndex, offsetBy: offset)]
  }
}

2 - use it like that

let input = "My String Here"
let char = input[3]
//or
let char = String(input[3])

Please see another stackoverflow question related to that.

But it's unsafe method and I would suggest to use another way to get params (for example store them in Array, not in String)

CodePudding user response:

Your design is wrong.

Extracting single characters from a string in a table view to be displayed in different rows makes no sense.

Actually you are passing two objects to the second view controller, an infoCollect object and an audioCollect object.

First of all rather than extracting all properties just pass the entire objects.

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let vc = storyboard?.instantiateViewController(identifier: "BeatViewID") as! BeatPackViewController
    vc.infoCollect = beatInfoCollect[indexPath.row]
    vc.audioCollect = beatAudioCollect[indexPath.row]
    self.navigationController?.pushViewController(vc, animated: true)
}

By the way using multiple arrays as data source is strongly discouraged!.


In the second controller replace the String properties with

var infoCollect : Loop!
var audioCollect : BeatLoops!

If the structs are declared inside in first view controller you have to write

var infoCollect : BPLibraryViewController.Loop!
var audioCollect : BPLibraryViewController.BeatLoops!

Then remove the table view and add UILabels instead. In viewDidLoad assign the values for example

imageBeatLabel.text = infoCollect.name
loopsAudioLabel.text = audioCollect.loopPath
  • Related