gpt4 book ai didi

objective-c - 10.10 中 NSTableView 的 selectRowIndexes 或 scrollRowToVisible 崩溃

转载 作者:行者123 更新时间:2023-12-03 16:35:28 26 4
gpt4 key购买 nike

在 while 循环中,一旦测试开始,就会重复调用更新 NSTableView 的方法。

......
-(void)runtest:(int)iType wellIndex:(int)nWellIndex
{
bTestRunning[nWellIndex] = TRUE;

NSNumber *wellIndex = [NSNumber numberWithInt:nWellIndex];

[testThread[nWellIndex] release];
testThread[nWellIndex] = [[NSThread alloc] initWithTarget:self
selector:@selector(testThreadMainRoutine:)
object:wellIndex];

[testThread[nWellIndex] start];
}
......

- (void)testThreadMainRoutine:(id)argument
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

int nWellIndex = [(NSNumber *)argument intValue];

int nStartIndex, nEndIndex;
if (nWellIndex == 0)
{
nStartIndex = 0;
nEndIndex = ONEWELL_UUT;
}
else if(nWellIndex==1)
{
nStartIndex = ONEWELL_UUT;
nEndIndex = TWOWELL_UUT;
}
else
{
nStartIndex=TWOWELL_UUT;
nEndIndex=MAX_UUT;
}

// Log library version etc.
if (nWellIndex == 0)
NSLog(@"*** Left Well Test Start ***");
else if(nWellIndex==1)
NSLog(@"*** Middle Well Test Start ***");
else
NSLog(@"*** Right Well Test Start ***");

// Run
int i, j, itemCount, bContinue;
itemCount = 0;
int lineCount = [cmdArray count];

for (j=nStartIndex; j<nEndIndex; j++)
{
[strPlog[j] release];
strPlog[j] = [[NSMutableString alloc] init];
}

