2015-02-09 67 views
2

我在Swift iOS應用程序中有一個tableView,允許用戶重新排序行。點擊一個編輯按鈕,可以重新排序或刪除行,然後重新點擊編輯按鈕(現在讀取完成)以完成該過程。在使用tableView之後將新訂單保存到核心數據:moveRowAtIndexPath:toIndexPath:方法

如果我只是簡單地使用tableView:moveRowAtIndexPath:toIndexPath:方法,它就像上面描述的那樣工作,並且表格顯示了當Done被點擊時正確地重新排序的行。但是在返回表時,它不記得新的順序,所以我在覈心數據中添加了一個新的「位置」變量(Int),並且我已經根據該表對自己的表進行了排序。

我的問題是,在用戶移動了一行並點擊完成之後,該表立即重新命令它自己回到之前的狀態。因此,在我的代碼可以正確捕獲新訂單並將其重新寫入核心數據之前,它將在覈心數據中使用舊的(原始)位置變量。

有沒有辦法讓這個新訂單在表重新加載之前單擊完成時捕獲?

這裏是我的代碼來處理移動:

func tableView(tableView: UITableView!, moveRowAtIndexPath sourceIndexPath: NSIndexPath!, toIndexPath destinationIndexPath: NSIndexPath!) { 
} 

這裏是我的代碼做的是按下時調用。我通過我的表,並重新分配在此基礎上的核心數據的人的處境變的每行的新行:

for currentIteration in 0..<tableView.numberOfRowsInSection(0) { 
    var indexPathForCurrentIteration = NSIndexPath(forRow: currentIteration, inSection: 0) 
    let personAtCurrentIndexIteration = fetchedResultsController.objectAtIndexPath(indexPathForCurrentIteration) as PersonModel 
    personAtCurrentIndexIteration.position = indexPathForCurrentIteration.row 
    println("\(personAtCurrentIndexIteration.name) has a position value of \(personAtCurrentIndexIteration.position)") 
    (UIApplication.sharedApplication().delegate as AppDelegate).saveContext() 
     tableView.reloadData(); 
} 

上面按下Done按鈕時被調用,但我也打過電話是內moveRowAtIndexPath方法沒有成功(相同的結果 - 它會在按下Done時重新加載表格的舊順序)。我也試過註釋掉reloadData沒有成功。

我認爲我的問題可能在於上述內容沒有捕獲新的行順序,而是仍舊獲得舊的行順序。如果是這種情況,那麼我不知道讓它「等待」以獲得新的行順序的最簡單方法。

我開始考慮的一個更長的解決方法是捕獲移動行的初始和最終行值,並基於該更新相應地更新剩餘行的值。其中一些代碼在下面,但我停止了,因爲我認爲這可能是一種更聰明的方式。

