簡體   English   中英

沙盒應用OS X 10.10中的NSSavePanel崩潰

[英]NSSavePanel crash in sandbox app OS X 10.10

我在沙盒應用程序中的OS X 10.10中使用NSSavePanel,讓用戶選擇文件的保存位置(非常標准),但是當我調用該應用程序時,該應用程序崩潰了:

NSSavePanel *panel = [NSSavePanel savePanel];

我在調試器中得到這個:

2014-10-14 18:22:16.019 Farm Hand[2807:942766] an error occurred while attempting to connect to listener 'com.apple.view-bridge': Connection interrupted
2014-10-14 18:22:16.020 Farm Hand[2807:942766] *** Assertion failure in +[NSXPCSharedListener connectionForListenerNamed:fromServiceNamed:], /SourceCache/ViewBridge/ViewBridge-99/NSXPCSharedListener.m:394
2014-10-14 18:22:16.023 Farm Hand[2807:942766] An uncaught exception was raised
2014-10-14 18:22:16.023 Farm Hand[2807:942766] NSXPCSharedListener unable to create endpoint for listener named com.apple.view-bridge
2014-10-14 18:22:16.023 Farm Hand[2807:942766] (
    0   CoreFoundation                      0x00007fff8880364c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff9390e6de objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff8880342a +[NSException raise:format:arguments:] + 106
    3   Foundation                          0x00007fff8a3a65b9 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
    4   ViewBridge                          0x00007fff964e40b8 +[NSXPCSharedListener connectionForListenerNamed:fromServiceNamed:] + 151
    5   ViewBridge                          0x00007fff964c2981 -[NSRemoteViewBase serviceMarshalConnection] + 286
    6   ViewBridge                          0x00007fff964c36ae -[NSRemoteViewBase advanceToConfigPhase:awaitingWindowRights:] + 414
    7   ViewBridge                          0x00007fff964d1f7b -[NSWindowCentricRemoteView advanceToConfigPhase] + 947
    8   ViewBridge                          0x00007fff964c4223 -[NSRemoteViewBase viewServiceMarshalProxy:withErrorHandler:] + 88
    9   ViewBridge                          0x00007fff964ba8a8 -[NSRemoteViewBase bridge] + 207
    10  AppKit                              0x00007fff8e859b9d -[NSVBSavePanel init] + 303
    11  AppKit                              0x00007fff8e5a8ec1 +[NSSavePanel newRemotePanel] + 301
    12  AppKit                              0x00007fff8e5a8f53 +[NSSavePanel _crunchyRawUnbonedPanel] + 74
    13  Farm Hand                           0x000000010009526d __40-[RHFlockHomeViewController exportTable]_block_invoke_3 + 109
    14  libdispatch.dylib                   0x00000001002202bb _dispatch_call_block_and_release + 12
    15  libdispatch.dylib                   0x000000010021ad43 _dispatch_client_callout + 8
    16  libdispatch.dylib                   0x0000000100229d9f _dispatch_main_queue_callback_4CF + 1370
    17  CoreFoundation                      0x00007fff88756c59 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    18  CoreFoundation                      0x00007fff887132ef __CFRunLoopRun + 2159
    19  CoreFoundation                      0x00007fff88712838 CFRunLoopRunSpecific + 296
    20  HIToolbox                           0x00007fff94ec743f RunCurrentEventLoopInMode + 235
    21  HIToolbox                           0x00007fff94ec71ba ReceiveNextEventCommon + 431
    22  HIToolbox                           0x00007fff94ec6ffb _BlockUntilNextEventMatchingListInModeWithFilter + 71
    23  AppKit                              0x00007fff8e006821 _DPSNextEvent + 964
    24  AppKit                              0x00007fff8e005fd0 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 194
    25  AppKit                              0x00007fff8dff9f73 -[NSApplication run] + 594
    26  AppKit                              0x00007fff8dfe5424 NSApplicationMain + 1832
    27  Farm Hand                           0x0000000100010552 main + 34
    28  libdyld.dylib                       0x00007fff8d7e85c9 start + 1
)
2014-10-14 18:22:16.027 Farm Hand[2807:942766] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSXPCSharedListener unable to create endpoint for listener named com.apple.view-bridge'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff8880364c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff9390e6de objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff8880342a +[NSException raise:format:arguments:] + 106
    3   Foundation                          0x00007fff8a3a65b9 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
    4   ViewBridge                          0x00007fff964e40b8 +[NSXPCSharedListener connectionForListenerNamed:fromServiceNamed:] + 151
    5   ViewBridge                          0x00007fff964c2981 -[NSRemoteViewBase serviceMarshalConnection] + 286
    6   ViewBridge                          0x00007fff964c36ae -[NSRemoteViewBase advanceToConfigPhase:awaitingWindowRights:] + 414
    7   ViewBridge                          0x00007fff964d1f7b -[NSWindowCentricRemoteView advanceToConfigPhase] + 947
    8   ViewBridge                          0x00007fff964c4223 -[NSRemoteViewBase viewServiceMarshalProxy:withErrorHandler:] + 88
    9   ViewBridge                          0x00007fff964ba8a8 -[NSRemoteViewBase bridge] + 207
    10  AppKit                              0x00007fff8e859b9d -[NSVBSavePanel init] + 303
    11  AppKit                              0x00007fff8e5a8ec1 +[NSSavePanel newRemotePanel] + 301
    12  AppKit                              0x00007fff8e5a8f53 +[NSSavePanel _crunchyRawUnbonedPanel] + 74
    13  Farm Hand                           0x000000010009526d __40-[RHFlockHomeViewController exportTable]_block_invoke_3 + 109
    14  libdispatch.dylib                   0x00000001002202bb _dispatch_call_block_and_release + 12
    15  libdispatch.dylib                   0x000000010021ad43 _dispatch_client_callout + 8
    16  libdispatch.dylib                   0x0000000100229d9f _dispatch_main_queue_callback_4CF + 1370
    17  CoreFoundation                      0x00007fff88756c59 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    18  CoreFoundation                      0x00007fff887132ef __CFRunLoopRun + 2159
    19  CoreFoundation                      0x00007fff88712838 CFRunLoopRunSpecific + 296
    20  HIToolbox                           0x00007fff94ec743f RunCurrentEventLoopInMode + 235
    21  HIToolbox                           0x00007fff94ec71ba ReceiveNextEventCommon + 431
    22  HIToolbox                           0x00007fff94ec6ffb _BlockUntilNextEventMatchingListInModeWithFilter + 71
    23  AppKit                              0x00007fff8e006821 _DPSNextEvent + 964
    24  AppKit                              0x00007fff8e005fd0 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 194
    25  AppKit                              0x00007fff8dff9f73 -[NSApplication run] + 594
    26  AppKit                              0x00007fff8dfe5424 NSApplicationMain + 1832
    27  Farm Hand                           0x0000000100010552 main + 34
    28  libdyld.dylib                       0x00007fff8d7e85c9 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

