快速删除使用领域的Tableview不会重新加载

时间:2018-12-15 03:33:47

标签: ios swift uitableview realm

我有一个带有保存数据的简单tableView。我创建了一个删除按钮,使我可以从领域中多次删除。该部分起作用,是当tableview应该重新加载时,它似乎不起作用。我已经看到很多答案,说您应该使用dispatchQueue.main.async将其重新加载到主线程或查看或任何其他内容上 仅使用普通的tableView.reloadData()不会重新加载tableview,但是当我使用dispatchQueue版本时,它确实会删除一个值,但通常会删除tableView中的最后一个值。

例如,我的tableView具有按降序排列的字符串Uno和Un。如果当我按下删除按钮时选择删除Uno,则表视图会重新加载,仅留下一个值,但该值为Uno,但是领域数据库告诉我我删除了Uno,当我返回该视图时,它显示Un。只是无法正确重新加载。

我尝试将reloadData放置在分派器中的许多不同位置,但是仍然不能正确地重新加载。我很好奇我在做什么错。

这是带有tableview的viewController,在其中删除tableView中的数据:

    import UIKit
import Realm
import RealmSwift

class OtherViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var otherTableView: UITableView!

    var realm: Realm!
    var realmedData = ""

    var realmList: Results<Realmed> {
        get {
            return realm.objects(Realmed.self)
        }
    }
    let deleteBtn = UIBarButtonItem()
    var testingBool = false
    var realmArr = [String]()
    var idValue = [Int]()
    var idArr = [Int]()

    var spanArrValue: [String] = []



    override func viewDidLoad() {
        super.viewDidLoad()
        otherTableView.reloadData()
        realm = try! Realm()
        self.otherTableView.delegate = self
        self.otherTableView.dataSource = self
        self.otherTableView.reloadData()
        deleteBtnInfo(btn: deleteBtn)
        self.navigationItem.rightBarButtonItem = deleteBtn
    }



    func deleteBtnInfo(btn: UIBarButtonItem) {
        btn.title = "Delete"
        btn.style = .plain
        btn.target = self
        btn.action = #selector(didTapDeleteBtn(sender:))
        testingBool = false

    }

    @objc func didTapDeleteBtn(sender: AnyObject) {
        testingBool = !testingBool
        if testingBool == true {
            deleteBtn.title = "Remove"
            otherTableView.allowsMultipleSelection = true
            otherTableView.allowsMultipleSelectionDuringEditing = true
        } else if testingBool == false {
            deleteBtn.title = "Delete"
            didPressRemove()
            DispatchQueue.main.async {
                self.otherTableView.reloadData()
            }
            otherTableView.allowsMultipleSelection = false
            otherTableView.allowsMultipleSelectionDuringEditing = false
        }
    }

    func didPressRemove() {
        if idValue.count == 0 {
            print("Please Select what to Delete")
        } else {
            deleteRealm(idInt: idValue)

        }
    }

    func deleteRealm(idInt: [Int]) {
        do {
            try realm.write {
                for deleteIndex in idInt {
                    let deleteValue = realm.objects(RealmTwo.self).filter("id == %@", deleteIndex as Any)
                    print(deleteIndex)
                    realm.delete(deleteValue)


                }

            }
        } catch {

        }
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        var counted = realm.objects(RealmTwo.self).filter("realmLbl == %@", realmedData)
        return counted.count

    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "otherCell", for: indexPath) as! OtherTableViewCell
        var celledItem = realm.objects(Realmed.self)
        for item in celledItem {
            for items in item.realmTwo {
                self.idArr.append(items.id)
                self.realmArr.append(items.spanish)
            }
        }
        cell.otherLbl.text = "\(realmArr[indexPath.row])"
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if testingBool == false {
            print(realmArr[indexPath.row])
        } else {
            self.idValue.append(idArr[indexPath.row])
            print(spanArrValue)
        }
    }


    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        if testingBool == true {
            if let index = idValue.index(of: idArr[indexPath.row]) {
                idValue.remove(at: index)
                print(spanArrValue)
            }
        }
    }
}

这是我要删除的数据的领域类。

    import Foundation
import UIKit
import Realm
import RealmSwift

class RealmTwo: Object {
    @objc dynamic var id = Int()
    @objc dynamic var realmLbl = String()
    @objc dynamic var spanish = String()
    @objc dynamic var french = String()
    let realmed = LinkingObjects(fromType: Realmed.self, property: "realmTwo")



    convenience init(id: Int, realmLbl: String, spanish: String, french: String) {
        self.init()
        self.id = id
        self.realmLbl = realmLbl
        self.spanish = spanish
        self.french = french
    }

}

如上所述,我将reloadData()放置在不同的位置,这些也是我放置它们的位置,以防万一您想知道:

 func didPressRemove() {
    if idValue.count == 0 {
        print("Please Select what to Delete")
    } else {
        deleteRealm(idInt: idValue)
        DispatchQueue.main.async {
            self.otherTableView.reloadData()
        }
    }
}


    func deleteRealm(idInt: [Int]) {
    do {
        try realm.write {
            for deleteIndex in idInt {
                let deleteValue = realm.objects(RealmTwo.self).filter("id == %@", deleteIndex as Any)
                print(deleteIndex)
                realm.delete(deleteValue)
                DispatchQueue.main.async {
                    self.otherTableView.reloadData()
                }

            }

        }
    } catch {

    }
}

我只是不确定reloadData应该放在哪里,或者这是否是真正的问题。谢谢您的帮助,请问我还有什么可以做的。

