swift – 使用计时器定期更新NSTableCellView内的文本字段

swift – 使用计时器定期更新NSTableCellView内的文本字段,第1张

概述我有一个由几个自定义NSTableCellView组成的tableView.一些视图必须与NSProgressIndicator一起显示计时器(已经过了多少时间). 我创建了一个计时器(带有中央显示器),每100毫秒我用setNeedsDisplay更新textView(或swift中的.needsDisplay = true). 我在具有NSTextField的常规视图中工作的代码很好,但是一旦 我有一个由几个自定义NStableCellVIEw组成的tableVIEw.一些视图必须与nsprogressIndicator一起显示计时器(已经过了多少时间).

我创建了一个计时器(带有中央显示器),每100毫秒我用setNeedsdisplay更新textVIEw(或swift中的.needsdisplay = true).

我在具有NSTextFIEld的常规视图中工作的代码很好,但是一旦文本字段是NStableCellVIEw的一部分,它就无法工作.计时器触发,但不重绘该字段.

如果我从vIEwController中每100毫秒重新加载整个表,它也无法工作.在任何情况下重新加载整个表都不是一个好的解决方案,因为选择每100毫秒丢失一次并且用户不能再编辑(常规)单元格.

那么我应该如何每秒在整个tablevIEw的几个单元格中重新加载一个特定的textFIEld呢?

@IBDesignable class ProgressCellVIEw : NStableCellVIEw{//MARK: propertIEs@IBInspectable var clock : Bool = false //should this type of cell show a clock? (is set to true in interface builder)private lazy var formatter = TimeIntervalFormatter() //move to vIEw controller?: 1 timer for the entire table => but then selection is lostprivate var timer : dispatch_source_t!private var isRunning : Bool = false//MARK: initoverrIDe func awakeFromNib(){    self.timeIndex?.formatter = formatter    if self.clock    {        self.timer = dispatch_source_create(disPATCH_SOURCE_TYPE_TIMER,dispatch_get_main_queue())        dispatch_source_set_timer(timer,dispatch_time(disPATCH_TIME_Now,0),100 * NSEC_PER_MSEC,50 * NSEC_PER_MSEC) //50 ms leeway,is good enough for the human eye        dispatch_source_set_event_handler(timer) {            self.timeIndex?.needsdisplay = true            //self.needsdisplay = true            //self.supervIEw?.needsdisplay = true        }    }}//only run the clock when the vIEw is visibleoverrIDe func vIEwWillMovetoSupervIEw(newSupervIEw: NSVIEw?){    super.vIEwWillMovetoSupervIEw(newSupervIEw)    if self.clock && !isRunning { dispatch_resume(self.timer); isRunning = true }}overrIDe func removeFromSupervIEw(){    super.removeFromSupervIEw()    if self.clock && isRunning { dispatch_suspend(self.timer); isRunning = false  }}//MARK: propertIEsoverrIDe var objectValue: AnyObject? {    dIDSet {        let entry = self.objectValue as! MyEntry        self.progressbar?.doubleValue = entry.progress?.fractionCompleted ?? 0        self.timeIndex?.objectValue = entry.dateStarted             }}//MARK: user interface@IBOutlet var timeIndex     : NSTextFIEld?@IBOutlet var progressbar   : nsprogressIndicator?

}

解决方法 一般来说,重新加载单元格只是为了更改其中的一个元素,更不用说它的状态是非常糟糕的,因为正如你所说,它会给状态带来很多问题,动画也会产生滚动和重新渲染的问题. .话虽如此,这肯定是最简单的解决方案.让我们尝试在编码的概念层面上做更多的事情,因为我可以清楚地看到你有能力自己编码,并有正确的方向

控制器与视图

虽然我在这里让自己处于困境,因为总会有人对此有不同的看法,我认为这是对视图和控制器的正确使用:

> iOS中的控制器用于控制和配置视图.在控制器中,不应该有网络逻辑等,但它应该与您的模型层通信.它应该只作为决策者如何呈现用户期望的输出
>与此相反,观点是应该控制的.应该没有适用于您的应用程序模型的逻辑.应该编写视图以使它们尽可能可重用,除非它们确实有充分的理由不这样做(非常具体的组件等).那些应该有方法,允许您更改该视图的属性.你不应该直接访问单元格上的插座(因为那些可以更改,名称等,但功能可能会保持不变 – 如果没有,没有区别)
>视图应该包含绘图逻辑(它还包括fe.如果你有日期格式化程序,它应该在那里).

所以现在如果我们建立了应该遵循的东西,我认为这是最好的解决方案:

>在控制器中创建一个计时器,让它无限期运行
>创建一个存储,在滚动和数据更改时,您将从中动态添加和删除您感兴趣的单元格
>在每个计时器刻度上,运行整个存储,并使用单元格(setProgress :)上的方法使用适当的数据更新您感兴趣的单元格,这将更新进度和Lb

即使不使用GCD,此解决方案也应该可以工作.问题是如果你有太多的更新请求,它基本上会阻塞UI并且只在有时或者从不渲染它.为此,您应该在主线程上更新UI,但在异步模式下调用,如下所示:

dispatch_async(dispatch_get_global_queue(disPATCH_QUEUE_PRIORITY_HIGH,{ () -> VoID in        dispatch_async(dispatch_get_main_queue(),{ () -> VoID in            // Do update here        })    })
总结

以上是内存溢出为你收集整理的swift – 使用计时器定期更新NSTableCellView内的文本字段全部内容,希望文章能够帮你解决swift – 使用计时器定期更新NSTableCellView内的文本字段所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1007887.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-22
下一篇2022-05-22

发表评论

登录后才能评论

评论列表(0条)

    保存