這是我的完整代碼:

if ([format isEqualToString:@".csv"]) {
            loadingBar = [RHLoadingBar loadingBarWithMessage:@"Preparing File..."];
            [loadingBar showModally];
            [loadingBar start];
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                NSString *string = [[RHFileController sharedController] CSVTableWithObject:sheepArrayController.arrangedObjects propertyKeys:@[@"tagNumber", @"ukNumber", @"age", @"breed", @"comments"] columnHeaders:@[@"Tag Number", @"UK Number", @"Age", @"Breed",  @"Comments"]];
                dispatch_async(dispatch_get_main_queue(), ^{
                    [loadingBar stop];
                    [loadingBar dismiss];
                    NSSavePanel *panel = [NSSavePanel savePanel];
                    [panel beginSheetModalForWindow:[[NSApplication sharedApplication] mainWindow] completionHandler:^(NSInteger result) {

                    }]; 
                });
            });
        }

這是一個已知的錯誤還是在我的代碼中? 如果是已知錯誤,我可以解決。

  • 編輯:這就是我如何解決它,直到Apple修復它(感謝@serren修復):

首先,取消選中主窗口Is Initial Controller中的“ Is Initial Controller (您的應用現在不會自動啟動主窗口)。

然后:

AppDelegate.h

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate>
// Add strong reference to the root window controller
@property (strong) NSWindowController *rootController;


@end

最后,在AppDelegate.m實現applicationDidFinishLaunching:像這樣(記住要設置您的初始控制器標識符,這里是“ HomeView”):

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application
    // Show main window (to avoid powerbox bug)...
    NSStoryboard *sb = [NSStoryboard storyboardWithName:@"Main" bundle:nil];
    rootController = [sb instantiateControllerWithIdentifier:@"HomeView"];
    [rootController showWindow:self];

    // Other custom setup for your App...
}

此過程意味着NSApplicationmainWindow屬性將自動設置為rootController.window 因此,如果您想隨時獲取主窗口,仍然可以調用[[NSApplication sharedApplication] mainWindow]; 同樣, AppDelegateNSApplication單例都對此窗口有很強的引用,這一點很重要(否則該窗口將被釋放並且App將崩潰)。

