[英]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) {
}];
});
});
}
這是一個已知的錯誤還是在我的代碼中? 如果是已知錯誤,我可以解決。
首先,取消選中主窗口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...
}
此過程意味着NSApplication
的mainWindow
屬性將自動設置為rootController.window
。 因此,如果您想隨時獲取主窗口,仍然可以調用[[NSApplication sharedApplication] mainWindow];
同樣, AppDelegate
和NSApplication
單例都對此窗口有很強的引用,這一點很重要(否則該窗口將被釋放並且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。
我做了什么:
applicationDidFinishLaunching:
,我手動創建了情節提要,並使用InstantiateControllerWithIdentifier加載了窗口控制器instantiateControllerWithIdentifier:
self.window
設置為創建的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.