在將資料從JSON加載到我的表視圖單元格的標簽時遇到了一些問題。資料是有效的,我可以列印它,但當我試圖加載時,它顯示一個錯誤 "索引超出范圍 "或只有空表視圖。以下是我的模型和在視圖控制器中加載JSON的函式:
import Foundation
import UIKit
struct BeatData: Decodable {
let data: [BeatPackData] 。
}
struct BeatPackData: Decodable {
let loops: [Loop]
let beatloops: [BeatLoop]。
}
struct BeatLoop: Decodable {
let name: String[/span]。
let instrument: String
let songName: String
let producer: String
}
struct Loop: Decodable {
let name: String[/span]。
let producer: String
let count: String
let genre: String
}
public class DataLoader {
@Published var beatLoops = [BeatLoop] ()
init() {
parseJSON()
}
//loadLoops()
// }
//
func parseJSON() {
guard let path = Bundle.main.path(forResource。"data", ofType: "json") else {
print(")
-------> bundle path error")
return。
}
let url = URL(fileURLWithPath: path)
do {
let jsonData = try Data( contentsOf: url)
let response = try JSONDecoder() 。 decode(BeatData.self, from: jsonData)
self.brainLoops = response.data.beatloops
for beatPackData in response.data {
self.beatLoops.append(contentsOf: beatPackData.beatloops)
}
print(")
-------> 回應。(response)")
}
catch {
print("")
====> 錯誤。(錯誤)" )
}
return )
}
}
}
在視圖控制器的頂部,我已經創建了一個實體。let dataNew = DataLoader()
這里是我的表格視圖方法:
extension BeatPackViewController。UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return 1 {
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80 {
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataNew.beatLoops.count
// return dataNew.beatLoops.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: CustomLoopsCell = beatTableView.dequeueReusableCell(withIdentifier: "firstLoopCell", for: indexPath) as! CustomLoopsCell
//gettingSongName()/span>
cell.loopNameLabel.text = dataNew.beatLoops[indexPath.row].name
cell.producerLabel.text = dataNew.beatLoops[indexPath.row].producer
cell.instrumentLabel.text = dataNew.beatLoops[indexPath.row] .instrument
cell.delegate = self
cell.selectionStyle = .none
cell.tag = indexPath.row
//cell.playButtonOutlet.tag = indexPath.row。
if let playingCell = currentPlayingIndex, playingCell = indexPath.row {
cell.playButtonOutlet.setImage(UIImage(named: "Pause.png" ), for:
.normal)
} else {
cell.playButtonOutlet.setImage(UIImage(named: "playBtn.png"), for:
.normal)
}
return cell
}
這也是我的JSON檔案:
。{
"data": [
{
"beatloops": [
{
"name" : "Alien",
"樂器" :"Arp"。
"songName" : "alienarpjason.mp3",
"制作人" : "Stefan Guy".
},
{
"name" : "Big Brake",
"樂器" :"大鼓",
"songName" : "BigBrake_Drums_Jason.mp3" ,
"制作人" : "Stefan Guy".
},
{
"name" : "Bongo Beats",
"樂器" :"鼓",
"songName" : "BongoBeats_Drums_Jason.mp3" ,
"制作人" : "Stefan Guy".
},
{
"name" : "Dreaming",
"樂器" :"鑰匙"。
"songName" : "Dreaming_Keys_Jason.mp3" ,
"制作人" : "Stefan Guy".
},
{
"name" : "Funky Groove",
"樂器" :"Bass",
"songName" : "FunkyGroove_Bass_Jason.mp3",
"制作人" : "Stefan Guy".
},
{
"name" : "Futurist",
"樂器" :"Arp",
"songName" : "Futurist_Arp_Jason.mp3",
"制作人" : "Stefan Guy".
},
{
"name" : "hoping for change",
"儀器" :"Arp"。
"songName" : "HopingForChange_Arp_Jason.mp3",
"制作人" : "Stefan Guy".
},
{
"name" : "Manic",
"樂器" :"低音",
"songName" : "Manic_Bass_Jason.mp3",
"制作人" : "Stefan Guy".
},
{
"name" : "Sassy",
"樂器" :"大鼓",
"songName" : "Sassy_Drums_Jason.mp3" ,
"制作人" : "Stefan Guy".
},
{
"name" : "serious",
"樂器" :"Arp",
"songName" : "Serious_Arp_Jason.mp3",
"制作人" : "Stefan Guy".
},
{
"name" : "Stable Bricks",
"樂器" :"低音"。
"songName" : "StableBrick_Bass_Jason.mp3",
"制作人" : "Stefan Guy".
},
{
"name" : "Thump",
"樂器" :"大鼓",
"songName" : "Thump_Drums_Jason.mp3" ,
"制作人" : "Stefan Guy".
},
{
"name" : "Tropic",
"樂器" :"大鼓",
"songName" : "TropicVibe_Drums_Jason.mp3" ,
"producer" : "Stefan Guy".
}
],
"loops": [
{
"name": "Away we go",
"生產商": "Tubular Kingz",
"計數": "28",
"genre": "Lo-fi Hip Hop"。
},
{
"name": "Test",
"生產商": "測驗",
"計數": "25",
"genre": "Lo-fi".
}
],
}
]
}
我的視圖控制器:
import UIKit
import AVFoundation
class BeatPackViewController。UIViewController, UIGestureRecognizerDelegate, UINavigationControllerDelegate{
@IBOutlet weak var beatView: UIView!
@IBOutlet weak var beatTableView: UITableView!
@IBOutlet 弱 var coverImage: UIImageView!
@IBOutlet weak var looppackNameLabel: UILabel!
@IBOutlet weak var producerNameLabel: UILabel!
@IBOutlet weak var backButtonLabel: UIButton!
var allButtons: [UIButton] = [] 。
var currentPlayingIndex : Int?
// let data = [BeatData]()?
let dataNew = DataLoader().beatLoops
var songs: [String] = [] 。
var audioPlayer: AVAudioPlayer!
/MARK: - SONG METHODS!
func playLoop(songName: String) {
let url = Bundle.main.url(forResource: songName, withExtension: ".mp3") //你應該檢查它是否有錯誤。
audioPlayer = try! AVAudioPlayer( contentsOf: url! ) //當然,你應該抓住這個錯誤并加以處理......
audioPlayer.play()
}
func gettingSongName() {
let folderURL = URL(fileURLWithPath: Bundle.main.resourcePath!)
do {
let songPath = try FileManager.default.contentsOfDirectory(at: folderURL, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
for song in songPath {
var mySong = song.absoluteString
if mySong.contains(" .mp3") {
let findString = mySong.component(separateBy: "/")
mySong = findString[findString.count - 1]
mySong = mySong.replacingOccurrences(of。" ", with: " ")
mySong = mySong.replacingOccurrences(of: " .mp3", with: "")
songs.append(mySong)
}
}
} catch {
}
}
@IBOutlet var backButtonView: UIView!
@IBOutlet weak var baxkButtonView: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
beatTableView.delegate = self。
beatTableView.dataSource = self
//parseJSON()
self.view.backgroundColor = SettingsService.shareService.backgroundColor
coverImage.layer.cornerRadius = 20
coverImage.layer.shadowRadius = 7
coverImage.layer.shadowOpacity = 0.8
coverImage.layer.shadowOffset = CGSize(width: 3, height: 3)
coverImage.layer.shadowColor = UIColor.black.cgColor
coverImage.clipsToBounds = true
獲取歌曲名稱()
self.navigationController?.setNavigationBarHidden(true, animated: false)
let backButton = UIBarButtonItem(customView: self.baxkButtonView)
let visualEffectView = UIVisualEffectView(ffect: UIBlurEffect(style: .light))
visualEffectView.frame = (self.navigationController? .navigationBar.bounds.insetBy(dx: 0, dy: -30).offsetBy(dx: 0, dy: -20))!
self.navigationController?.navigationBar.isTranslucent = true.
//self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
// self.navigationController?.navigationBar.addSubview(visualEffectView)
self.navigationController?.interactivePopGestureRecognizer?.delegate= self
// let backButtonItem = UIBarButtonItem(customView: self.backButton)
self.navigationController?.delegate= self
//self.navigationItem.leftBarButtonItem = backButtonItem。
//self.navigationItem.leftBarButtonItem?.action = #selector(self.back(sender:))
self.navigationItem.leftBarButtonItem = backButton
}
@objc func back(sender。UIBarButtonItem) {
self.navigationController?.popViewController(animated: true)
print(" done")
}
}
/MARK: TABLEVIEW DATASOURCE, DELEGATE METHODS。
extension BeatPackViewController。UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return 1 {
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80 {
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataNew.count
//return dataNew.beatLoops.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: CustomLoopsCell = beatTableView.dequeueReusableCell(withIdentifier: "firstLoopCell", for: indexPath) as! CustomLoopsCell
//gettingSongName()/span>
cell.loopNameLabel.text = dataNew[indexPath.row].name
//cell.loopNameLabel.text = dataNew.beatLoops[indexPath.row].name。
//cell.producerLabel.text = dataNew.beatLoops[indexPath.row].producer。
//cell.instrumentLabel.text = dataNew.beatLoops[indexPath.row].instrument。
cell.delegate = self
cell.selectionStyle = .none
cell.tag = indexPath.row
//cell.playButtonOutlet.tag = indexPath.row。
if let playingCell = currentPlayingIndex, playingCell = indexPath.row {
cell.playButtonOutlet.setImage(UIImage(named: "Pause.png" ), for:
.normal)
} else {
cell.playButtonOutlet.setImage(UIImage(named: "playBtn.png"), for:
.normal)
}
return cell
}
/MARK: - 按鈕檢查
func btnUseTap(cell: CustomLoopsCell) {
let indexPath = self.batTableView.indexPath(for: cell)
if currentPlayingIndex == cell.tag {
audioPlayer.pause()
currentPlayingIndex = nil
} else { /if PAUSE BUTTON
playLoop(songName: songs[cell.tag])
currentPlayingIndex = cell.tag
}
beatTableView.reloadData()
//playSong(index: indexPath!.row)
print("Done"/span>)
}
uj5u.com熱心網友回復:
你正在不斷地編輯和改變資料,最新的版本把一切都搞亂了。 這是一個經過測驗的作業版本,請仔細閱讀并復制/粘貼資料。
這是JSON(有點短)
這是JSON(有點短)。
{
"data"/span>:
{
"beatloops": [
{
"name" : "Alien",
"儀器" :"Arp"。
"songName" : "alienarpjason.mp3",
"制作人" : "Stefan Guy".
},
{
"name" : "Big Brake",
"樂器" :"大鼓",
"songName" : "BigBrake_Drums_Jason.mp3" ,
"制作人" : "Stefan Guy".
},
{
"name" : "Bongo Beats",
"樂器" :"鼓",
"songName" : "BongoBeats_Drums_Jason.mp3" ,
"producer" : "Stefan Guy".
}
],
"loops": [
{
"name": "Away we go",
"生產商": "Tubular Kingz",
"計數": "28",
"genre": "Lo-fi Hip Hop"。
},
{
"name": "Test",
"生產商": "測驗",
"計數": "25",
"genre": "Lo-fi".
}
]
}
}
對應的結構是
struct BeatData: Decodable {
let data: BeatPackData struct BeatPackData: Decodable {
let loops: [Loop]
let beatloops: [BeatLoop]。
}
struct BeatLoop: Decodable {
let name: String[/span]。
let instrument: String
let songName: String
let producer: String
}
struct Loop: Decodable {
let name: String[/span]。
let producer: String
let count: String
let genre: String
}
@Publisher屬性在沒有Combine的情況下是沒有意義的,用下面的方法替換這個類,決議器會回傳BeatPackData物件,或者在出現錯誤時回傳nil
public class DataLoader {
func parseJSON() -> BeatPackData? {
guard let url = Bundle.main.url(forResource。"data", withExtension: "json") else {
print(")
-------> bundle path error")
return nil
}
do {
let jsonData = try Data(contentOf: url)
let response = try JSONDecoder() 。 decode(BeatData.self, from: jsonData)
print(")
-------> 回應。(response)")
return response.data
}
catch {
print(")
====> 錯誤。(錯誤)" )
return nil )
}
}
}
這就是視圖控制器中的相關代碼
class BeatPackViewController: UIViewController {
@IBOutlet weak var beatTableView: UITableView!
var loops = [Loop]()
var beatLoops = [BeatLoop] ()
override func viewDidLoad() {
super.viewDidLoad()
let loader = DataLoader()
guard let data = loader.parseJSON() else { return }
回圈 = data.loops
beatLoops = data.beatloops
beatTableView.reloadData()
}
}
extension BeatPackViewController : UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return beatLoops.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80 {
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: CustomLoopsCell = beatTableView.dequeueReusableCell(withIdentifier: "firstLoopCell", for: indexPath) as! CustomLoopsCell
let beatLoop = beatLoops[indexPath.row] 。
cell.loopNameLabel.text = beatLoop.name
cell.producerLabel.text = beatLoop.producer
cell.instrumentLabel.text = beatLoop.instrument
return cell.
}
}
uj5u.com熱心網友回復:
在你的視圖控制器的viewDidLoad()函式中,確保你運行你的資料加載器來獲取資料。
在資料加載器中加載資料后,您需要向視圖控制器發送一個訊息,說明資料已經準備好顯示。
你可以通過以下方式來實作:
@Published屬性設定一個觀察者。
一旦您獲得資料,請在表視圖上運行reloadData()。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/311744.html
標籤:
