- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 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/
我正在尝试执行一个操作以滚动到 NSTableView 的顶部和 NSTableView 的底部。我正在使用 scrollRowToVisible,但我希望该 Action 具有动画效果。有办法做到这
在 while 循环中,一旦测试开始,就会重复调用更新 NSTableView 的方法。 ...... -(void)runtest:(int)iType wellIndex:(int)nWellIn
我是一名优秀的程序员,十分优秀!