2 个答案:

答案 0 :(得分:1)

有两个问题,但主要问题是您正在从领域中删除对象,但该对象仍在dataSource tableView数组 realmArr 中徘徊。

有很多解决方案,但是最简单的方法是将观察者添加到领域结果中,并且在添加,更改或删除项目时,请先更新dataSource数组,然后重新加载tableview。这里的一种选择是使用这些结果作为数据源,而不是单独的数组。领域 Results 对象的行为与数组非常相似,并且非常适合作为数据源。

从概念上讲,领域代码类似于

notificationToken = results.observe { [weak self] (changes: RealmCollectionChange) in
    guard let tableView = self?.tableView else { return }
    switch changes {
    case .initial:
        tableView.reloadData() //this is when the realm data is intially loaded.
    case .update(_, let deletions, let insertions, let modifications):
        //handle add, edit and modify per event.
        // with an add, add the provided object to your dataSource
        // same thing for remove and modify
    case .error(let error):
        // An error occurred while opening the Realm file on the background worker thread
        fatalError("\(error)")
    }
    //reload the tableView now the dataSource has been updated
}

有几种处理这些事件的选项,它们都在Realm文档中进行了介绍。有关设置通知的更多详细信息,请参见Realm Notifications

第二种选择是手动保持同步。例如从Realm删除项目时,还要从dataSource数组中删除项目

答案 1 :(得分:1)

这就是我设法解决此问题的方法。

    import UIKit
import Realm
import RealmSwift

class OtherViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    var notificationToken: NotificationToken? = nil

    @IBOutlet weak var otherTableView: UITableView!

    var realm: Realm!
    var realmedData = ""

    var realmList: Results<RealmTwo> {
        get {
            return realm.objects(RealmTwo.self).filter("%@ == realmLbl", realmedData)
        }
    }
    var realmingList: Results<RealmTwo> {
        get {
            return realm.objects(RealmTwo.self)
        }
    }
    let deleteBtn = UIBarButtonItem()
    var testingBool = false
    var realmArr = [String]()
    var idValue = [Int]()
    var idArr = [Int]()

    var spanArrValue: [String] = []




    override func viewDidLoad() {
        super.viewDidLoad()
        otherTableView.allowsMultipleSelectionDuringEditing = true
        realm = try! Realm()
        notificationToken = realmList.observe { [weak self] (changes: RealmCollectionChange) in
            guard let tableView = self?.otherTableView else {return}
            switch changes {
            case .initial:
                tableView.reloadData()
            case .update(_, let deletions, let insertions, let modifications):
                tableView.beginUpdates()
                tableView.insertRows(at: insertions.map({ IndexPath(row: $0, section: 0) }),
                                     with: .automatic)

                tableView.deleteRows(at: deletions.map({ IndexPath(row: $0, section: 0)}),
                                     with: .automatic)
                tableView.reloadRows(at: modifications.map({ IndexPath(row: $0, section: 0) }),
                                     with: .automatic)
                tableView.endUpdates()
            case .error(let error):
                fatalError("\(error)")
            }
        }
        self.otherTableView.delegate = self
        self.otherTableView.dataSource = self
        self.otherTableView.reloadData()
        deleteBtnInfo(btn: deleteBtn)
        self.navigationItem.rightBarButtonItem = deleteBtn
    }



    func deleteBtnInfo(btn: UIBarButtonItem) {
        btn.title = "Delete"
        btn.style = .plain
        btn.target = self
        btn.action = #selector(didTapDeleteBtn(sender:))
        testingBool = false
    }

    @objc func didTapDeleteBtn(sender: AnyObject) {
        testingBool = !testingBool
        if testingBool == true {
            deleteBtn.title = "Remove"
        } else if testingBool == false {
            deleteBtn.title = "Delete"
        }
    }

    func didPressRemove() {
        if testingBool == false {
            print("Select what to Delete")
        } else {
            deleteRealm(idInt: idValue)
            otherTableView.isEditing = false
        }
    }

    @IBAction func pressEdit(_ sender: Any) {
        testingBool = !testingBool
        if testingBool == true {
            otherTableView.isEditing = true
        } else if testingBool == false {
            otherTableView.isEditing = false
        }
    }

    @IBAction func pressDelete(_ sender: Any) {
        deleteRealm(idInt: idValue)

    }

    func deleteRealm(idInt: [Int]) {
        do {
            try realm.write {
                for deleteIndex in idInt {
                    let deletingValue = realmList.filter("id == %@", deleteIndex as Any)
                    print("DeleteValue: \(deletingValue)")
                    realm.delete(deletingValue)

                }
            }
        } catch {

        }
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return realmList.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "otherCell", for: indexPath) as! OtherTableViewCell
        cell.otherLbl.text = realmList.filter("%@ == realmLbl", realmedData)[indexPath.row].spanish
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if otherTableView.isEditing == false {
        } else {
            let idArr = realmList.filter("%@ == realmLbl", realmedData)[indexPath.row].id
            self.idValue.append(idArr)
            print("ID: \(idValue)")
        }
    }


    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        if otherTableView.isEditing == true {
            let idArr = realmList.filter("%@ == realmLbl", realmedData)[indexPath.row].id
            if let index = idValue.index(of: idArr) {
                idValue.remove(at: index)
                print("ID: \(idValue)")
            }
        }
    }
    deinit {
        notificationToken?.invalidate()
    }
}

谢谢

相关问题