我很难实现NSFetchedResultsController,因为我一直在收到错误。我正在尝试使用UITableView连接Core Data,并且我没有通过让UITableView根据Core Data中的记录数抽出正确的行数来实现下一步。我收到此错误消息:
<form enctype="multipart/form-data" action="/processing.php?page=vmrp" method="post" accept-charset="UTF-8" id="formvmrp">
<input type="checkbox" name="changePIN" onclick="document.getElementById(\'pintext\').style.display = (this.checked) ? \'block\' : \'none\'; document.getElementById(\'nopintext\').style.display = (this.checked) ? \'none\' : \'block\'; " /> Change My PIN
<div id="nopintext" style="display: block;">
<button onclick="submitForm(\'vmrp\',\'uvml\')">Unlock Voicemail</button>
</div>
<div id="pintext" style="display: none;">
<label for="edit-submitted-user-name">New PIN: <span class="form-required" title="This field is required.">*</span></label>
<br>PIN Must be 6 numbers<br>
<input required="required" type="password" placeholder="New 6 Digit PIN" id="edit-submitted-user-name" name="PIN" value="" pattern="[0-9]{6}" maxlength="6" size="75" title="PIN Must Contain 6 numbers!" class="form-text required" /><br>
<button onclick="submitForm(\'vmrp\',\'uvml\')">Change PIN</button>
</div>
<input type="hidden" name="form_id" value="uVMResetPIN" />
<input type="hidden" name="uVMPINURI" value="' . (string)$_SESSION['uVMPINURI'] . '" />
<input type="hidden" name="rmtIP" value="' . $_SERVER['REMOTE_ADDR'] . '" />
<input type="hidden" name="tz" value="' . $_SESSION['uVMtzn'] . '" />
<input type="hidden" name="user" value="' . $_SESSION['inUser'] . '" />
</form>
以下是我的代码:
*** Terminating app
due to uncaught exception 'NSRangeException', reason: '***
[__NSSingleObjectArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
下面显示包含CoreDataStack实现的文件:
import UIKit
import CoreData
class CustomerProfileViewController: UITableViewController, NSFetchedResultsControllerDelegate {
var coreDataStack: CoreDataStack!
var itemList: [NSManagedObject] = [] // I hope to have the fetch results controller manage this object
// The data model contains one entity "Item" with one attribute "name"
lazy var fetchResultsControllerItem: NSFetchedResultsController<Item> = {
// Initialize Fetch Request
let fetchRequest: NSFetchRequest<Item> = Item.fetchRequest()
// Configure Fetch Request
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
// Initialize Fetch Results Controller
let fetchResultsControllerItem =
NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: self.coreDataStack.managedContext,
sectionNameKeyPath: nil,
cacheName: nil)
fetchResultsControllerItem.delegate = self
return fetchResultsControllerItem
}()
override func viewDidLoad() {
super.viewDidLoad()
do {
try fetchResultsControllerItem.performFetch()
print("Fetch worked! ")
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
let cellNib = UINib(nibName: "SummaryCell", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "SummaryCell")
let cellNib = UINib(nibName: "ListingsCell", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "ListingsCell")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 2 // Corresponds to the custom table view cells as Nib files
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "SUMMARY"
} else if section == 1 {
return "ITEM LISTINGS"
} else {
return ""
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return 1
} else if section == 1 {
/* Adding the "guard let sections" to the "return
sectionInfo.numberOfObject" below causes an error: *** Terminating app
due to uncaught exception 'NSRangeException', reason: '***
[__NSSingleObjectArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]' */
enter code here
guard let sections = fetchResultsControllerItem.sections else {
return 0
}
let sectionInfo = sections[section]
return sectionInfo.numberOfObjects
} else {
return 1
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "SummaryCell", for: indexPath) as! SummaryCell
cell.totalNumberOfItems?.text = "\(itemList.count)"
return cell
} else if indexPath.section == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "ListingsCell", for: indexPath) as! ListingsCell
let listItem = fetchResultsControllerItem.object(at: indexPath)
cell.itemName?.text = listItem.name
return cell
}
return UITableViewCell()
}
}
在检查sqlite文件后,我确实使用Liya确认有记录名称的项目。对于任何有任何提示或想法的人,我将不胜感激任何帮助。感谢。
答案 0 :(得分:0)
问题在于,在FetchedResultsController的视图中,如果世界上只有一个部分:第0部分。但是你的tableView有两个部分,你希望FRC为第1部分提供数据。所以你需要重新映射FRC indexPaths到表视图中的正确部分,在tableView数据源方法中。因此,在numberOfRowsInSection
中,您的代码当前正在向FRC询问第1部分中的对象数量,并且FRC会抛出错误,因为就其而言,没有第1部分。只需替换:
let sectionInfo = sections[section]
return sectionInfo.numberOfObjects
使用:
let sectionInfo = sections[0]
return sectionInfo.numberOfObjects
在那个方法中。然后在cellForRowAt
中,将其替换为:
let cell = tableView.dequeueReusableCell(withIdentifier: "ListingsCell", for: indexPath) as! ListingsCell
let listItem = fetchResultsControllerItem.object(at: indexPath)
cell.itemName?.text = listItem.name
return cell
用这个:
let cell = tableView.dequeueReusableCell(withIdentifier: "ListingsCell", for: indexPath) as! ListingsCell
let listItem = fetchResultsControllerItem.fetchedObjects![indexPath.row]
cell.itemName?.text = listItem.name
return cell
(这使用FRC的fetchedObjects
属性来避免在object(at:)
)中使用indexPath中的错误部分。