我为iPad构建了一个多线程应用程序。我有这个类从影片剪辑中提取帧,我有一个UIScrollView来显示我提取的东西。帧提取器在不同的线程中运行,我想在我提取一定数量的帧之后才开始构建滚动视图。因此,我创建了这个名为buffering的BOOL属性,它通过线程进行更新。我的视图控制器观察此属性,并且只有在此属性等于NO我才开始构建ScrollView。
问题是我在调用构建方法后没有看到GUI的任何变化。我只能在触摸屏幕后看到滚动视图
继续做什么:
创建线程:
[NSThread detachNewThreadSelector:@selector(startReading) toTarget:self withObject:nil];
线程中运行的代码:
-(void) startReadingWithTimeRange:(STimeRange *) timeRange;
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Top-level pool
//setting the time range for reading the file
[assetReader setTimeRange:timeRange.timeRange];
//start reading
[assetReader startReading];
//declearing about the buffer
CMSampleBufferRef buffer;
int z = 0;
while ( [assetReader status]==AVAssetReaderStatusReading)
{
z++;
//reading buffer
buffer = [assetReaderTrackOutput copyNextSampleBuffer];
if (buffer == NULL) break;
//converting the buffer to UIImage
UIImage *frameImage = imageFromSampleBuffer(buffer);
CMTime time = CMSampleBufferGetOutputPresentationTimeStamp(buffer);
NSLog(@"###duration %lld",time.value/time.timescale);
SFrame *frame = [[SFrame alloc] initWithImage:frameImage andTime:time];
//add it to the frame array
[framesArray addObject:frame];
[frame release];
//check if buffer is not null and needed release
//release the buffer
CFRelease(buffer);
if ([framesArray count] > 100 && self.buffering) {
[self willChangeValueForKey:@"buffering"];
self.buffering = NO;
[self didChangeValueForKey:@"buffering"];
}
}
[pool release];
}
我真的很无能,我真的很感激任何帮助
答案 0 :(得分:1)
首先不要调用willChangeValueForKey和didChangeValueForKey,因为你只是使KVO通知触发两次,它已被self.buffering = NO触发;
其次,主线程外部的属性/ ivar更改应该在@synchronized块内完成,例如:
@synchronized (self) {
self.buffering = NO;
}
您可以使用performSelectorOnMainThread来调用缓冲方法,例如:
[self performSelectorOnMainThread:@selector(buffering:) withObject:[NSNumber numberWithBool:YES] waitUntilDone:NO];
如果这样做无法解决您的问题,那么您的代码可能会遇到其他问题,例如需要在某些视图或类型上调用setNeedsDisplay。
你没有说KVO通知会发生什么,你不明白这就是你明确试图发送它的原因吗?