if((sourceIndexPath.row > indexPathForCurrentIteration.row) && (destinationIndexPath.row > indexPathForCurrentIteration.row)) { 
    //if the moved row was ahead of this row before AND after the move, do nothing (don't change this row's position value) 
    //println("\(personAtCurrentIndexIteration.name)'s position was unchnaged") 
} else if((sourceIndexPath.row > indexPathForCurrentIteration.row) && (destinationIndexPath.row < indexPathForCurrentIteration.row)) { 
    //if the moved row was ahead of this row before BUT behind it after the move, then this row's position value needs to be bumped up one number 
    personAtCurrentIndexIteration.position = indexPathForCurrentIteration.row+1 
//Etc... 

在此先感謝您提供的任何幫助。

回答

1

我不能幫助解決您的問題,因爲我需要更多的代碼。我在Core Data項目中的做法是維護一個本地緩衝區,用於執行所有操作並在適當時更新Core Data。例如:

  1. 我更新從核心數據的本地緩存的初始控制器
  2. 的viewDidLoad中我大多工作在本地緩存,直到我做類似移動和刪除行。那時我更新了核心數據。這主要是單向操作,因爲我的本地緩衝區是最新的。它可以通過一個好的算法變得高效。
  3. 您仍然需要維護行順序整數,因爲核心數據不能保證維持特定順序。
  4. 我還更新了didReceiveMemoryWarning中的核心數據,以防我收到警告。

有哪些風險?

如果你的程序被終止的didReceiveMemoryWarning結果是,有您的數據可能是舊的風險。如果你有一個大桌子,並且用戶很多,那麼這種方法可能不適合,因爲在大更新期間遇到延遲。我相信還有其他人。

+0

感謝您快速回復Syed,非常感謝。因此,您在控制器的初始視圖上構建本地緩衝區,使用該緩衝區以正確的順序顯示行,然後在進行編輯時更新該緩衝區。我會嘗試這一點,並希望它會允許我點擊完成後顯示新的行順序(然後我會將新訂單寫入核心數據)。 – ScreenWatcher 2015-02-15 16:41:26

5
  1. 添加到CoreData「orderPosition」類型的Int屬性並將orderPosition添加到您的模型文件。

  2. 當你添加一些數據到你CoreData,還加orderPosition值

    let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate 
        let contxt: NSManagedObjectContext = appDel.managedObjectContext! 
        let en = NSEntityDescription.entityForName("MyCoreData", inManagedObjectContext: contxt) 
        let freq = NSFetchRequest(entityName: "MyCoreData") 
        var MyData = contxt.executeFetchRequest(freq, error: nil)! 
        var newItem = Model(entity: en!, insertIntoManagedObjectContext: contxt) 
        var newOrderPosition = MyData.count 
    
    
        //here you add some data to your CoreData 
        //and also you must add new order position 
        newItem.orderPosition = orderPosition 
    
  3. 在你的TableView必須創建一個將數組排序,你會在你的TableView中顯示的功能。事情是這樣的:

    func RefreshCoredata() 
    { 
        let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate 
        let freq = NSFetchRequest(entityName: "MyCoreData") 
        let contxt: NSManagedObjectContext = appDel.managedObjectContext! 
    
        let sortDescriptor = NSSortDescriptor(key: "orderPosition", ascending: true) 
        freq.sortDescriptors = [sortDescriptor] 
        MyData = contxt.executeFetchRequest(freq, error: nil)! 
    
    } 
    
  4. 記住,你必須始終排序您的陣列之前送他到餐桌!

  5. ,當你想你的重新排序表中的行你必須做什麼? :

    override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool { 
    return true 
    } 
    
    override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { 
    
    let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate 
    let contxt: NSManagedObjectContext = appDel.managedObjectContext! 
    
    RefreshCoredata() 
    
    
    if fromIndexPath.row > toIndexPath.row 
    { 
        for i in toIndexPath.row..<fromIndexPath.row 
    
        { 
         MyData[i].setValue(i+1, forKey: "orderPosition") 
    
    
        } 
    
        MyData[fromIndexPath.row].setValue(toIndexPath.row, forKey: "orderPosition") 
    } 
    if fromIndexPath.row < toIndexPath.row 
    { 
    
        for i in fromIndexPath.row + 1...toIndexPath.row 
    
        { 
         MyData[i].setValue(i-1, forKey: "orderPosition") 
    
    
        } 
    
        MyData[fromIndexPath.row].setValue(toIndexPath.row, forKey: "orderPosition") 
    
    
    
    } 
    
    contxt.save(nil) 
    
    RefreshCoredata() 
    
    } 
    

這就需要重置您的CoreData排序位置

  • 什麼,當你想刪除一些表中的行必須做什麼?

    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: 
    UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) 
    { 
    if editingStyle == .Delete { 
    let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate 
    let contxt: NSManagedObjectContext = appDel.managedObjectContext! 
    RefreshCoredata() 
    contxt.deleteObject(MyData[indexPath.row] as NSManagedObject) 
    for i in indexPath.row + 1..<MyData.count 
         { 
          MyData[i].setValue(i-1, forKey: "orderPosition") 
         } 
    RefreshCoredata() 
    
    tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic) 
    contxt.save(nil) 
    
    } 
    
  • 這一切!

    0

    我最近解決了這個問題中的應用程序,我提出,存儲在覈心數據的地方的列表,而這些地方被轉移到一個數組位[]表中的視圖中顯示。

    如上所述,您需要在您的實體中創建'orderID'屬性。

    當你重新排列moveRowAt一排,確保你重新加載表數據。

    override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { 
        let movedObject = places[sourceIndexPath.row] 
        places.remove(at: sourceIndexPath.row) 
        places.insert(movedObject, at: destinationIndexPath.row) 
    
        tableView.reloadData() 
    } 
    

    這將重新加載表中的每個單元格。因此,當你設置在cellForRowAt函數中的每個單元格的內容,那麼你可以使用

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
        let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "Cell") 
    
        places[indexPath.row].setValue(indexPath.row, forKey: "orderID") 
        cell.textLabel?.text = places[indexPath.row].value(forKey: "name") as? String 
    
        return cell 
    
    } 
    

    可能低效後的一舉一動,但對於小型數據集,這是好的重新加載數據集將訂單。如果您需要某種其他順序,也不起作用,因爲這只是將每個值分配給當前放置的單元格的索引。