【问题标题】:How to load data from more then one local JSON file to the labels in table view using swift如何使用swift将数据从一个以上的本地JSON文件加载到表格视图中的标签
【发布时间】:2025-12-14 19:10:01
【问题描述】:

我有两个文件夹,每个文件夹都包含图像、歌曲名称和 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 文件中加载数据,需要从每个文件中加载,部分中的 numberofrows 应该返回文件夹的计数。这是我在视图控制器中的表格视图:

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
    }

应该是这样的:

【问题讨论】:

  • LoopTwoLoopOne 是一样的,不是吗?为什么不只使用其中之一?此外,在 JSON 中,oneloopstwoloops 真的很重要吗?拥有 2 个相同但具有不同值的 JSON 不是更好吗?
  • 他们有不同的数据。在最后一张图片中你也看到了单元格,所以它应该从每个 json 文件中加载数据。
  • 但它们具有相同的属性。我的意思是,结构是一样的。
  • 那么我怎样才能做到这一点,也许你可以展示一下?

标签: ios json swift uitableview parsing


【解决方案1】:

在您的情况下没有理由有两个具有不同结构的 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()
}

【讨论】:

  • 你从哪里得到 loopsNames?
  • 这是你的 loopsName 你在 tableview 中使用的那个。
  • 无法将类型“[BPLibraryViewController.Loop]”的值分配给类型“[LoopOne]”
  • 确实,现在是var loopsName: [Loop]
  • 还有这个:在调用实例方法'append'时没有完全匹配
最近更新 更多