如何使用 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"
}
]
}
}
我保留了 beatPack
和 loops
,但这甚至可能与保留它们无关。
那么我们的模型有:
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()
}
我有两个文件夹,每个文件夹都包含图像、歌曲名称和 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"
}
]
}
}
我保留了 beatPack
和 loops
,但这甚至可能与保留它们无关。
那么我们的模型有:
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()
}