for (i=0; i<lineCount; i++)
{
[NSThread sleepForTimeInterval:0.001];

[self probeForAbortCondition:nWellIndex];

if ([testThread[nWellIndex] isCancelled])
{
bTestStatus[nWellIndex] = ABORT;
goto TESTTHREAD_EXIT;
}

// Is there any UUT available?
bContinue = 0;
for (j=nStartIndex; j<nEndIndex; j++)
{
if (uutActive[j])
{
bContinue = 1;
break;
}
}
if (bContinue == 0)
{
goto TESTTHREAD_EXIT;
}

while(bPaused[nWellIndex])
{
[NSThread sleepForTimeInterval:0.1];
[self setTextResult:@"Pause" textColor:[NSColor orangeColor] wellIndex:nWellIndex];
}
[self setTextResult:@"Running" textColor:[NSColor orangeColor] wellIndex:nWellIndex];

// Per Command Line
CommandLine *cmdLine = [cmdArray objectAtIndex:i];

// Run UUT independently from this command line
if ([cmdLine independentRun] == INDEPENDENTRUN_START)
{
g_nIndependentStart = i;
g_nIndependentStop = [self independentRunStopIndex];

// Dispatch independent thread for each active UUT
for (j=nStartIndex; j<nEndIndex; j++)
{
if (uutActive[j])
{
g_itemCount[j] = itemCount;

NSNumber *uutIndex = [NSNumber numberWithInt:j];
[g_uutThread[j] release];
g_uutThread[j] = [[NSThread alloc] initWithTarget:self
selector:@selector(testThreadUUTRoutine:)
object:uutIndex];

[g_uutThread[j] start];
}
}

// Waiting till test abort or UUT thread finish
while ( 1 )
{

[self probeForAbortCondition:nWellIndex];

// User press button to abort the test
if ([testThread[nWellIndex] isCancelled])
{
for (j=nStartIndex; j<nEndIndex; j++)
{
if ([g_uutThread[j] isExecuting])
{
[g_uutThread[j] cancel];
}
}
bTestStatus[nWellIndex] = ABORT;
}

// Wait until all thread exited, then continue remaining test
bContinue = 0;
for (j=nStartIndex; j<nEndIndex; j++)
{
if (uutSelected[j])
{
if ([g_uutThread[j] isExecuting])
{
bContinue = 1;
}
else
{
[g_uutThread[j] release];
g_uutThread[j] = nil;
}
}
}
// All UUT thread exited
if ( ! bContinue)
{
break;
}

// Select current test row
if (itemCount != [self maxCurrentItemCount:nWellIndex])
{
itemCount = [self maxCurrentItemCount:nWellIndex];
NSArray *objArray = [NSArray arrayWithObjects:[NSNumber numberWithInt:nWellIndex], [NSNumber numberWithInt:itemCount], nil];
[self performSelectorOnMainThread:@selector(selectCurrentRow:) withObject:objArray
waitUntilDone:YES];

}
if (nWellIndex == 0)
{
[testTable01 display];
}
else if(nWellIndex==1)
{
[testTable02 display];
}
else
{
[testTable03 display];
}
}

// Test abort or UUT fail and aborted
if (bTestStatus[nWellIndex] == ABORT)
{
goto TESTTHREAD_EXIT;
}

if (g_nIndependentStop >= lineCount)
{
// All test done
goto TESTTHREAD_EXIT;
}
else
{
// Continue remaining test
i = g_nIndependentStop;
cmdLine = [cmdArray objectAtIndex:i];
itemCount = [self maxCurrentItemCount:nWellIndex];
}
}

NSArray *objArray = [NSArray arrayWithObjects:[NSNumber numberWithInt:nWellIndex], [NSNumber numberWithInt:itemCount], nil];
// Select current test row
dispatch_async(dispatch_get_main_queue(), ^{
[self performSelectorOnMainThread:@selector(selectCurrentRow:) withObject:objArray waitUntilDone:YES];
});


NSString *cmdName = [cmdLine valueForKey:@"cmdName"];
NSString *cmdParam = [cmdLine valueForKey:@"cmdParam"];
NSString *itemName = [cmdLine valueForKey:@"itemName"];

// Clear returnArray
for (j=nStartIndex; j<nEndIndex; j++)
{
if ([cmdLine flag] & FLAG_SKIP) {

[[cmdReturn objectAtIndex:j] setUnit:@"NA"];
[[cmdReturn objectAtIndex:j] setLowerLimit:@"NA"];
[[cmdReturn objectAtIndex:j] setUpperLimit:@"NA"];

[[cmdReturn objectAtIndex:j] setCmdResult:@"Skipped"];
[[cmdReturn objectAtIndex:j] setTestResult:@"Skipped"];
[[cmdReturn objectAtIndex:j] setCmdStatus:SKIPPED];
continue;
}


[[cmdReturn objectAtIndex:j] setCmdResult:nil];
[[cmdReturn objectAtIndex:j] setTestResult:nil];
[[cmdReturn objectAtIndex:j] setCmdStatus:FAIL];

[[cmdReturn objectAtIndex:j] setUnit:nil];
[[cmdReturn objectAtIndex:j] setLowerLimit:nil];
[[cmdReturn objectAtIndex:j] setUpperLimit:nil];

}




if (nWellIndex == 0)
NSLog(@"Left Well Executing %d: %@, (%@), %@", i, cmdName, cmdParam, itemName);
else if(nWellIndex==1)
NSLog(@"Middle Well Executing %d: %@, (%@), %@", i, cmdName, cmdParam, itemName);
else
NSLog(@"Right Well Executing %d: %@, (%@), %@", i, cmdName, cmdParam, itemName);

if ([cmdName characterAtIndex:0] == '_') // Per UUT command
{
// Repeat for all UUT
for (j=nStartIndex; j<nEndIndex; j++)
{
// whether UUT is selected
if (uutActive[j])
{
if ([cmdLine flag] & FLAG_SKIP) {

[[cmdReturn objectAtIndex:j] setUnit:@"NA"];
[[cmdReturn objectAtIndex:j] setLowerLimit:@"NA"];
[[cmdReturn objectAtIndex:j] setUpperLimit:@"NA"];

[[cmdReturn objectAtIndex:j] setCmdResult:@"Skipped"];
[[cmdReturn objectAtIndex:j] setTestResult:@"Skipped"];
[[cmdReturn objectAtIndex:j] setCmdStatus:SKIPPED];

[self saveCmdReading:[[cmdReturn objectAtIndex:j] cmdResult]
commandLine:i uutIndex:j lineStatus:SKIPPED];

// Process test result
if (itemName != nil)
{
[self saveUutResult:[[cmdReturn objectAtIndex:j] testResult] testItem:itemName uutIndex:j uutStatus:SKIPPED];
}

continue;
}


// Before Item Test, save timestamp


if (itemName != nil) {
NSString* timeStamp = [[NSDate date] descriptionWithCalendarFormat:@"\n%y-%m-%d %H:%M:%S: "
timeZone:nil locale:nil];
[strPlog[j] appendFormat:@"%@ START %@", timeStamp, itemName];
}

// insert to UART log file
char buff[1024];
NSString *strInfo = [NSString stringWithFormat:@"%d: %@, (%@), %@", i, cmdName, cmdParam, itemName];
sprintf(buff, "\n[Host Executing Cmd]%s\n", [strInfo UTF8String]);
[self uartDataLogging:j buffer:buff pureUARTData:NO];




[self parseCommand:cmdName parameter:cmdParam lineIndex:i uutIndex:j wellIndex:nWellIndex];

// Process test result
[self saveCmdReading:[[cmdReturn objectAtIndex:j] cmdResult] commandLine:i uutIndex:j lineStatus:[[cmdReturn objectAtIndex:j] cmdStatus]];

// Test Item
if (itemName != nil)
{
[self saveUutResult:[[cmdReturn objectAtIndex:j] testResult] testItem:itemName uutIndex:j uutStatus:[[cmdReturn objectAtIndex:j] cmdStatus]];
}


// After Item Test, save timestamp
NSString* timeStamp = [[NSDate date] descriptionWithCalendarFormat:@"\n%y-%m-%d %H:%M:%S: " timeZone:nil locale:nil];
[strPlog[j] appendFormat:@"%@ FINISH %@", timeStamp, itemName];
}

// Fail Stop/Abort
if ([[cmdReturn objectAtIndex:j] cmdStatus] == FAIL)
{
if ([cmdLine flag] & FLAG_FAILSTOP)
{
// Stop this UUT test
uutActive[j] = 0;

// Close UART
[self closeSerialPort:j];

// shut down UUT USB & Battery Power
uutPower(j, 0);
}
else if ([cmdLine flag] & FLAG_FAILABORT)
{
bTestStatus[nWellIndex] = ABORT;
goto TESTTHREAD_EXIT;
}

}
}
}
}
else // For all active UUT
{
bool skip = false;

// Before Item Test, save timestamp
for (j=nStartIndex; j<nEndIndex; j++)
{
if ([cmdLine flag] & FLAG_SKIP) {

skip = true;

[[cmdReturn objectAtIndex:j] setUnit:@"NA"];
[[cmdReturn objectAtIndex:j] setLowerLimit:@"NA"];
[[cmdReturn objectAtIndex:j] setUpperLimit:@"NA"];

[[cmdReturn objectAtIndex:j] setCmdResult:@"Skipped"];
[[cmdReturn objectAtIndex:j] setTestResult:@"Skipped"];
[[cmdReturn objectAtIndex:j] setCmdStatus:SKIPPED];

[self saveCmdReading:[[cmdReturn objectAtIndex:j] cmdResult] commandLine:i uutIndex:j lineStatus:SKIPPED];

// Process test result
if (itemName != nil)
{
[self saveUutResult:[[cmdReturn objectAtIndex:j] testResult]
testItem:itemName uutIndex:j uutStatus:SKIPPED];
}


continue;
}

// whether UUT is selected
if (uutActive[j])
{
if (itemName != nil)
{
NSString* timeStamp = [[NSDate date] descriptionWithCalendarFormat:@"\n%y-%m-%d %H:%M:%S: " timeZone:nil locale:nil];
[strPlog[j] appendFormat:@"%@ START %@", timeStamp, itemName];
}

// insert to UART log file
char buff[1024];
NSString *strInfo = [NSString stringWithFormat:@"%d: %@, (%@), %@", i, cmdName, cmdParam, itemName];
sprintf(buff, "\n[Host Executing Cmd]%s\n", [strInfo UTF8String]);
[self uartDataLogging:j buffer:buff pureUARTData:NO];
}
}

if (skip) {
continue;
}


[self parseCommand:cmdName parameter:cmdParam lineIndex:i uutIndex:-1 wellIndex:nWellIndex];

// Process command return result
for (j=nStartIndex; j<nEndIndex; j++)
{
// whether UUT is selected
if (uutActive[j])
{
[self saveCmdReading:[[cmdReturn objectAtIndex:j] cmdResult] commandLine:i uutIndex:j lineStatus:[[cmdReturn objectAtIndex:j] cmdStatus]];

// Process test result
if (itemName != nil)
{
[self saveUutResult:[[cmdReturn objectAtIndex:j] testResult] testItem:itemName uutIndex:j uutStatus:[[cmdReturn objectAtIndex:j] cmdStatus]];

// After Item Test, save timestamp
NSString* timeStamp = [[NSDate date] descriptionWithCalendarFormat:@"\n%y-%m-%d %H:%M:%S: " timeZone:nil locale:nil];
[strPlog[j] appendFormat:@"%@ FINISH %@", timeStamp, itemName];
}

// Fail Stop/Abort
if ([[cmdReturn objectAtIndex:j] cmdStatus] == FAIL)
{
if ([cmdLine flag] & FLAG_FAILSTOP)
{
// Stop this UUT test
uutActive[j] = 0;

// Close UART
[self closeSerialPort:j];

// shut down UUT USB & Battery Power
uutPower(j, 0);

}
else if ([cmdLine flag] & FLAG_FAILABORT)
{
bTestStatus[nWellIndex] = ABORT;
goto TESTTHREAD_EXIT;
}
else if ([cmdLine flag] & FLAG_SKIP)
{
[[cmdReturn objectAtIndex:j] setCmdStatus:SKIPPED];
[self saveUutResult:[[cmdReturn objectAtIndex:j] testResult] testItem:itemName uutIndex:j uutStatus:[[cmdReturn objectAtIndex:j] cmdStatus]];
}

}
}
}
}

