代码之家  ›  专栏  ›  技术社区  ›  fs_tigre

使用领域对象滚动到UITableView中插入的最后一行

  •  0
  • fs_tigre  · 技术社区  · 6 年前

    我有以下代码可以正常工作,它从 Realm 打电话 groceryList 并将它们显示在 UITableView 根据产品名称降序排列。我想做的是滚动到表中最新插入的行/项,当插入一个新项时,用户可能看不到它,因为这些项是按字母顺序重新排序的,并且最新项可能在tableView上不可见。

    如何滚动到UITableView中最新插入的行/项?

    领域对象:

        class Item:Object{
            @objc dynamic var productName:String = ""
            @objc dynamic var isItemActive = true
            @objc dynamic var createdAt = NSDate()
        }
    
        class ItemList: Object {
            @objc dynamic var listName = ""
            @objc dynamic var createdAt = NSDate()
            let items = List<Item>()
        }
    

    UITableView:

        class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
    
            var allItems : Results<Item>!
            var groceryList : ItemList!
    
            override func viewDidLoad() {
                super.viewDidLoad()
                groceryList = realm.objects(ItemList.self).filter("listName = %@", "groceryList").first              
                updateResultsList()
            }
    
            func updateResultsList(){
                if let list = groceryList{
                    allItems  = activeList.items.sorted(byKeyPath: "productName", ascending: false)
                }
            }
    
            func numberOfSections(in tableView: UITableView) -> Int {
                return 1
            }
            func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                return allItems.count
            }
            func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {       
                let cell = tableView.dequeueReusableCell(withIdentifier: "reusableCell", for: indexPath) as! CustomCell       
                let data = allItems[indexPath.row]      
                cell.displayProductName.text = data.productName
                return cell
            }  
        }
    
    1 回复  |  直到 6 年前
        1
  •  3
  •   Dávid Pásztor    6 年前

    你可以用 Realm 通知以了解数据源的时间 Results 已被修改,然后从那里更新表视图并进行滚动。

    class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
        var allItems: Results<Item>!
        var groceryList: ItemList!
    
        var notificationToken: NotificationToken? = nil
    
        deinit {
            notificationToken?.invalidate()
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            groceryList = realm.objects(ItemList.self).filter("listName = %@", "groceryList").first
            updateResultsList()
            observeGroceryList
        }
    
        func updateResultsList(){
            if let list = groceryList {
                allItems  = activeList.items.sorted(byKeyPath: "productName", ascending: false)
            }
        }
    
        func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return allItems.count
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "reusableCell", for: indexPath) as! CustomCell
            let data = allItems[indexPath.row]
            cell.displayProductName.text = data.productName
            return cell
        }
    
        func observeGroceryList() {
            notificationToken = allItems.observe { [weak self] (changes: RealmCollectionChange) in
                switch changes {
                case .initial:
                    self?.tableView.reloadData()
                case .update(_, let deletions, let insertions, let modifications):
                    // Query results have changed, so apply them to the UITableView
                    self?.tableView.beginUpdates()
                    self?.tableView.insertRows(at: insertions.map({ IndexPath(row: $0, section: 0) }),
                                         with: .automatic)
                    self?.tableView.deleteRows(at: deletions.map({ IndexPath(row: $0, section: 0)}),
                                         with: .automatic)
                    self?.tableView.reloadRows(at: modifications.map({ IndexPath(row: $0, section: 0) }),
                                         with: .automatic)
                    self?.tableView.endUpdates()
                    if let lastInsertedRow = insertions.last {
                        self?.tableView.scrollToRow(at: insertions.last, at: .none, animated: true)
                    }
                case .error(let error):
                    // An error occurred while opening the Realm file on the background worker thread
                    print("\(error)")
                }
            }
        }
    }
    
        2
  •  1
  •   MRizwan33    6 年前

    添加以下代码作为tableview的扩展。

    extension UITableView {
        func scrollToBottom() {
            let sections = numberOfSections-1
            if sections >= 0 {
                let rows = numberOfRows(inSection: sections)-1
                if rows >= 0 {
                    let indexPath = IndexPath(row: rows, section: sections)
                    DispatchQueue.main.async { [weak self] in
                        self?.scrollToRow(at: indexPath, at: .bottom, animated: true)
                    }
                }
            }
        }
    }
    

    现在只需在方法中使用它:

    func updateResultsList(){
           if let list = groceryList{
                 allItems  = activeList.items.sorted(byKeyPath: "productName", ascending: false
                 yourTableView.scrollToBottom()
          }
     }
    

    只要在需要的地方使用这个方法,它应该是向下滚动的。

    yourTableView.scrollToBottom()