2016-05-05 58 views
1

我有一個奇怪的問題,我的tableview中的單元格不一致。有時它們會顯示爲空白單元格,而其他時間則會顯示正確的數據。請參閱下面的GIF。當滾動tableview時,單元格變成空白(swift)

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) 

} 
} 
+0

您可以創建與上面的代碼的東西示範項目,並分享這裏下載,所以任何人都可以看看,爲您提供解決方案。 – Hasya

+0

其實,這是我的演示項目,我有我的實際應用這個問題,所以我建立了它儘可能的簡單,試圖找出其中的問題來自何處。這是Dropbox的一個zip文件。我很想知道其他人是否看到相同的結果。從我廣泛的研究來看,似乎我做的都是正確的。但是我可以在網上找到的大多數例子都是使用數組而不是CoreData,所以我猜這就是問題出現的地方。

回答

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)問題是自動版式,當我關閉它,所有的標籤去-X位置,當我使用自動調整大小正確對齊,它現在是工作的罰款。 (見附圖)

所以你需要檢查AutoLayout,爲什麼它給iOS 9和更新的問題。

參考link

我希望你能找出和解決進一步。

一切順利。

Download

enter image description here

enter image description here

+0

非常感謝你在這你的幫助。我從來沒有想過要嘗試在早期版本的iOS中運行它。只是爲了確保我瞭解,自動版式是什麼控制我在故事板施加限制......所以,如果我的所有標籤的代碼,而不是定位,這將有可能解決我的問題?我一定會更多地關注AutoLayout並研究它的功能以及如何打開和關閉它。再次感謝你! –

+1

傑森,從https://drive.google.com/file/d/0B7ooURy3zGWKblQ3aG85OWJnOHM/view?usp=sharing – Hasya

+1

解決問題的自動版式下載整個項目與iOS 9,如果自動版式真的不那麼需要禁用它,並與自動尺寸口罩工作。作出明智的決定。 – Hasya

0

而不是使用

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

嘗試使用

tableView.dequeueReusableCellWithIdentifier("listContentCell") 
+0

謝謝你的建議,但嘗試這種沒有任何改變。我仍然遇到這兩種情況,滾動更改爲空,並添加新項目顯示爲空白。爲了確保我已經說過了,沒有一個單元格應該是空白的。當我退出並重新啓動應用後,他們都會自行修復。 –

+0

如果我向你發送文件,會有幫助嗎? –

+0

https://www.dropbox.com/s/siq85jtg3ho8lz5/EZ%20List.zip?dl=0 –