我正在尝试在UITableViewController中获取核心数据对象,但出现致命错误。有趣的是,该日志实际上在底部显示了该值,但应用程序stil崩溃了
import UIKit
import CoreData
import MediaPlayer
class FavoritesTableViewController: UIViewController, NSFetchedResultsControllerDelegate, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
var entry: Song?
var song: MPMediaItem!
var songs: [Song?] = []
// var fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult>!
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tableView.dataSource = self
self.tableView.delegate = self
self.initializeFetchRequest()
self.tableView.reloadData()
self.tableView.tableFooterView = UIView(frame: CGRect.zero)
}
func initializeFetchRequest() {
let coreDataStack: CoreDataStack = CoreDataStack.defaultStack
let fetchRequest: NSFetchRequest = self.entryListFetchRequest()
// self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: coreDataStack.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
coreDataStack.managedObjectContext.performAndWait {
do {
if #available(iOS 10.0, *) {
self.songs = try fetchRequest.execute() as? [Song] ?? []
} else {
// Fallback on earlier versions
self.songs = try coreDataStack.managedObjectContext.fetch(fetchRequest) as? [Song] ?? []
}
} catch {
print(error)
}
}
// fetchedResultsController.delegate = self
//
// do {
// try self.fetchedResultsController.performFetch()
// } catch {
// print(error)
// }
}
func entryListFetchRequest() -> NSFetchRequest<NSFetchRequestResult> {
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Song")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)]
return fetchRequest
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
let newSongs = songs.compactMap{ $0 }
print(newSongs.map{$0.songId})
if (newSongs.count > 0) {
return newSongs.count
} else {
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let newSongs = self.songs.compactMap{ $0 }
self.entry = newSongs[indexPath.row]
if let currentEntry = self.entry {
if (currentEntry.songId != nil) {
print("Hello", currentEntry.songId!)
self.song = findSongWithPersistentIdString(persistentIDString: currentEntry.songId!)
// Configure the cell...
cell.textLabel?.text = self.song.value(forKey: MPMediaItemPropertyTitle) as? String
}
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
// Configure the cell...
self.tableView.deselectRow(at: indexPath, animated: true)
self.entry = songs[indexPath.row]
if let currentEntry = self.entry {
print("Hello", currentEntry.songId!)
self.song = findSongWithPersistentIdString(persistentIDString: currentEntry.songId!)
// Configure the cell...
}
self.performSegue(withIdentifier: "details", sender: self)
}
func findSongWithPersistentIdString(persistentIDString: String) -> MPMediaItem? {
let predicate = MPMediaPropertyPredicate(value: persistentIDString, forProperty: MPMediaItemPropertyPersistentID)
let songQuery = MPMediaQuery()
songQuery.addFilterPredicate(predicate)
var song: MPMediaItem?
if let items = songQuery.items, items.count > 0 {
song = items[0]
}
return song
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "details") {
// let navController: UINavigationController = segue.destination as! UINavigationController
let entryVC: SongDetailsViewController = segue.destination as! SongDetailsViewController
entryVC.entry = entry
entryVC.song = self.song
}
}
}
print命令实际上会打印日志,但是应用程序崩溃。
以下是我访问核心数据的方式
func initializeFetchRequest() {
let coreDataStack: CoreDataStack = CoreDataStack.defaultStack
let fetchRequest: NSFetchRequest = self.entryListFetchRequest()
// self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: coreDataStack.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
coreDataStack.managedObjectContext.performAndWait {
do {
if #available(iOS 10.0, *) {
self.songs = try fetchRequest.execute() as? [Song]
} else {
// Fallback on earlier versions
self.songs = try coreDataStack.managedObjectContext.fetch(fetchRequest) as? [Song]
}
} catch {
print(error)
}
}
// fetchedResultsController.delegate = self
//
// do {
// try self.fetchedResultsController.performFetch()
// } catch {
// print(error)
// }
}
func entryListFetchRequest() -> NSFetchRequest<NSFetchRequestResult> {
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Song")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)]
return fetchRequest
}
实际上,我正在将喜欢的歌曲保存在屏幕中,然后从那里尝试打开存在上述代码的“喜欢的屏幕”。