简体   繁体   English

滚动表格视图时单元格变为空白(swift)

[英]Cells become blank when scrolling tableview (swift)

I have a strange problem where my cells in the tableview are not consistent.我有一个奇怪的问题,我在 tableview 中的单元格不一致。 Sometimes they will show as a blank cell and other times they will load with the correct data.有时它们会显示为空白单元格,有时它们会加载正确的数据。 See the GIF below.请参阅下面的 GIF。

在此处输入图片说明

Notice the blank cell in section 1 changes each time.请注意,第 1 部分中的空白单元格每次都会更改。

I also have this problem when adding new cells to the tableview, but closing and reopening the app always fixes it.在向 tableview 添加新单元格时,我也遇到了这个问题,但关闭并重新打开应用程序总是可以修复它。 It just doesn't load correctly when getting added... but sometimes it does load correctly.添加时它只是无法正确加载...但有时它确实加载正确。 See GIF Below.请参阅下面的 GIF。

在此处输入图片说明

I've been recommended to use the reloadData(), but that doesn't seem to help anything at all.有人建议我使用 reloadData(),但这似乎没有任何帮助。 I'm hoping someone will see this that will know what to do.我希望有人会看到这将知道该怎么做。

See Code Below请参阅下面的代码

Table View Controller: (Swift)表视图控制器:(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)!)

}

}

Add Button View Controller: (Swift)添加按钮视图控制器:(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)

}
}

@Jason Brady, I have just downloaded your code. @Jason Brady,我刚刚下载了您的代码。

There is no problem with you core data, array or table view.你的核心数据、数组或表视图没有问题。

When i run an app in iPhone 5 / iPhone 6 / iPhone 6 Plus with 8.1 it is working fine, none of cell or add button is getting hidden.当我在 iPhone 5 / iPhone 6 / iPhone 6 Plus 和 8.1 上运行应用程序时,它工作正常,没有任何单元格或添加按钮被隐藏。

But with same devices with 9.2 there is a problem.但是使用 9.2 的相同设备存在问题。

Solutions解决方案

(1) Custom cell with dequeueReusableCellWithIdentifier (1) 带有 dequeueReusableCellWithIdentifier 的自定义单元格

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

(2) DidselectedRowAtIndex - Here you will get information at cell selection, So data is going perfectly. (2) DidselectedRowAtIndex - 在这里您将获得单元格选择的信息,因此数据运行良好。

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

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

}

(3) Problem is with AutoLayout, when i disabled it, all label went to -X positions, when i have aligned it properly using auto resizing, it is now working fine. (3) 问题在于 AutoLayout,当我禁用它时,所有标签都转到 -X 位置,当我使用自动调整大小正确对齐它时,它现在工作正常。 ( See attached screen shot ) (见附件截图)

So you need to check with AutoLayout, why it is giving problem in iOS 9 and newer.所以你需要检查 AutoLayout,为什么它在 iOS 9 和更新版本中出现问题。

Refer link参考链接

I hope you can figure out and resolve further.希望你能进一步了解和解决。

All the best.祝一切顺利。

Download 下载

在此处输入图片说明

在此处输入图片说明

Instead of using而不是使用

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

try using尝试使用

tableView.dequeueReusableCellWithIdentifier("listContentCell")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM