1

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]()

8
  • 2
    Did you check these related questions? stackoverflow.com/… Commented Sep 8, 2021 at 7:30
  • Yes, but there is no answer for my problem Commented Sep 8, 2021 at 7:32
  • 1
    You need to update your question include the declaration of the variables that are causing the problem. I would also suggest updating your question to include a minimum, reproducible example Commented Sep 8, 2021 at 7:33
  • Check, I've updated Commented Sep 8, 2021 at 7:35
  • 2
    You probably want to get a value from an array by index rather than from a string (a single character) Commented Sep 8, 2021 at 7:39

2 Answers 2

2

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)

Sign up to request clarification or add additional context in comments.

7 Comments

As you can see, I'm passing data from the first view controller to the variables which I have created in second view controller.
your error is not about passing data, it is about accessing the loopsDesc[indexPath.row] where indexPath.row is an Int. As mentioned by "Roman Shinyavski" answer, you cannot do that. You need to use a "special" index just for strings, not a Int. Read the error message, it tells you what to do. Look at the docs for Accessing and Modifying a String in swift at: docs.swift.org/swift-book/LanguageGuide/…
I think you don't understand what I want, only to pass data from the structure
you mean you don't get the error that you showing us?
I'm getting only this error which I've wrote in this question
|
0

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

10 Comments

On this line: vc?.audioCollect = beatAudioCollect[indexPath.row] - I'm getting an error: Cannot assign value of type 'BPLibraryViewController.BeatLoops' to type 'BeatLoops'
You have to declare the proper matching type. I just guessed what it is.
Proper matching type, what do you mean?
Te proper type of beatInfoCollect and beatAudioCollect
Now they are: var beatInfoCollect = [Loop]() var beatAudioCollect = [BeatLoops]()
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.