3

AVCaptureSessionを使用して、AVCaptureVideoDataOutputクラスのsetSampleBufferDelegateメソッドを使用してカメラからフレームをキャプチャしています。デリゲートメソッドは次のようになります。UIImageに変換して、UIImageViewに配置していることがわかります。各UIImageをディスクに保存し、URLを新しいmanagedObjectに保存したいのですが、各呼び出しがシリアルディスパッチキューを使用して新しいスレッドを生成するため、managedObjectContextを適切に取得する方法がわかりません。ディスクに保存され、managedObjectに対応するイメージのコレクションを構築できる方法でCoreDataとディスパッチキューを使用するソリューションを誰かが提案できますか?

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
/*Lock the image buffer*/
CVPixelBufferLockBaseAddress(imageBuffer,0); 
/*Get information about the image*/
uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer); 
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
size_t width = CVPixelBufferGetWidth(imageBuffer); 
size_t height = CVPixelBufferGetHeight(imageBuffer);  

/*Create a CGImageRef from the CVImageBufferRef*/
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGImageRef newImage = CGBitmapContextCreateImage(newContext); 

    /*We release some components*/
    CGContextRelease(newContext); 
    CGColorSpaceRelease(colorSpace);

/*We display the result on the image view (We need to change the orientation of the image so that the video is displayed correctly).
     Same thing as for the CALayer we are not in the main thread so ...*/
    UIImage *image= [UIImage imageWithCGImage:newImage scale:1.0 orientation:UIImageOrientationRight];

/*We relase the CGImageRef*/
CGImageRelease(newImage);

[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];

/*We unlock the  image buffer*/
CVPixelBufferUnlockBaseAddress(imageBuffer,0);

[pool drain];
}
4

1 に答える 1

2

推奨される解決策は、スレッドごとに新しい NSManagedObjectContext を作成し、それぞれが単一の NSPersistentStoreCoordinator を指すようにすることです。をリッスンしてNSManagedObjectContextDidSaveNotification、変更をメイン スレッドのコンテキストにマージすることもできます (適切な名前の を使用mergeChangesFromContextDidSaveNotification:)。

個人的には、次のようなアクセサーを中央の場所で使用して、スレッドごとのコンテキストを処理するのが好きです。

- (NSManagedObjectContext *) managedObjectContext {
    NSManagedObjectContext *context = [[[NSThread currentThread] threadDictionary] objectForKey:@"NSManagedObjectContext"];
    if (context == nil) {
        context = [[[NSManagedObjectContext alloc] init] autorelease];
        [context setPersistentStoreCoordinator:self.persistentStoreCoordinator];
        [[[NSThread currentThread] threadDictionary] setObject:context forKey:@"NSManagedObjectContext"];
    }
    return context;
}

コンテキストを渡すよりも簡単にスレッド間で NSManagedObjects を渡すことができないことに注意してください。代わりに、(オブジェクトのプロパティから) NSManagedObjectID を渡してからobjectID、宛先スレッドでそのスレッドのコンテキストのobjectWithID:メソッドを使用して同等のオブジェクトを取得する必要があります。

于 2011-04-16T22:19:45.040 に答える