名前に基づいて NSDictionary から格納された NSData アイテムをフェッチできるカスタム NSURLProtocol (「memory:」と呼ばれる) を作成しました。たとえば、次のコードは NSURLProtocol クラスを登録し、いくつかのデータを追加します。
[VPMemoryURLProtocol register];
[VPMemoryURLProtocol addData:data withName:@"video"];
これにより、"memory://video" のような URL を介して NSData を参照できます。
以下は、私のカスタム NSURLProtocol 実装です。
NSMutableDictionary* gMemoryMap = nil;
@implementation VPMemoryURLProtocol
{
}
+ (void)register
{
static BOOL inited = NO;
if (!inited)
{
[NSURLProtocol registerClass:[VPMemoryURLProtocol class]];
inited = YES;
}
}
+ (void)addData:(NSData *)data withName:(NSString *)name
{
if (!gMemoryMap)
{
gMemoryMap = [NSMutableDictionary new];
}
gMemoryMap[name] = data;
}
+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
NSLog(@"URL: %@, Scheme: %@",
[[request URL] absoluteString],
[[request URL] scheme]);
NSString* theScheme = [[request URL] scheme];
return [theScheme caseInsensitiveCompare:@"memory"] == NSOrderedSame;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
{
return request;
}
- (void)startLoading
{
NSString* name = [[self.request URL] path];
NSData* data = gMemoryMap[name];
NSURLResponse* response = [[NSURLResponse alloc] initWithURL:[self.request URL]
MIMEType:@"video/mp4"
expectedContentLength:-1
textEncodingName:nil];
id<NSURLProtocolClient> client = [self client];
[client URLProtocol:self didReceiveResponse:response
cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[client URLProtocol:self didLoadData:data];
[client URLProtocolDidFinishLoading:self];
}
- (void)stopLoading
{
}
このコードが機能するかどうかはわかりませんが、問題はありません。カスタム プロトコルを登録しているにもかかわらず、次のコードで URL を使用しようとすると、 canInitWithRequest: が呼び出されることはありません。
NSURL* url = [NSURL URLWithString:@"memory://video"];
AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil];
AVAssetImageGenerator* imageGen = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
CMTime time = CMTimeMakeWithSeconds(0, 600);
NSError* error;
CMTime actualTime;
CGImageRef image = [imageGen copyCGImageAtTime:time
actualTime:&actualTime
error:&error];
UIImage* uiImage = [UIImage imageWithCGImage:image];
CGImageRelease(image);
「memory://video」を使用すると画像は常に nil ですが、「file:///...」を使用すると正常に動作します。私は何が欠けていますか?canInitWithRequest が呼び出されないのはなぜですか? AVFoundation は特定の URL プロトコルのみをサポートし、カスタム プロトコルはサポートしませんか?
ありがとう