如何使用 swift 从多个本地 JSON 文件将数据加载到 table 视图中的标签

How to load data from more then one local JSON file to the labels in table view using swift

我有两个文件夹,每个文件夹都包含图像、歌曲名称和 JSON 文件: 需要弄清楚如何从每个 JSON 加载数据。也许它应该是一个数组。 JSON 个文件:

第二个文件夹:

{
    "beatpacktwo":
    {
        "twoloops": [
            {
                "name": "Midnight",
                "producer": "Stefan Guy",
                "count": "32",
                "genre": "R&B",
                "imagename": "beatpacktwo"
            }
        ]
    }
}

第一个文件夹:

{
    "beatpackone":
    {
        "oneloops": [
            {
                "name": "Away we go",
                "producer": "Tubular Kingz",
                "count": "28",
                "genre": "Lo-fi Hip Hop",
                "imagename": "beatpackone"
            }
        ]
    }
}

这是每个文件夹的 swift 文件:BeatPackTwo

import Foundation
import UIKit

struct BeatPackTwo: Decodable {
    let beatpacktwo: BeatPackDataTwo
}

struct BeatPackDataTwo: Decodable {
    let oneloops: [LoopTwo]
}

struct LoopTwo: Decodable {
    let name: String
    let producer: String
    let count: String
    let genre: String
    let imagename: String
}

public class DataLoaderTwo {
    
    func parseJSONtwo() -> BeatPackDataTwo? {
        guard let url = Bundle.main.url(forResource: "beatpacktwo", withExtension: "json") else {
            print("\n-------> bundle path error")
            return nil
        }
        
        do {
            let jsonData = try Data(contentsOf: url)
            let response = try JSONDecoder().decode(BeatPackTwo.self, from: jsonData)
            print("\n-------> response: \(response)")
            return response.beatpacktwo
        }
        catch {
            print("\n====> error: \(error)" )
            return nil
        }
    }
}

BeatPackOne:

import Foundation
import UIKit

struct BeatPackOne: Decodable {
    let beatpackone: BeatPackDataOne
}

struct BeatPackDataOne: Decodable {
    let oneloops: [LoopOne]
}

struct LoopOne: Decodable {
    let name: String
    let producer: String
    let count: String
    let genre: String
    let imagename: String
}

public class DataLoaderOne {
    
    func parseJSONone() -> BeatPackDataOne? {
        guard let url = Bundle.main.url(forResource: "beatpackone", withExtension: "json") else {
            print("\n-------> bundle path error")
            return nil
        }
        
        do {
            let jsonData = try Data(contentsOf: url)
            let response = try JSONDecoder().decode(BeatPackOne.self, from: jsonData)
            print("\n-------> response: \(response)")
            return response.beatpackone
        }
        catch {
            print("\n====> error: \(error)" )
            return nil
        }
    }
}

我试图在视图控制器中创建一个实例,但现在我只能从一个 JSON 文件中加载数据,需要从每个文件中加载,并且部分中的行数应该 return 文件夹的数量。这是我在视图控制器中的表视图:

extension BPLibraryViewController: UITableViewDataSource, UITableViewDelegate, UIScrollViewDelegate {
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 180
    }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return loopsName.count
    }
    
    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: S.newOneCell, for: indexPath) as! BeatPackLibraryCell
        
        let loopsCount = loopsName[indexPath.row]  //Instance of our arrays from JSON
        
        cell.loopNameLabel.text = loopsCount.name
        cell.producerNameLabel.text = loopsCount.producer
        cell.loopsCountLabel.text = String(beatLoops.count)
        cell.genreLabel.text = loopsCount.genre
        cell.firstBeatButtonLabel.setImage(UIImage(named: loopsCount.imagename), for: .normal)
        
        cell.delegate = self
        cell.selectionStyle = .none
        cell.tag = indexPath.row
        
        if let playingCell = currentPlayingIndex, playingCell == indexPath.row {
            cell.firstBtnOutlet.setImage(UIImage(named: "pauseButtonPack.png"), for:
                                            .normal)
        } else {
            cell.firstBtnOutlet.setImage(UIImage(named: "playButtonPack.png"), for:
                                            .normal)
        }
        return cell
    }

应该是这样的:

没有理由在你的情况下有两个 JSON 具有不同的结构:

让我们改为:

{
    "beatPack":
    {
        "loops": [
            {
                "name": "Midnight",
                "producer": "Stefan Guy",
                "count": "32",
                "genre": "R&B",
                "imagename": "beatpacktwo"
            }
        ]
    }
}

{
    "beatPack":
    {
        "loops": [
            {
                "name": "Away we go",
                "producer": "Tubular Kingz",
                "count": "28",
                "genre": "Lo-fi Hip Hop",
                "imagename": "beatpackone"
            }
        ]
    }
}

我保留了 beatPackloops,但这甚至可能与保留它们无关。

那么我们的模型有:

struct TopLevel: Decodable {
    let beatPack: BeatPack
}

struct BeatPack: Decodable {
    let loops: [Loop]
}

struct Loop: Decodable {
    let name: String
    let producer: String
    let count: String
    let genre: String
    let imagename: String
}

然后,解析它们:

在你的BPLibraryViewController中:

var loopsName = [Loop]()

func parseJSON(file fileName: String) -> BeatPack? {
    guard let url = Bundle.main.url(forResource: fileName, withExtension: "json") else {
        print("\n-------> bundle path error: File \(fileName) not found")
        return nil
    }
    
    do {
        let jsonData = try Data(contentsOf: url)
        let response = try JSONDecoder().decode(TopLevel.self, from: jsonData)
        print("\n-------> response: \(response)")
        return response.beatPack
    }
    catch {
        print("\n====> error: \(error)" )
        return nil
    }
}



func retrieveLoops() -> [Loop] {
    let packOne = parseJSON(file: "beatpackone")
    let packTwo = parseJSON(file: "beatpacktwo")
    var loops = [Loop]()
    loops.append(contentsOf: packOne?.loops ?? [])
    loops.append(contentsOf: packTwo?.loops ?? [])
    // or, if you prefer more explicitly:
    // if let loopOne = packOne?.loops {
    //     loops.append(contentsOf: loopOne)
    // }
    return loops
}

func prepareInit() {
    loopsNames = retrieveLoops()
    tableView.reloadData()
}