2012-12-13 14 views
0

我有一個標準的NSTableView基於單元格的內容模式,它的dataSource是一個數組控制器附加到我的AppDelegate的managedObjectContext。在代表,該代碼刪除在後臺線程對象(DB可以有30K +對象,所以這是很好的有一個響應的用戶界面和一個進度條和取消選項):NSTableView錯誤:行1應該在有效的可見部分

-(void)deleteObjects:(NSArray*)objs completionBlock:(void (^)(void))aBlock 
{ 
     [self showCancelButton:YES]; 
     __block __typeof__(self) blockself = self; 
     dispatch_group_t dispatchGroup = dispatch_group_create(); 
     dispatch_group_async(dispatchGroup, dispatch_get_global_queue(0, 0), ^{ 
      NSManagedObjectContext *mainContext = [(AppDelegate*)[[NSApplication sharedApplication] delegate] managedObjectContext]; 
      [objs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
       [mainContext deleteObject:obj]; 
       if ((idx % saveSpace == 0) && (idx > 0)) { 
        dispatch_sync(dispatch_get_main_queue(), ^{ 
         NSError *error; 
         [blockself.managedObjectContext save:&error]; 
         theProgressOverlay.filesCount -= saveSpace; // 
        }); 
       } 
       if (isCancelled) { 
        *stop = TRUE; 
       } 
      }]; 
      NSError *error; 
      [mainContext save:&error]; 
      NSLog(@"delete error: %@",error); 
      if (aBlock) { 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        [self showCancelButton:NO]; 
        aBlock(); 
       }); 
      } 
     }); 
} 

這個方法是由被叫代碼:

NSFetchRequest *toDelFetch = [NSFetchRequest fetchRequestWithEntityName:entity]; 
    [toDelFetch setIncludesPropertyValues:NO]; 
    NSError *error; 
    NSArray *toDelObjs = [self.managedObjectContext executeFetchRequest:toDelFetch error:&error]; 
    NSLog(@"Error: %@",error); 
    if (!toDelObjs || toDelObjs.count < 1) { 
     return FALSE; 
    } 
    [self deleteObjects:toDelObjs completionBlock:{NSLog(@"Finished");}]; 

這一切似乎很好地工作:用戶界面的響應和取消按鈕總是工作,但每隔一段時間我得到的錯誤:

