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

过滤域时显示NSPROGRESS指示器

  •  2
  • Jay  · 技术社区  · 8 年前

    安装程序

    Swift 3应用程序RealmSwift 2.10.1,带有一个按钮、tableview和一个不确定的旋转进度指示器(旋转圆圈)

    :

    当用户单击按钮时,查询一个大型领域数据库(数百万条记录),在等待结果的同时,显示进度指示器。

    :

    过滤完成后,进度指示器才会显示。

    :

    //called from button click
    func performFilterAction() {  
         self.filterProgressIndicator.isHidden = false
         self.filterProgressIndicator.startAnimation(nil)
         let predicate = NSPredicate(format: "location = %@", "US")
         let realm = try! Realm()
         self.results = realm.objects(MyClass.self).filter(predicate)
         self.tableView.reloadData()
         self.filterProgressIndicator.isHidden = true
    }
    

    另外 :

    另一个问题是,即使进度指示器隐藏在代码末尾,它也不会隐藏在UI中。

    func performFilterAction() {
         self.filterProgressIndicator.isHidden = false
         self.filterProgressIndicator.startAnimation(nil)
    
         DispatchQueue.global(qos: .background).async {  
              let predicate = NSPredicate(format: "location = %@", "US")
              let realm = try! Realm()
              self.results = realm.objects(MyClass.self).filter(predicate)
              DispatchQueue.main.async {
                  self.tableView.reloadData()
                  self.filterProgressIndicator.isHidden = true
              }
         }
    }
    

    此应用程序正在后台修改autolayout引擎 从主线程访问引擎后的线程。这个可以

    另一次尝试:

    根据提供的答案,我实现了如下收集通知

    func performFilterAction1() {
        self.filterProgressIndicator.isHidden = false
        self.filterProgressIndicator.startAnimation(nil)
        let predicate = NSPredicate(format: "location = %@", "US")
        let realm = try! Realm()
        self.results = realm.objects(MyClass.self).filter(predicate)
    
        self.notificationToken = self.results.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in
            guard let tableView = self?.filterTableView else { return }
            switch changes {
            case .initial:
                // Results are now populated and can be accessed without blocking the UI
                tableView.reloadData()
                self?.filterProgressIndicator.isHidden = true
                break
            case .update(_, let deletions, let insertions, let modifications):
                break
            case .error(let error):
                // An error occurred while opening the Realm file on the background worker thread
                fatalError("\(error)")
                break
            }
        }
    }
    

    其结果是:进度指示器直到 之后 过滤器完成后,它只是瞬间“闪烁”。

    772.00 ms   58.7%   0 s      Main Thread  0x72995
    742.00 ms   56.5%   0 s       start
    742.00 ms   56.5%   0 s        main
    742.00 ms   56.5%   0 s         NSApplicationMain
    625.00 ms   47.6%   1.00 ms          -[NSApplication run]
    377.00 ms   28.7%   0 s           -[NSApplication(NSEvent) sendEvent:]
    342.00 ms   26.0%   0 s            -[NSWindow(NSEventRouting) sendEvent:]
    342.00 ms   26.0%   0 s             -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:]
    342.00 ms   26.0%   0 s              -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:]
    331.00 ms   25.2%   0 s               -[NSControl mouseDown:]
    330.00 ms   25.1%   0 s                -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:]
    330.00 ms   25.1%   0 s                 -[NSCell trackMouse:inRect:ofView:untilMouseUp:]
    319.00 ms   24.2%   0 s                  _os_activity_initiate_impl
    319.00 ms   24.2%   0 s                   -[NSButtonCell _sendActionFrom:]
    319.00 ms   24.2%   0 s                    -[NSCell _sendActionFrom:]
    319.00 ms   24.2%   0 s                     _os_activity_initiate_impl
    319.00 ms   24.2%   0 s                      __26-[NSCell _sendActionFrom:]_block_invoke
    319.00 ms   24.2%   0 s                       -[NSControl sendAction:to:]
    319.00 ms   24.2%   0 s                        -[NSApplication(NSResponder) sendAction:to:from:]
    318.00 ms   24.2%   0 s                         _os_activity_initiate_impl
    259.00 ms   19.7%   0 s                          @objc FilterVC.filterAction(Any) -> ()
    259.00 ms   19.7%   0 s                           FilterVC.filterAction(Any) -> ()
    257.00 ms   19.5%   0 s                            FilterVC.test() -> ()
    238.00 ms   18.1%   0 s                             Results.count.getter
    238.00 ms   18.1%   0 s                              -[RLMResults count]
    238.00 ms   18.1%   0 s                               -[RLMResults count]::$_1::operator()() const
    238.00 ms   18.1%   0 s                                realm::Results::size()
    238.00 ms   18.1%   0 s                                 realm::Query::count(unsigned long, unsigned long, unsigned long) const
    238.00 ms   18.1%   0 s                                  realm::Query::aggregate_internal(realm::Action, realm::DataType, bool, realm::ParentNode*, realm::QueryStateBase*, unsigned long, unsigned long, realm::SequentialGetterBase*) const
    
    2 回复  |  直到 8 年前
        1
  •  1
  •   bdash    8 年前

    这是一个完美的用例 Realm's collection notifications

    var notificationToken: NotificationToken? = nil
    var results: Results<MyClass>? = nil
    
    func performFilterAction() {
      filterProgressIndicator.isHidden = false
      filterProgressIndicator.startAnimation(nil)
    
      let realm = try! Realm()
      results = realm.objects(MyClass.self).filter("location = %@", "US")
      notificationToken = results.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in
        guard let tableView = self?.tableView else { return }
        switch changes {
        case .initial:
          // Results are now populated and can be accessed without blocking the UI
          tableView.reloadData()
          self.filterProgressIndicator.isHidden = true
          break
        case .update(_, let deletions, let insertions, let modifications):
          // Query results have changed, so apply them to the UITableView
          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()
          break
        case .error(let error):
          // An error occurred while opening the Realm file on the background worker thread
          fatalError("\(error)")
          break
        }
      }
    }
    
    deinit {
      notificationToken?.stop()
    }
    

    这使您可以在执行初始过滤时显示进度指示器,并在对集合中的数据进行更改时提供动画更新。如果你不在乎后者,你可以打电话 reloadData() .update 案例也是如此。

        2
  •  0
  •   Alain T.    8 年前

    你有什么视觉上的东西是在自我时触发的吗。结果发生了变化(例如在didSet中)?如果你这样做了,那么这可能就是导致第二个解决方案出错的原因。

    您可以将加载过程发送到主线程,而不是后台线程(即第一种和第二种方法的混合),以便进度指示器有机会出现:

    func performFilterAction() {
         self.filterProgressIndicator.isHidden = false
         self.filterProgressIndicator.startAnimation(nil)
    
         DispatchQueue.main.async {  
              let predicate = NSPredicate(format: "location = %@", "US")
              let realm = try! Realm()
              self.results = realm.objects(MyClass.self).filter(predicate)
              self.tableView.reloadData()
              self.filterProgressIndicator.isHidden = true
         }
    }
    

    func performFilterAction() {
         self.filterProgressIndicator.isHidden = false
         self.filterProgressIndicator.startAnimation(nil)
    
         DispatchQueue.global(qos: .background).async {  
              let predicate = NSPredicate(format: "location = %@", "US")
              let realm = try! Realm()
              let newResults = realm.objects(MyClass.self).filter(predicate)
              DispatchQueue.main.async {
                  self.results = newResults
                  self.tableView.reloadData()
                  self.filterProgressIndicator.isHidden = true
              }
         }
    }