希望暫時能有所幫助。

簡短的介紹:

這看起來像是一個與ArrayController以及與之相關的其他控制器類似的錯誤,或者它繼承的任何東西或IB中的綁定系統。 這是一個簡單的代碼,詳細說明了問題: https : //www.dropbox.com/s/atwoc2hweh5fjk6/Bug.zip?dl=0

詳細描述:

SDK內似乎發生了一些奇怪的事情。

在我提供的示例中,我有一個使用標准Xcode 6.1模板生成的標准應用程序。 該應用程序已沙箱化。 在應用程序委托內部,我們僅測試NSSavePanel是否可以正常啟動。 ViewController聲明一個名為“ array”的屬性,該屬性隨后綁定到NSArrayController(請參閱Main.storyboard內部)。

如果在此設置中啟動應用程序,您將看到NSSavePanel失敗。 但是,如果我們僅關閉NSArrayController綁定,則對NSSavePanel的調用會奇跡般地起作用。

因此,可以肯定地認為,這只是隱藏在最新的SDK(蘋果需要修復)下的一個錯誤漏洞。

隨時將示例添加到您的Apple錯誤報告中。

Woraround:

看起來,如果您在陣列控制器綁定中禁用了“為不適用的鍵提高”選項,則可以使應用程序再次運行而無需關閉綁定本身。 這可能意味着在設置連接到XPC服務的沙箱之前會引發異常,因此會使應用程序行為異常。

對於蘋果來說,正確的解決方法是將XPC連接初始化代碼放在可以防止奇怪的錯誤和異常的地方,從而確保它始終可以正常工作。

UPDATE

基於serenn建議,我使用以下代碼使我的應用程序按預期運行:

    let sb = NSStoryboard(name: "Main", bundle: nil)!

    // ---

    rootWindowController = sb.instantiateControllerWithIdentifier("MainWindowController") as? NSWindowController

    // ---

    rootWindowController?.showWindow(self)

在我的測試中,我發現rootWindowController?.showWindow(self)可以更好地顯示窗口而不是makeKeyAndOrderFront因為否則,segue無法正確連接(彈出窗口等)。 這種方法對我有用。

不幸的是,上面的答案與我的情況無關,因為在屏幕上沒有創建NSSavePanel的ArrayControllers。

但是,對原始問題的評論之一向我指出了正確的方向,那就是擺脫自定義WindowController子類。 當我這樣做時,面板看起來很好。 但是,由於這不是一個很好的解決方案(萬一您真的想保留您的自定義類),我一直在挖掘。

僅供參考,我正在使用NSStoryboards並為10.10構建應用程序。

當我(臨時)在主窗口上取消選中“可還原”時,我注意到了一些奇怪的行為-每次出現保存面板時,都會出現我的應用程序的新主窗口。 這使我相信,我的應用程序委托與顯示的主窗口存在很大的脫節,尤其是現在故事板具有單獨的應用程序場景和WindowController。

我做了什么:

  1. 選擇我的主窗口控制器,然后取消選中“是初始控制器”(即,未為情節提要設置初始控制器)
  2. 在我的應用程序委托中,在applicationDidFinishLaunching: ,我手動創建了情節提要,並使用InstantiateControllerWithIdentifier加載了窗口控制器instantiateControllerWithIdentifier:
  3. 我將self.window設置為創建的self.window屬性
  4. 我將self.window設置為鍵和訂單前面(使用makeKeyAndOrderFront:

該應用程序將像以前一樣啟動並加載窗口,但是現在保存面板顯示就很好了。 它還與自定義windowController子類一起使用。

最后,作為獎勵,我最終在使用applicationShouldTerminateAfterLastWindowClosed時具有正確的行為(設置為NO)

根據《 應用程序沙箱設計指南》,您應該創建自己的NSDocument子類。 NSDocument有自己的方法來顯示保存對話框:

NSDocument類自動與Powerbox配合使用。 如果用戶使用Finder移動文檔,NSDocument還提供了將文檔保留在沙箱中的支持。

請記住,將應用程序沙箱化后,NSOpenPanel和NSSavePanel類的繼承路徑是不同的。 請參閱使用應用程序沙箱打開和保存對話框行為。

由於存在運行時差異,因此NSOpenPanel或NSSavePanel對象通過App Sandbox繼承的方法較少。 如果您嘗試向NSOpenPanel或NSSavePanel對象發送消息,並且該方法在NSPanel,NSWindow或NSResponder類中定義,則系統會引發異常。 Xcode編譯器不會發出警告或錯誤來提醒您這種運行時行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM