Cocoa从不存在的NSViewController

时间:2016-08-04 18:40:23

标签: swift cocoa

在我的mac应用程序中,我正在呈现一个登录窗口(通过sheet segue在NSViewController中)。它上面有一个OK按钮,当我按下它时,我打网络电话。在网络通话结束时,我会做一些事情,然后解散表格。事实上,这张纸确实消失了。

现在回到我的NSViewController,它出现了登录窗口,我开始上下滚动NSTableView。我收到有关未提交的CATransaction消息的CoreAnimation警告。有时它会导致崩溃,有时则不会。

这是我得到的堆栈跟踪:

  

CoreAnimation:警告,删除线程与未提交的CATransaction;创建者:
  0 QuartzCore 0x00007fff8befe69a _ZN2CA11Transaction4pushEv + 318
  1 QuartzCore 0x00007fff8befe19a _ZN2CA11Transaction15ensure_implicitEv + 276
  2 QuartzCore 0x00007fff8bf04719 _ZN2CA5Layer13thread_flags_EPNS_11TransactionE + 37
  3 QuartzCore 0x00007fff8bf04668 _ZN2CA5Layer4markEPNS_11TransactionEjj + 64
  4 QuartzCore 0x00007fff8bf0612b _ZN2CA5Layer25set_needs_display_in_rectERK6CGRect + 333
  5 QuartzCore 0x00007fff8bf05fdc - [CALayer setNeedsDisplayInRect:] + 25
  6 AppKit 0x00007fff91aff2e8 _NSBackingLayerSetNeedsDisplayInRect + 319
  7 AppKit 0x00007fff91aff1a3 - [_ NSBackingLayer setNeedsDisplayInRect:] + 61
  8 QuartzCore 0x00007fff8bf05f9d - [CALayer setNeedsDisplay] + 62
  9 AppKit 0x00007fff91aff98b - [NSView(NSInternal)_setLayerNeedsDisplayInViewRect:] + 606
  10 AppKit 0x00007fff91acd88e NSViewSetNeedsDisplayInRect + 945
  11 AppKit 0x00007fff91acd4d6 - [NSView setNeedsDisplayInRect:] + 48
  12 AppKit 0x00007fff91acd2ed - [NSView setNeedsDisplay:] + 81
  13 AppKit 0x00007fff91e48905 - [NSProgressIndicator setDoubleValue:] + 338
  14数字交通系统0x0000000100063fba _TFFFC22Digital_Traffic_System19LoginViewControllerP33_5EDE918279C9F0B1F3EE7B966507D60715okButtonPressedFCSo8NSButtonT_U_FGSqPs9AnyObject__T_U_FTSSSi_T_ + 266
  15数字交通系统0x0000000100064282 _TTRXFo_oSSdSi_dT__XFo_iTSSSi__iT__ + 66

第14行显示来自LoginViewController的我的“okButtonPressed”方法,然后在第13行我看到它在谈论我的NSProgressIndicator试图设置一个值。它现在甚至不应该存在:(

这是该方法的样子:

final class LoginViewController: NSViewController, HasMOC {
    @IBOutlet private weak var progressBar: NSProgressIndicator!

    @IBAction private func okButtonPressed(sender: NSButton) {
        sender.enabled = false

        commitEditing()

        // Webserver uses Alamofire to make async web calls.
        Webserver.sharedInstance.startupData {
            [unowned self] data in

            defer { sender.enabled = true }

            guard let json = data as? [[[String : AnyObject]]] else {
                NSAlert.okWithMessage("Failed to download data from web server.")
                return
            }

            self.progressBar.hidden = false

            DataImporter.importData(json, managedObjectContext: self.managedObjectContext,
                onType: {
                    [weak self] str, max in
                    self?.progressBar.doubleValue = 0
                    self?.progressBar.maxValue = Double(max)
                    self?.progressText.stringValue = str
                }, onEntity:  {
                    [weak self] in
                    self?.progressBar.incrementBy(1)
                }, onComplete: {
                    [weak self] in
                    (NSApplication.sharedApplication().delegate as! AppDelegate).showHideReportMenu()

                    self?.onLoginSuccessful?()

                    self?.dismissController(nil)
            })
        }
}

我在初始块中使用unowned,因为除非Web调用已返回,否则此窗口不会消失。没有按钮可以让它手动消失。

1 个答案:

答案 0 :(得分:0)

您的服务回调在非UI线程上执行,您尝试更新UI元素。

你应该将它们移到主队列上,即:

NSOperationQueue.mainQueue().addOperationWithBlock {
        [unowned self] in
        //Your code changing UI elements, kicking animations .e.t.c
    }