AVFoundationとCocoaBindings

durationをBindしたい!でもCMTimeだから無理?
そういう時はNSValueTransformer。


CMTime -> NSNumber of double
サンプルではdurationをNSSliderのmaxValueにbindする時に使用。

@interface HMCMTimeTransformer: NSValueTransformer
@end

@implementation HMCMTimeTransformer

+ (Class)transformedValueClass
{
    return [NSNumber class];
}
+ (BOOL)allowsReverseTransformation
{
    return NO;
}

- (id)transformedValue:(id)value
{
    if(!value) return nil;
    
    CMTime time = [value CMTimeValue];
    
    Float64 seconds = CMTimeGetSeconds(time);
    return [NSNumber numberWithDouble:seconds];
}
@end


CMTime -> NSDate
サンプルではdurationをNSDateFormatterを適用したNSTextFieldのvalueにbindする時に使用。

@interface HMCMTimeDateTransformer : NSValueTransformer
@end

@implementation HMCMTimeDateTransformer
+ (Class)transformedValueClass
{
    return [NSDate class];
}
+ (BOOL)allowsReverseTransformation
{
    return NO;
}
- (id)transformedValue:(id)value
{
    if(!value) return nil;
    
    CMTime time = [value CMTimeValue];
    
    Float64 seconds = CMTimeGetSeconds(time);
    // GMT+-X:XX補正。現地時間に合わせる
    // 日本なら 00:00:00が 09:00:00となるのでそれを補正
    seconds -= [[NSTimeZone systemTimeZone] secondsFromGMT]; 
    return [NSDate dateWithTimeIntervalSince1970:seconds];
}
@end


クラスを作っただけではダメでこれらを起動時に登録しておく。

@implementation HMAppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
	NSValueTransformer *cmt = [[[HMCMTimeTransformer alloc] init] autorelease];
	[NSValueTransformer setValueTransformer:cmt forName:@"HMCMTimeTransformer"];
	
	cmt = [[[HMSecondsDateTransformer alloc] init] autorelease];
	[NSValueTransformer setValueTransformer:cmt forName:@"HMSecondsDateTransformer"];
	
	cmt = [[[HMCMTimeDateTransformer alloc] init] autorelease];
	[NSValueTransformer setValueTransformer:cmt forName:@"HMCMTimeDateTransformer"];
}
@end

で、登録名をbindのValue Transformarに設定すればOK。