Просмотр таблицы с использованием области не будет перезагружен при удалении в swift - PullRequest
0 голосов
/ 15 декабря 2018

У меня есть простой tableView с сохраненными данными.Я создал кнопку удаления, которая позволяет мне многократное удаление из области.Эта часть работает, именно когда табличное представление должно перезагрузить, кажется, что оно не работает.Я видел много ответов, в которых говорилось, что вы должны перезагрузить его в главном потоке, или просмотреть или что-то еще, используя dispatchQueue.main.async, используя просто обычный tableView.reloadData (), но не перезагрузил просмотр таблицы, но когда я использую версию dispatchQueue, это делаетудалить значение, но обычно последнее значение в tableView.

Например, в моем tableView есть строки Uno и Un в этом порядке убывания.Если я выбрал удаление Uno, когда я нажимаю кнопку удаления, просмотр таблицы перезагружается, оставляя только одно значение, но это значение Uno, но база данных области сообщает мне, что я удалил Uno, и когда я возвращаюсь к этому представлению, отображается Un.Это просто не корректно перезагружается.

Я пытался поместить reloadData в отправку во многих разных местах, но все равно не перезагружается правильно.Мне любопытно, что я делаю не так.

это 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 голосов
/ 25 января 2019

Вот так мне удалось решить эту проблему.

    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()
    }
}

Спасибо

0 голосов
/ 26 декабря 2018

Есть несколько проблем, но главная проблема заключается в том, что вы удаляете объект из области, но этот объект все еще находится в вашем массиве данных dataSource tableView, realmArr .

Существует целый ряд решений, но самое простое - добавить наблюдателя в результаты области, и при добавлении, изменении или удалении элемента обновите массив dataSource, а затем перезагрузите просмотр таблицы.Здесь также можно использовать эти результаты в качестве источника данных вместо отдельного массива.Область Результаты объекты ведут себя очень похоже на массив и являются отличным источником данных.

Концептуально код области похож на

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...