使用Swift在tableView中重新排序Realm.io数据

3
我已经使用Realm.io实现了一个基本的iOS应用程序示例。
我想在我的iOS应用程序中能够重新排列表格行并将顺序保存回Realm。为此,Realm模型包含一个名为“position”的属性。
附注:很抱歉有这么多代码。
import UIKit
import Realm

class Cell: UITableViewCell {
    var position: Int!
    init(style: UITableViewCellStyle, reuseIdentifier: String!) {
        super.init(style: .Subtitle, reuseIdentifier: reuseIdentifier)
    }
}

class Language: RLMObject {
    var title = ""
    var position = Int()
}

class ManagerLanguagesController: UITableViewController, UITableViewDelegate, UITableViewDataSource {

    var array = RLMArray()
    var notificationToken: RLMNotificationToken?
    var editButton = UIBarButtonItem()

    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        notificationToken = RLMRealm.defaultRealm().addNotificationBlock { note, realm in
            self.reloadData()
        }
        reloadData()
    }

    override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int {
        return Int(array.count)
    }

    func setupUI() {
        tableView.registerClass(Cell.self, forCellReuseIdentifier: "cell")
        self.title = "Languages"    
        var addButton = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "add")
        editButton = UIBarButtonItem(title: "Edit", style: .Plain, target: self, action: "edit")
        var buttons = [addButton, editButton]
        self.navigationItem.rightBarButtonItems = buttons
    }

    func add() {
        var addLanguageView:UIViewController = self.storyboard.instantiateViewControllerWithIdentifier("newLanguage") as UIViewController
        self.navigationController.presentViewController(addLanguageView, animated: true, completion: nil)
    }

    func edit () {
        if tableView.editing {      
            /* FROM THIS POINT I'M PROBABLY DOING SOMETHING WRONG.. IT IS NOT WORKING  */
            var positionArray = NSMutableArray()
            let realm = RLMRealm.defaultRealm()
            var i = 0

            for var row = 0; row < tableView.numberOfRowsInSection(0); row++ {
                var cellPath = NSIndexPath(forRow: row, inSection: 0)
                var cell:Cell = tableView.cellForRowAtIndexPath(cellPath) as Cell
                positionArray.addObject(cell.position)
            }

            realm.beginWriteTransaction()
            for row: RLMObject in array {
                row["position"] = positionArray[i]
                i++
            }
            realm.commitWriteTransaction()

            /* -- NOT WORKING END -- */

            tableView.setEditing(false, animated: true)
            editButton.style = UIBarButtonItemStyle.Plain
            editButton.title = "Edit"
        } else{
            tableView.setEditing(true, animated: true)
            editButton.title = "Done"
            editButton.style =  UIBarButtonItemStyle.Done
        }
    }

    override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? {
        let cell = tableView!.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as Cell
        let object = array[UInt(indexPath!.row)] as Language
        cell.textLabel.text = object.title
        cell.position = object.position // I have implemented this to be able to retain initial positions for each row and maybe use this when reordering..
        return cell
    }

    override func tableView(tableView: UITableView!, canMoveRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
        return true
    }

    override func tableView(tableView: UITableView!, moveRowAtIndexPath sourceIndexPath: NSIndexPath!, toIndexPath destinationIndexPath: NSIndexPath!) {
        //  println("Old index: \(sourceIndexPath.indexAtPosition(sourceIndexPath.length - 1)+1)")
        //  println("New index: \(destinationIndexPath.indexAtPosition(sourceIndexPath.length - 1)+1)")
        // Maybe something needs to be implemented here instead...
    }

    func reloadData() {
        array = Language.allObjects().arraySortedByProperty("position", ascending: true)
        tableView.reloadData()
    }

}

提前感谢你的帮助。

2个回答

5

不必使用position属性,相反,您可以将有序数组作为另一个对象的属性来保持。这样,您就不必保持位置最新,并且可以根据需要排列对象:

class Language: RLMObject {
    dynamic var title = ""
}

class LanguageList: RLMObject {
    dynamic var languages = RLMArray(objectClassName: "Language")
}

class ManagerLanguagesController: UITableViewController, UITableViewDelegate, UITableViewDataSource {

    override func viewDidLoad() {
        super.viewDidLoad()

        // create our list
        var realm = RLMRealm.defaultRealm()
        realm.beginWriteTransaction()
        realm.addObject(LanguageList())
        realm.commitWriteTransaction()
        ...
    }

    // helper to get the RLMArray of languages in our list
    func array() -> RLMArray {
        return (LanguageList.allObjects().firstObject() as LanguageList).languages
    }

    override func tableView(tableView: UITableView!, moveRowAtIndexPath sourceIndexPath: NSIndexPath!, toIndexPath destinationIndexPath: NSIndexPath!) {
        var languages = array()
        var object = languages.objectAtIndex(UInt(sourceIndexPath.row)) as Language
        var realm = RLMRealm.defaultRealm()
        realm.beginWriteTransaction()                
        languages.removeObjectAtIndex(UInt(sourceIndexPath.row))
        languages.insertObject(object, atIndex: UInt(destinationIndexPath.row))
        realm.commitWriteTransaction()
    }

    ...
}

谢谢,Ari!我将你的方法“array()”重命名为其他名称,因为它与我的变量同名,而我使用该变量作为表视图的初始数据源。根据你的建议,我不再使用“position”属性,并在所有地方删除了对它的引用。然而,现在,只要我重新排序表格单元,就会出现崩溃错误:“2014-07-30 09:47:23.707 MyApp[37470:1078754] *** Terminating app due to uncaught exception 'RLMException', reason: 'Index is out of bounds.'”。另外,由于我不再依赖“position”属性,以后如何使用Realm查询来排序行呢? - kernelpanic
你成功了吗?在RLMArrays中有重新排列项目顺序的方法。 - Gusutafu

0

这段代码可以让我在使用Swift 2.2结合Realm的TableView中移动行:

func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
    let aux = TimesHome.mutableCopy() as! NSMutableArray
    let itemToMove = aux[fromIndexPath.row]
    let realm = try! Realm()
    realm.beginWrite()
    aux.removeObjectAtIndex(fromIndexPath.row)
    aux.insertObject(itemToMove, atIndex: toIndexPath.row)
    try! realm.commitWrite()

    TimesHome = aux

    let times = realm.objects(ParciaisTimes)
    if times.count  > 0 {
        for tm in times {
            for i in 1...aux.count {
                if aux[i-1].valueForKey("time_id") as! Int == tm.time_id {
                    realm.beginWrite()
                    tm.ordem = i
                    try! realm.commitWrite()
                }
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接