if (itemName != nil)
itemCount++;
}

TESTTHREAD_EXIT:

// Turn Off USB & Battery Power
for (j=nStartIndex; j<nEndIndex; j++)
{
strTestTimeRecord[j] = [[NSString stringWithString:strPlog[j]] retain];
[strPlog[j] release];
strPlog[j] = nil;

// whether UUT is selected
if (uutActive[j])
{
// Close UART
[self closeSerialPort:j];

// shut down UUT USB & Battery Power
uutPower(j, 0);

}

//Clear Buffer for Smokey
[self clearRdBuffStr:j];
}


// Refresh UI to indicate test result
[self performSelectorOnMainThread:@selector(afterRun:) withObject:argument waitUntilDone:NO];

[pool release];

}

......
-(void)selectCurrentRow:(NSArray*)objArray
{
int nWellIndex = [[objArray objectAtIndex:0] intValue];
int itemCount = [[objArray objectAtIndex:1] intValue];

if (nWellIndex == 0)
{
[testTable01 selectRowIndexes:[NSIndexSet indexSetWithIndex:itemCount] byExtendingSelection:NO];
[testTable01 scrollRowToVisible:itemCount];
}
else if(nWellIndex == 1)
{
[testTable02 selectRowIndexes:[NSIndexSet indexSetWithIndex:itemCount] byExtendingSelection:NO];
[testTable02 scrollRowToVisible:itemCount];
}
else
{
[testTable03 selectRowIndexes:[NSIndexSet indexSetWithIndex:itemCount] byExtendingSelection:NO];
[testTable03 scrollRowToVisible:itemCount];
}
}

