1 个 UIViewController 中的 2 个 UITableViews 均从 CoreData 加载
2 UITableViews inside 1 UIViewController both loading from CoreData
我试图在 1 个 UIViewController 中有 2 个单独的 UITableView,但诀窍是我正在尝试这样做,以便它们都从 CoreDate 加载。
我试图通过使用与 UITableViewController 相同的样式来完成它,但我似乎 运行 遇到了问题。
我获取表格数据的方式是使用 FRC (NSFetchedResultsController),但我似乎只大声说每个 UIViewController 有 1 个。
这是我正在使用的 2 个 FRC 提取器。
FRC 1:
func getFRCIngredients() -> NSFetchedResultsController<Ent_Ingredients> {
let fetchReq: NSFetchRequest<Ent_Ingredients> = Ent_Ingredients.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "order", ascending: true)
let predicate = NSPredicate(format: "recipeRel == %@", self.recipe!)
fetchReq.sortDescriptors = [sortDescriptor]
fetchReq.predicate = predicate
let frc = NSFetchedResultsController(fetchRequest: fetchReq, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
return frc
}
FRC 2:
func getFRCDirections() -> NSFetchedResultsController<Ent_Directions> {
let fetchReq: NSFetchRequest<Ent_Directions> = Ent_Directions.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "order", ascending: true)
let predicate = NSPredicate(format: "recipeRel == %@", self.recipe!)
fetchReq.sortDescriptors = [sortDescriptor]
fetchReq.predicate = predicate
let frc = NSFetchedResultsController(fetchRequest: fetchReq, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
return frc
}
在尝试将第 2 个 FRC 上的委托设置为自身后,viewDidLoad()
中出现错误。当我考虑时,这是有道理的,您可能无法让它管理两组独立的数据。
错误:“libc++abi.dylib: terminating with uncaught exception of type NSException
”
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.plain, target: nil, action: nil)
tableViewIngredients.dataSource = self
tableViewIngredients.delegate = self
tableViewIngredients.register(UITableViewCell.self, forCellReuseIdentifier: "recipeIngredientCell")
tableViewDirections.dataSource = self
tableViewDirections.delegate = self
tableViewDirections.register(UITableViewCell.self, forCellReuseIdentifier: "recipeDirectionCell")
recipeName.text = recipe!.name
recipeImage.image = UIImage(data: recipe!.image as! Data)
oldName = recipe!.name!
frcIngredients = getFRCIngredients()
frcIngredients!.delegate = self
do {
try frcIngredients!.performFetch()
} catch {
fatalError("Failed to perform initial FRC fetch for Ingredients")
}
frcDirections = getFRCDirections()
frcDirections!.delegate = self //<- ***ERRORS HERE***
do {
try frcDirections!.performFetch()
} catch {
fatalError("Failed to perform initial FRC fetch for Ingredients")
}
NotificationCenter.default.addObserver(self, selector: #selector(AddRecipesVC.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
}
我怎样才能完成我在这里想做的事情?我对 Xcode 和 Swift 还是比较陌生,所以非常感谢任何帮助。
谢谢!
原来我犯了一个愚蠢的错误。我忘记了我没有更新 Ent_Directions
实体中的属性名称,所以我总是调用一个不存在的属性。但以防万一这对以后的人有帮助,这是我最终用来让 2 个 UITableView 在单个 UIViewController 中工作的代码。我删除了与 UITableViews 无关的额外代码。
Swift 3.0:
class EditRecipesVC: UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate {
// MARK: - Constants and Variables
let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var frcIngredients: NSFetchedResultsController<Ent_Ingredients>?
var frcDirections: NSFetchedResultsController<Ent_Directions>?
var recipe: Ent_Recipes?
// MARK: - Class Loading Functions
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.plain, target: nil, action: nil)
tableViewIngredients.dataSource = self
tableViewIngredients.delegate = self
tableViewIngredients.rowHeight = UITableViewAutomaticDimension
tableViewIngredients.estimatedRowHeight = 40
tableViewDirections.dataSource = self
tableViewDirections.delegate = self
tableViewDirections.rowHeight = UITableViewAutomaticDimension
tableViewDirections.estimatedRowHeight = 40
recipeName.text = recipe!.name
recipeImage.image = UIImage(data: recipe!.image as! Data)
oldName = recipe!.name!
frcIngredients = getFRCIngredients()
frcIngredients!.delegate = self
do {
try frcIngredients!.performFetch()
} catch {
fatalError("Failed to perform initial FRC fetch for Ingredients")
}
frcDirections = getFRCDirections()
frcDirections!.delegate = self
do {
try frcDirections!.performFetch()
} catch {
fatalError("Failed to perform initial FRC fetch for Ingredients")
}
NotificationCenter.default.addObserver(self, selector: #selector(AddRecipesVC.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
}
// MARK: - Outlets and Actions
@IBOutlet var tableViewIngredients: UITableView!
@IBOutlet var tableViewDirections: UITableView!
// MARK: - Table View Data Source
func numberOfSections(in tableView: UITableView) -> Int {
var frc: NSFetchedResultsController<NSFetchRequestResult>
if (tableView == tableViewIngredients) {
frc = frcIngredients as! NSFetchedResultsController<NSFetchRequestResult>
} else {
frc = frcDirections as! NSFetchedResultsController<NSFetchRequestResult>
}
if let sections = frc.sections {
return sections.count
}
return 0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var frc: NSFetchedResultsController<NSFetchRequestResult>
if (tableView == tableViewIngredients) {
frc = frcIngredients as! NSFetchedResultsController<NSFetchRequestResult>
} else {
frc = frcDirections as! NSFetchedResultsController<NSFetchRequestResult>
}
if let sections = frc.sections {
let currentSection = sections[section]
return currentSection.numberOfObjects
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (tableView == tableViewIngredients) {
let cell: RecipeIngredientTVCell = tableView.dequeueReusableCell(withIdentifier: "recipeIngredientCell", for: indexPath) as! RecipeIngredientTVCell
return cell
} else {
let cell: RecipeDirectionTVCell = tableView.dequeueReusableCell(withIdentifier: "recipeDirectionCell", for: indexPath) as! RecipeDirectionTVCell
return cell
}
}
// MARK: - Custom Functions
func getFRCIngredients() -> NSFetchedResultsController<Ent_Ingredients> {
let fetchReq: NSFetchRequest<Ent_Ingredients> = Ent_Ingredients.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "order", ascending: true)
let predicate = NSPredicate(format: "recipeRel == %@", self.recipe!)
fetchReq.sortDescriptors = [sortDescriptor]
fetchReq.predicate = predicate
let frc = NSFetchedResultsController(fetchRequest: fetchReq, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
return frc
}
func getFRCDirections() -> NSFetchedResultsController<Ent_Directions> {
let fetchReq: NSFetchRequest<Ent_Directions> = Ent_Directions.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "order", ascending: true)
let predicate = NSPredicate(format: "recipeRel == %@", self.recipe!)
fetchReq.sortDescriptors = [sortDescriptor]
fetchReq.predicate = predicate
let frc = NSFetchedResultsController(fetchRequest: fetchReq, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
return frc
}
}
我试图在 1 个 UIViewController 中有 2 个单独的 UITableView,但诀窍是我正在尝试这样做,以便它们都从 CoreDate 加载。
我试图通过使用与 UITableViewController 相同的样式来完成它,但我似乎 运行 遇到了问题。
我获取表格数据的方式是使用 FRC (NSFetchedResultsController),但我似乎只大声说每个 UIViewController 有 1 个。
这是我正在使用的 2 个 FRC 提取器。
FRC 1:
func getFRCIngredients() -> NSFetchedResultsController<Ent_Ingredients> {
let fetchReq: NSFetchRequest<Ent_Ingredients> = Ent_Ingredients.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "order", ascending: true)
let predicate = NSPredicate(format: "recipeRel == %@", self.recipe!)
fetchReq.sortDescriptors = [sortDescriptor]
fetchReq.predicate = predicate
let frc = NSFetchedResultsController(fetchRequest: fetchReq, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
return frc
}
FRC 2:
func getFRCDirections() -> NSFetchedResultsController<Ent_Directions> {
let fetchReq: NSFetchRequest<Ent_Directions> = Ent_Directions.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "order", ascending: true)
let predicate = NSPredicate(format: "recipeRel == %@", self.recipe!)
fetchReq.sortDescriptors = [sortDescriptor]
fetchReq.predicate = predicate
let frc = NSFetchedResultsController(fetchRequest: fetchReq, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
return frc
}
在尝试将第 2 个 FRC 上的委托设置为自身后,viewDidLoad()
中出现错误。当我考虑时,这是有道理的,您可能无法让它管理两组独立的数据。
错误:“libc++abi.dylib: terminating with uncaught exception of type NSException
”
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.plain, target: nil, action: nil)
tableViewIngredients.dataSource = self
tableViewIngredients.delegate = self
tableViewIngredients.register(UITableViewCell.self, forCellReuseIdentifier: "recipeIngredientCell")
tableViewDirections.dataSource = self
tableViewDirections.delegate = self
tableViewDirections.register(UITableViewCell.self, forCellReuseIdentifier: "recipeDirectionCell")
recipeName.text = recipe!.name
recipeImage.image = UIImage(data: recipe!.image as! Data)
oldName = recipe!.name!
frcIngredients = getFRCIngredients()
frcIngredients!.delegate = self
do {
try frcIngredients!.performFetch()
} catch {
fatalError("Failed to perform initial FRC fetch for Ingredients")
}
frcDirections = getFRCDirections()
frcDirections!.delegate = self //<- ***ERRORS HERE***
do {
try frcDirections!.performFetch()
} catch {
fatalError("Failed to perform initial FRC fetch for Ingredients")
}
NotificationCenter.default.addObserver(self, selector: #selector(AddRecipesVC.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
}
我怎样才能完成我在这里想做的事情?我对 Xcode 和 Swift 还是比较陌生,所以非常感谢任何帮助。
谢谢!
原来我犯了一个愚蠢的错误。我忘记了我没有更新 Ent_Directions
实体中的属性名称,所以我总是调用一个不存在的属性。但以防万一这对以后的人有帮助,这是我最终用来让 2 个 UITableView 在单个 UIViewController 中工作的代码。我删除了与 UITableViews 无关的额外代码。
Swift 3.0:
class EditRecipesVC: UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate {
// MARK: - Constants and Variables
let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var frcIngredients: NSFetchedResultsController<Ent_Ingredients>?
var frcDirections: NSFetchedResultsController<Ent_Directions>?
var recipe: Ent_Recipes?
// MARK: - Class Loading Functions
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.plain, target: nil, action: nil)
tableViewIngredients.dataSource = self
tableViewIngredients.delegate = self
tableViewIngredients.rowHeight = UITableViewAutomaticDimension
tableViewIngredients.estimatedRowHeight = 40
tableViewDirections.dataSource = self
tableViewDirections.delegate = self
tableViewDirections.rowHeight = UITableViewAutomaticDimension
tableViewDirections.estimatedRowHeight = 40
recipeName.text = recipe!.name
recipeImage.image = UIImage(data: recipe!.image as! Data)
oldName = recipe!.name!
frcIngredients = getFRCIngredients()
frcIngredients!.delegate = self
do {
try frcIngredients!.performFetch()
} catch {
fatalError("Failed to perform initial FRC fetch for Ingredients")
}
frcDirections = getFRCDirections()
frcDirections!.delegate = self
do {
try frcDirections!.performFetch()
} catch {
fatalError("Failed to perform initial FRC fetch for Ingredients")
}
NotificationCenter.default.addObserver(self, selector: #selector(AddRecipesVC.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
}
// MARK: - Outlets and Actions
@IBOutlet var tableViewIngredients: UITableView!
@IBOutlet var tableViewDirections: UITableView!
// MARK: - Table View Data Source
func numberOfSections(in tableView: UITableView) -> Int {
var frc: NSFetchedResultsController<NSFetchRequestResult>
if (tableView == tableViewIngredients) {
frc = frcIngredients as! NSFetchedResultsController<NSFetchRequestResult>
} else {
frc = frcDirections as! NSFetchedResultsController<NSFetchRequestResult>
}
if let sections = frc.sections {
return sections.count
}
return 0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var frc: NSFetchedResultsController<NSFetchRequestResult>
if (tableView == tableViewIngredients) {
frc = frcIngredients as! NSFetchedResultsController<NSFetchRequestResult>
} else {
frc = frcDirections as! NSFetchedResultsController<NSFetchRequestResult>
}
if let sections = frc.sections {
let currentSection = sections[section]
return currentSection.numberOfObjects
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (tableView == tableViewIngredients) {
let cell: RecipeIngredientTVCell = tableView.dequeueReusableCell(withIdentifier: "recipeIngredientCell", for: indexPath) as! RecipeIngredientTVCell
return cell
} else {
let cell: RecipeDirectionTVCell = tableView.dequeueReusableCell(withIdentifier: "recipeDirectionCell", for: indexPath) as! RecipeDirectionTVCell
return cell
}
}
// MARK: - Custom Functions
func getFRCIngredients() -> NSFetchedResultsController<Ent_Ingredients> {
let fetchReq: NSFetchRequest<Ent_Ingredients> = Ent_Ingredients.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "order", ascending: true)
let predicate = NSPredicate(format: "recipeRel == %@", self.recipe!)
fetchReq.sortDescriptors = [sortDescriptor]
fetchReq.predicate = predicate
let frc = NSFetchedResultsController(fetchRequest: fetchReq, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
return frc
}
func getFRCDirections() -> NSFetchedResultsController<Ent_Directions> {
let fetchReq: NSFetchRequest<Ent_Directions> = Ent_Directions.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "order", ascending: true)
let predicate = NSPredicate(format: "recipeRel == %@", self.recipe!)
fetchReq.sortDescriptors = [sortDescriptor]
fetchReq.predicate = predicate
let frc = NSFetchedResultsController(fetchRequest: fetchReq, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
return frc
}
}