Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cell reordering not working via canMoveRowAtIndexPath: #35

Open
pincheira opened this issue Aug 12, 2015 · 6 comments
Open

Cell reordering not working via canMoveRowAtIndexPath: #35

pincheira opened this issue Aug 12, 2015 · 6 comments

Comments

@pincheira
Copy link

Hi guys, do you have any idea why cell reordering doesn't work after setting YES for editing mode on the tableview? Is it supported?

Thanks!

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}
@bigfish24
Copy link
Contributor

Cell reordering isn't supported out of the box. Since RBQFRC works off of a Realm query (RLMResults), to handle reordering you would need to sort the objects and adjust the sort property value of the object for the cell being moved when it changes to reflect the new position. This can get pretty tough. Instead, what needs to be included is adding support for RLMArray to back RBQFRC. This way the sort is defined by the array so you can simply adjust the index of the objects when moving them. If you need to support reordering the data model should use RLMArray typically over backing the table with a query. I want to add support so RBQFRC can monitor changes on an RLMArray but haven't found time yet.

@bigfish24
Copy link
Contributor

One cool thing is that Realm just added support for KeyValueObserving on RLMArray so this would allow RBQFRC to work on an RLMArray and not require any manual effort to log changes. When I find some time potentially this weekend I was going to look into adding support for this.

@pincheira
Copy link
Author

@bigfish24 Nice and thank you for the explanation!

@bigfish24
Copy link
Contributor

@jpincheira I added preliminary support for RLMArray with Realm's KVO support in 0.95. Check it out in the KVO branch

Go to Dynamic--> RBQFRCDynamicExample

You can create an RBQArrayFetchRequest that is based on a specific persisted RLMArray. This allows simpler handling of moves... and it works with KVO so you don't have to actually manually log any changes.

The only downside is that Realm only supports insert/delete. A point release will be coming that add KVO support for move/exchange methods on RLMArray. The other issue is that because the FRC supports sections, I hadn't yet figured out a good way to handle managing the RLMArray indexes changing when using sections.

@alexSchaefer84
Copy link

I don't want to have an extra RLMArray which stores my rows. This works for me:

override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
        var tasks = Array(fetchedResultsController.fetchedObjects)
        let task = tasks[fromIndexPath.row]
        tasks.removeAtIndex(fromIndexPath.row)
        tasks.insert(task, atIndex: toIndexPath.row)

        movingRow = true
        try! realm.write{
            // reorder all tasks...
            (0..<tasks.count).forEach{tasks[$0].displayOrder = $0}
            // ...notify change for moved object
            ChangeLogger.loggerForRealm(realm).didChangeObject(task)
        }
        movingRow = false
    }

and in delegate methods

extension TaskTableViewController: FetchedResultsControllerDelegate {
    func controllerWillChangeContent<T: Object>(controller: FetchedResultsController<T>) {
        if movingRow { return }
        tableView.beginUpdates()
    }

    func controllerDidChangeObject<T: Object>(controller: FetchedResultsController<T>, anObject: SafeObject<T>, indexPath: NSIndexPath?, changeType: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
        if movingRow { return }

        switch changeType {
        case .Insert:
            tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
            break
        case .Update:
            tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
            break
        case .Delete:
            tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
            break
        case .Move:
            tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
            tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
            break
        }
    }

    func controllerDidChangeSection<T:Object>(controller: FetchedResultsController<T>, section: FetchResultsSectionInfo<T>, sectionIndex: UInt, changeType: NSFetchedResultsChangeType) {
    }

    func controllerDidChangeContent<T: Object>(controller: FetchedResultsController<T>) {
        if movingRow { return }
        tableView.endUpdates()
    }
}

@bigfish24
Copy link
Contributor

If you are happy with the performance then that does work, but it is less than ideal. Using an RLMArray is better since it already maintains ordering versus RLMResults needing to be sorted on a property to have an order.

I was wanting to add support for RLMArray so that the order isn't based on a property value... however, I don't see myself doing more work on this because Realm is getting very close to adding fine-grained notifications directly into the binding.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants