滚动tableview(swift)时单元格变为空白

时间:2016-05-05 03:29:05

标签: ios swift uitableview

我有一个奇怪的问题,我在tableview中的单元格不一致。有时它们会显示为空白单元格,有时则会加载正确的数据。请参阅下面的GIF。

enter image description here

请注意,第1部分中的空白单元格每次都会更改。

将新单元格添加到tableview时我也遇到此问题,但关闭并重新打开应用程序始终会修复它。添加时它只是无法正确加载...但有时它确实正确加载。见下面的GIF。

enter image description here

我被建议使用reloadData(),但这似乎没有任何帮助。我希望有人会看到这会知道该怎么做。

请参阅下面的代码

表视图控制器:( Swift)

import UIKit
import CoreData

class ListItemsTVC: UITableViewController, NSFetchedResultsControllerDelegate {

// MARK: - Constants and Variables

let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var frc: NSFetchedResultsController = NSFetchedResultsController()
//var sequeItem: createItem?

// MARK: - App loading Functions

override func viewDidLoad() {
    super.viewDidLoad()

    frc = getFCR()
    frc.delegate = self

    do {
        try frc.performFetch()
    } catch {
        print("Failed to perform inital fetch")
    }
    self.tableView.rowHeight = 62

}

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    self.tableView.reloadData()

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    if let sections = frc.sections {
        return sections.count
    }

    return 0

}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    if let sections = frc.sections {
        let currentSection = sections[section]
        return currentSection.numberOfObjects
    }

    return 0

}

override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {

    return 28

}

override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

    if let sections = frc.sections {
        let currentSection = sections[section]
        return currentSection.name
    }

    return nil

}

func controllerWillChangeContent(controller: NSFetchedResultsController) {

    tableView.beginUpdates()

}

func controllerDidChangeContent(controller: NSFetchedResultsController) {

    tableView.endUpdates()

}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("listContentCell", forIndexPath: indexPath) as! ListItemsTVCell
    let item = frc.objectAtIndexPath(indexPath) as! Items

    cell.separatorInset = UIEdgeInsets(top: 0, left: 78, bottom: 0, right: 0)
    cell.itemName.text = item.name
    cell.itemSection.text = item.section
    cell.itemQty.text = "Qty: \(item.qty!)"
    cell.itemSize.text = item.size
    cell.itemPrice.text = floatToCurrency(Float(item.price!))
    //cell.itemImage.image = UIImage(data: item.image!)
    cell.itemID.text = String(item.id!)

    return cell

}

override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {

    let delete = UITableViewRowAction(style: .Destructive, title: "Delete") { (action, indexPath) in

        let item = self.frc.objectAtIndexPath(indexPath) as! Items
        let id = item.id!
        let request = self.fetchRequest()
        let pred = NSPredicate(format: "%K == %@", "id",id)
        request.predicate = pred
        var fetchResults = [AnyObject]()

        do {
            fetchResults = try self.moc.executeFetchRequest(request)
        } catch {
            fatalError("Fetching Data to Delete Failed")
        }

        self.moc.deleteObject(fetchResults[0] as! NSManagedObject)
        fetchResults.removeAtIndex(0)

        do {
            try self.moc.save()
        } catch {
            fatalError("Failed to Save after Delete")
        }

    }

    return [delete]

}

func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {

    switch type {
    case NSFetchedResultsChangeType.Delete:
        self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Automatic)
        break
    case NSFetchedResultsChangeType.Insert:
        self.tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Automatic)
        break
    /*case NSFetchedResultsChangeType.Update:
        tableView.reloadSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Automatic)
        break*/
    default:
        print("Default in didChangeSection was called")
        break
    }

}

func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {

    switch type {
    case NSFetchedResultsChangeType.Delete:
        self.tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Automatic)
        break
    case NSFetchedResultsChangeType.Insert:
        self.tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: UITableViewRowAnimation.Fade)
        break
    default:
        print("Default in didChangeObject was called")
        break
    }

}

// MARK: - Custom Functions