2012-12-13 19:31:53.352 QS[1399:403] *** Assertion failure in -[NSTableRowData _addRowViewForVisibleRow:withPriorView:], /SourceCache/AppKit/AppKit-1138.51/TableView.subproj/NSTableRowData.m:2484 
2012-12-13 19:31:53.353 QS[1399:403] Row 1 should be in the valid visible section 
2012-12-13 19:31:53.358 QS[1399:403] (
    0 CoreFoundation      0x00007fff8b773f56 __exceptionPreprocess + 198 
    1 libobjc.A.dylib      0x00007fff88715d5e objc_exception_throw + 43 
    2 CoreFoundation      0x00007fff8b773d8a +[NSException raise:format:arguments:] + 106 
    3 Foundation       0x00007fff8db1a71f -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 169 
    4 AppKit        0x00007fff917c6003 -[NSTableRowData _addRowViewForVisibleRow:withPriorView:] + 164 
    5 AppKit        0x00007fff917c5ef2 -[NSTableRowData _addRowViewForVisibleRow:withPriorRowIndex:inDictionary:withRowAnimation:] + 184 
    6 AppKit        0x00007fff917c5e38 -[NSTableRowData _addRowViewForVisibleRow:] + 38 
    7 AppKit        0x00007fff917c557c -[NSTableRowData _unsafeUpdateVisibleRowEntries] + 448 
    8 AppKit        0x00007fff917c5397 -[NSTableRowData updateVisibleRowViews] + 95 
    9 AppKit        0x00007fff9175d854 -[NSTableView viewWillDraw] + 156 
    10 AppKit        0x00007fff916c1f08 -[NSView viewWillDraw] + 666 
    11 AppKit        0x00007fff916c1f08 -[NSView viewWillDraw] + 666 
    12 AppKit        0x00007fff916c2796 -[NSScrollView viewWillDraw] + 43 
    13 AppKit        0x00007fff916c1f08 -[NSView viewWillDraw] + 666 
    14 AppKit        0x00007fff916c1f08 -[NSView viewWillDraw] + 666 
    15 AppKit        0x00007fff916c0c4d -[NSView _sendViewWillDrawInRect:clipRootView:suppressRecursion:] + 1358 
    16 AppKit        0x00007fff916bf9b8 -[NSView displayIfNeeded] + 1039 
    17 AppKit        0x00007fff916bf375 _handleWindowNeedsDisplayOrLayoutOrUpdateConstraints + 648 
    18 CoreFoundation      0x00007fff8b7338e7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23 
    19 CoreFoundation      0x00007fff8b733846 __CFRunLoopDoObservers + 374 
    20 CoreFoundation      0x00007fff8b708af9 __CFRunLoopRun + 825 
    21 CoreFoundation      0x00007fff8b708486 CFRunLoopRunSpecific + 230 
    22 HIToolbox       0x00007fff8cb352bf RunCurrentEventLoopInMode + 277 
    23 HIToolbox       0x00007fff8cb3c4bf ReceiveNextEventCommon + 181 
    24 HIToolbox       0x00007fff8cb3c3fa BlockUntilNextEventMatchingListInMode + 62 
    25 AppKit        0x00007fff91683779 _DPSNextEvent + 659 
    26 AppKit        0x00007fff9168307d -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 135 
    27 AppKit        0x00007fff9167f9b9 -[NSApplication run] + 470 
    28 AppKit        0x00007fff918fbeac NSApplicationMain + 867 
    29 QuickSlide       0x00000001000019c2 main + 34 
    30 QuickSlide       0x0000000100001994 start + 52 

與我們d搜查耳邊的朋友谷歌顯示了一些博客,指出Row 1 should be in the valid visible section是NSTableView的-reloadData稱爲'太早',即-awakeFromNib期間的錯誤。但對我而言,情況並非如此 - 應用程序完全清醒後肯定會發生刪除操作。我也註釋掉showCancelButton:,以確保它不是我的自定義進度欄,並試圖

[contentArrayController setAutomaticallyRearrangesObjects:NO]; 

誰能告訴我,如果有一個狡猾的手段來避免這種斷言?或者即使這很重要?該應用程序似乎仍然可以繼續,但我看到的其中一個博客說,它爲後來儲存了麻煩,但沒有詳細說明。在錯誤發生後,表似乎會更慢地刷新自己。

回答

0

我想我已經想通了。大約一個星期後,我沒有遇到這個問題...... S * d的法律意味着它現在可能會再次開始,現在我已經回答了我自己的問題。

反正我用的是委託方法:

- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex 

- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView 

表似乎變得越來越填充,因爲我通過它被緩存與NSManagedObjects從我的CD DB一個NSArray通緝。

我主要在刪除對象時發生錯誤(儘管如我所想,用NSFetchRequest更新數組緩存)。

所以在抓住吸管的方式,我決定在每個表列中對NSTextFieldCell進行子類化,並將NSTableColumns綁定到我的主要nib文件中的數組控制器。這出乎意料的好,並且在懸停在表格行上時提供了有關工具提示的好處。無論如何,接觸更多的木材比說得好,現在看起來已經平靜下來了.....如果這種情況隨時改變,我會更新這個答案。

更新:似乎NSTableView和/或多線程不能很好地與UI API匹配。我發現從後臺線程返回像NSDrawers和工作表不會動畫 - 他們忽略他們的標準方法,如-orderOut和-toggle。使用上面的和帶有延遲動畫的NSView(延遲後執行選擇器)似乎已經完全解決了應用程序的問題。

相關問題