我的应用程序经常崩溃,崩溃日志如下。我不确定为什么,也无法弄清楚崩溃消息的含义。谁能给我指点一下吗?谢谢。

......
Time Awake Since Boot: 130 seconds

Crashed Thread: 4

Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00006d1920bdbec0

VM Regions Near 0x6d1920bdbec0:
MALLOC_NANO 0000608000400000-0000608001c00000 [ 24.0M] rw-/rwx SM=PRV
-->
MALLOC_TINY 00007fb048c00000-00007fb049000000 [ 4096K] rw-/rwx SM=PRV

Application Specific Information:
objc_msgSend() selector name: indexGreaterThanIndex:
......
Thread 4 Crashed:
0 libobjc.A.dylib 0x00007fff8640e0dd objc_msgSend + 29
1 com.apple.AppKit 0x00007fff88f44c6a -[NSTableView highlightSelectionInClipRect:] + 728
2 com.apple.AppKit 0x00007fff88f43e43 -[NSTableView drawRect:] + 1439
3 com.apple.AppKit 0x00007fff88db5799 -[NSView _drawRect:clip:] + 4238
4 com.apple.AppKit 0x00007fff88db3e0a -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 1875
5 com.apple.AppKit 0x00007fff88db420e -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 2903
6 com.apple.AppKit 0x00007fff88db420e -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 2903
7 com.apple.AppKit 0x00007fff88db420e -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 2903
8 com.apple.AppKit 0x00007fff88db420e -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 2903
9 com.apple.AppKit 0x00007fff88db420e -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 2903
10 com.apple.AppKit 0x00007fff88db420e -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 2903
11 com.apple.AppKit 0x00007fff88db1ca6 -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 913
12 com.apple.AppKit 0x00007fff88db1403 -[NSThemeFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 333
13 com.apple.AppKit 0x00007fff88dad79b -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 2761
14 com.apple.AppKit 0x00007fff88d652be -[NSView displayIfNeeded] + 1876
15 com.TopTestDFU 0x000000010b966d31 -[AppController(TestEngine) testThreadMainRoutine:] + 1825
16 com.apple.Foundation 0x00007fff8f26fdc2 __NSThread__main__ + 1345
17 libsystem_pthread.dylib 0x00007fff89880268 _pthread_body + 131
18 libsystem_pthread.dylib 0x00007fff898801e5 _pthread_start + 176
19 libsystem_pthread.dylib 0x00007fff8987e41d thread_start + 13

最佳答案

要获得更具体的答案,您需要提供包含您提到的 while 循环的代码。

EXC_BAD_ACCESS 是一个内存管理错误。具体来说,消息被发送到地址不再有效(已被释放)的对象。我怀疑这是一个计时问题,因为您在修改其数据源集合时反复请求刷新主线程上的表选择。有时它正在访问有效的东西;有时它正在访问一些有效的东西。其他时候则不然。

有两件事让我担心:1)在 while 循环中排队一百万个与 UI 相关的更新(而不是用计时器等合理地限制 UI 更新),2)奇怪地使用集合的计数作为行索引(如果 count 为 0,则选择第 0 行,意味着没有第 0 行?如果 count 为 3,则选择第 0-3 行,意味着只有 0-2 行是有效行?)。

尝试在更新开始时启动半秒或一秒重复计时器,请求 TableView 自行更新,然后在每次触发时调整其选择(当然是在主队列上)。在同一操作中同时执行这两项操作可确保表反射(reflect)数据,从而使选择有意义。然后在所有更新完成后停止/关闭/取消计时器(如果发生过这种情况;如果是“始终更新”,则一定要选择更长的刷新间隔,因为多秒长的更新不需要如此频繁的刷新)。

至于索引范围,很容易调整 - 全选应该是一个简单的范围NSMakeRange(0, collection.count)(从第一项开始,长度为计数)。不选择任何内容都应该是空集[NSIndexSet indexSet]

更新

此外,在您的 dispatch_async 调用中,您已经指定了主队列,因此调用 -performSelectorOnMainThread:... 是不必要且浪费的。实际上,您是在说“安排告诉主队列安排告诉主队列执行以下操作...”

关于objective-c - 10.10 中 NSTableView 的 selectRowIndexes 或 scrollRowToVisible 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29793861/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com