func fetchRequest() -> NSFetchRequest {

    let fetchRequest = NSFetchRequest(entityName: "Items")
    let sortDesc1 = NSSortDescriptor(key: "section", ascending: true)
    let sortDesc2 = NSSortDescriptor(key: "isChecked", ascending: true)
    let sortDesc3 = NSSortDescriptor(key: "name", ascending: true)
    fetchRequest.sortDescriptors = [sortDesc1, sortDesc2, sortDesc3]

    return fetchRequest

}

func getFCR() -> NSFetchedResultsController {

    frc = NSFetchedResultsController(fetchRequest: fetchRequest(), managedObjectContext: moc, sectionNameKeyPath: "section" , cacheName: nil)

    return frc

}

func floatToCurrency(flt: Float) -> String {

    let formatter = NSNumberFormatter()
    formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    return String(formatter.stringFromNumber(flt)!)

}

}

添加按钮视图控制器:( Swift)

import UIKit
import CoreData

class AddItemListVC: UIViewController, NSFetchedResultsControllerDelegate {

// MARK: - Constants and Variables

let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var sendItem: Items?

// MARK: - App loading Functions

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Outlets and Actions

@IBAction func addItem(sender: AnyObject) {

    let entityDesc = NSEntityDescription.entityForName("Items", inManagedObjectContext: moc)
    let item = Items(entity: entityDesc!, insertIntoManagedObjectContext: moc)

    if (NSUserDefaults.standardUserDefaults().objectForKey("nextItemID") == nil) {
        NSUserDefaults.standardUserDefaults().setObject(1, forKey: "nextItemID")
        NSUserDefaults.standardUserDefaults().synchronize()
    }

    let id = NSUserDefaults.standardUserDefaults().integerForKey("nextItemID")

    item.id = id
    switch id {
    case 1..<10:
        item.name = "Item ID 00\(id)"
    case 10..<100:
        item.name = "Item ID 0\(id)"
    default:
        item.name = "Item ID \(id)"
    }
    item.brand = "Brand \(id)"
    item.qty = 1
    item.price = 0
    item.size = "Size \(id)"
    let sec: Int = Int(arc4random_uniform(UInt32(4 - 1))) + 1
    item.section = "Section \(sec)"
    item.isChecked = false

    do {
        try moc.save()
        NSUserDefaults.standardUserDefaults().setObject(id + 1, forKey: "nextItemID")
        NSUserDefaults.standardUserDefaults().synchronize()
    } catch {
        fatalError("New item save failed")
    }

    navigationController!.popViewControllerAnimated(true)

}
}

2 个答案:

答案 0 :(得分:1)

@Jason Brady,我刚刚下载了你的代码。

核心数据,数组或表视图没有问题。

当我在iPhone 5 / iPhone 6 / iPhone 6 Plus中使用8.1运行应用程序时,它工作正常,没有任何单元格或添加按钮被隐藏。

但使用9.2的相同设备存在问题。

<强>解决方案

(1)具有dequeueReusableCellWithIdentifier

的自定义单元格
let cell : ListItemsTVCell! = tableView.dequeueReusableCellWithIdentifier("listContentCell", forIndexPath: indexPath)  as! ListItemsTVCell

(2)DidselectedRowAtIndex - 在这里您将获得选择单元格的信息,因此数据完美无缺。

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
        print("Select")

        let myCell = tableView.cellForRowAtIndexPath(indexPath) as! ListItemsTVCell
        print(myCell.itemName.text)

}

(3)问题在于AutoLayout,当我禁用它时,所有标签都转到-X位置,当我使用自动调整大小正确对齐时,它现在正常工作。 (参见随附的屏幕截图)

因此,您需要查看AutoLayout,为什么它会在iOS 9及更新版本中出现问题。

参考link

我希望你能找到并进一步解决。

一切顺利。

Download

enter image description here

enter image description here

答案 1 :(得分:0)

而不是使用

tableView.dequeueReusableCellWithIdentifier("listContentCell", forIndexPath: indexPath)

尝试使用

tableView.dequeueReusableCellWithIdentifier("listContentCell")