2015-11-11 47 views
2

我在使用Swift中的核心數據顯示在表視圖的分區中顯示數據時遇到了一些麻煩。在Swift中使用核心數據在表視圖中顯示數據

我會用一個例子來說明這個問題。讓我們假設三個類:訂單,產品和服務。類別訂單具有屬性「日期」和與產品和服務的多對多關係。

對於每個訂單,應創建一個部分以顯示在特定日期訂購的所有產品和服務。

使用NSFetchedResultsController,所有的訂單都是根據atttribute日期獲取的。這提供了正確數量的部分。 但是,由於「numberOfRowsInSection」基於訂單數量而不是產品和服務數量,因此我遇到問題以每個部分分開顯示所有產品和服務。

下面是說明我的問題的代碼。希望任何人都能幫助我走向正確的方向。

由於提前,

傑拉德

import UIKit 
import CoreData 

class ExampleViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate { 

@IBOutlet weak var tableView: UITableView! 

let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate 
let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext 
var fetchedResultController: NSFetchedResultsController = NSFetchedResultsController() 

var orders = [Order]() 

override func viewDidLoad() { 
    super.viewDidLoad() 
    fetchedResultController.delegate = self 
    tableView.dataSource = self 
    tableView.delegate = self 

    fetchData() 
} 

func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
    return fetchedResultController.sections?.count ?? 0 
} 

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    let sectionInfo = fetchedResultController.sections![section] as NSFetchedResultsSectionInfo 
    return sectionInfo.numberOfObjects 
    // Unfortunatelly, this provides not the total number of products and services per section 
} 

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
    let textCellIdentifier = "ExampleTableViewCell" 
    let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! ExampleTableViewCell 

    let order = orders[indexPath.row] // Data fetched using NSFetchedResultsController 

    let products = order.products!.allObjects as! [Product] // Swift Array 
    let services = order.services!.allObjects as! [Service] // Swift Array 

    // Each product and each service should be displayed in separate rows. 
    // Instead, all products and services are displayed in a single row as below 
    var displaytext = "" 
    for product in products { 
     displaytext += product.name! + "\n" 
    } 

    for service in services { 
     displaytext += service.name! + "\n" 
    } 

    cell.orderLabel.text = displaytext // display text in ExampleTableViewCell 

    return cell 
} 

func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 
    if let sections = fetchedResultController.sections { 
     let currentSection = sections[section] 
     return currentSection.name 
    } 
    return nil 
} 


func orderFetchRequest() -> NSFetchRequest { 
    let fetchRequest = NSFetchRequest(entityName: "Order") 
    let sortDescriptor = NSSortDescriptor(key: "date", ascending: true) 
    let predicate = NSPredicate(format: "date >= %@ AND date <= %@", startDate, endDate) // startDate and endData are defined elsewhere 

    fetchRequest.sortDescriptors = [sortDescriptor] 
    fetchRequest.predicate = predicate 

    return fetchRequest 
} 

func fetchData() { 
    let fetchRequest = orderFetchRequest() 
    fetchedResultController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: "date", cacheName: nil) 

    do { 
     orders = try managedObjectContext.executeFetchRequest(fetchRequest) as! [Order] 
    } 
    catch let error as NSError { 
     print("Could not fetch \(error), \(error.userInfo)") 
    } 

    do { 
     try fetchedResultController.performFetch() 
    } 
    catch _ { 
    } 
} 

}

+0

因此,您需要爲每個訂單分配一個部分,並在每個部分中爲所有產品分配行,然後在所有服務中分配行? FRC不會輕易幫助你。它想要展示訂單並鑽取產品和服務...... – Wain

+0

這正是我想要的。事實上,我希望可以獲取父類Order的數據(使用NSSortDescriptor和NSPredicate),並根據子類Product和Service的實例數爲Table View提供每個節的行數。當NSFetchedResultsController不可能(很容易)這樣做時,是否有另一種方法來執行此操作? – Gerard

回答

0

正如韋恩所說,FRC沒有太大幫助。 FRC有兩個主要的優點,除了普通的提取之外:它可以爲你管理這些部分,並且它可以通過它的委託方法自動處理插入/刪除/更新。第一種在你的情況下是沒有用的,因爲你需要每個訂單一個部分。第二個是沒有什麼幫助,因爲FRC只會觀察一個實體進行更改,而您的桌面視圖是從三個建立的。

不過,我想你可能會使用FRC來產生一些效果。首先,請不要打擾sectionNameKeyPath:您在Orders和表格視圖部分之間有一對一的映射關係,因此您可以使用表格視圖的section作爲FRC的fetchedObjects上的索引來標識每個部分的順序。然後可以通過將相關Orderproductsservices的計數相加來找到numberOrRowsInSection。混亂(可能很慢)的位將表格視圖的行映射到productsservices的正確元素。

import UIKit 
import CoreData 

class ExampleViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate { 

    @IBOutlet weak var tableView: UITableView! 

    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate 
    let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext! 
    var fetchedResultController: NSFetchedResultsController = NSFetchedResultsController() 

    var orders = [Order]() 
    var startDate : NSDate = NSDate() 
    var endDate : NSDate = NSDate() 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     fetchedResultController.delegate = self 
     tableView.dataSource = self 
     tableView.delegate = self 

     fetchData() 
    } 

    func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
     return fetchedResultController.fetchedObjects!.count 
    } 

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     let order = fetchedResultController.fetchedObjects![section] as! Order 
     return ((order.products?.count ?? 0) + (order.services?.count ?? 0)) 
    } 

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
     let textCellIdentifier = "ExampleTableViewCell" 
     let row = indexPath.row 

     let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! ExampleTableViewCell 

     let order = fetchedResultController.fetchedObjects![indexPath.section] as! Order // Data fetched using NSFetchedResultsController 
     let products = (order.products?.allObjects ?? [Product]()) as! [Product] // Swift Array 
     let services = (order.services?.allObjects ?? [Service]()) as! [Service] // Swift Array 

     if (row < products.count) { // this is a Product row 
      cell.orderLabel.text = products[row].name! 
     } else { // this is a Service row 
      cell.orderLabel.text = services[row-products.count].name! 
     } 
     return cell 
    } 

    func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 
     let order = fetchedResultController.fetchedObjects![section] as! Order 
     return "\(order.date)" 
    } 


    func orderFetchRequest() -> NSFetchRequest { 
     let fetchRequest = NSFetchRequest(entityName: "Order") 
     let sortDescriptor = NSSortDescriptor(key: "date", ascending: true) 
     let predicate = NSPredicate(format: "date >= %@ AND date <= %@", startDate, endDate) // startDate and endData are defined elsewhere 

     fetchRequest.sortDescriptors = [sortDescriptor] 
     fetchRequest.predicate = predicate 

     return fetchRequest 
    } 

    func fetchData() { 
     let fetchRequest = orderFetchRequest() 
     fetchedResultController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath:nil, cacheName: nil) 

     do { 
      try fetchedResultController.performFetch() 
     } 
     catch let error as NSError { 
      print("Could not fetch \(error), \(error.userInfo)") 
     } 
    } 
} 

有可能有更好的方法來編碼;我不是Swift愛好者。

如果您使用FRC委託方法,您至少可以根據需要監視新/刪除的訂單並向電視添加/刪除部分,並且可以使用更新來重新加載相關部分。

+0

非常感謝您的幫助。遺憾的是,只有一個實體可以使用FRC觀看更改,但您提出的解決方案完全按照我的意願工作! – Gerard

相關問題