ここでの高レベルは、iOSアプリでやろうとしていることです:
- ユーザーがフォト ライブラリからアセットを選択できるようにする
- アプリの外部エンティティが同じアセットをリクエストするために使用できる URL を共有する
- 私のアプリは Web サーバー (CocoaHTTPServer) を実行しており、そのデータを要求エンティティに提供できます。
- ALAssetRepresentation getBytes:fromOffset:length:error: を使用して意図的にこれを実装し、次の頭痛の種を回避できると考えました。
- イメージを提供する前にイメージのローカル コピーを書き込む (その後、ローカル コピーを管理する必要がある)
- すべての画像データをメモリに入れる
- パフォーマンスが低下する可能性があり、画像全体を取得するのを待ってからサービスを提供する
高レベルで動作しますが、1 つの問題があります。画像の向きが正しくない場合があります。
これはよく知られている問題ですが、解決策としては、ALAssetRepresentation から CGImage または UIImage を作成する必要があるようです。これを行うとすぐに、その便利な ALAssetRepresentation getBytes:fromOffset:length:error: メソッドを使用できなくなります。
この方法を引き続き使用する方法があれば、それはクールです。ただし、向きを修正します。そうでない場合は、次善のアプローチに関する推奨事項をいただければ幸いです。ありがとう!
関連するメソッドのいくつかを次に示します。
- (id)initWithAssetURL:(NSURL *)assetURL forConnection:(MyHTTPConnection *)parent{
if((self = [super init]))
{
HTTPLogTrace();
// Need this now so we can use it throughout the class
self.connection = parent;
self.assetURL = assetURL;
offset = 0;
// Grab a pointer to the ALAssetsLibrary which we can persistently use
self.lib = [[ALAssetsLibrary alloc] init];
// Really need to know the size of the asset, but we will also set a property for the ALAssetRepresentation to use later
// Otherwise we would have to asynchronously look up the asset again by assetForURL
[self.lib assetForURL:assetURL
resultBlock:^(ALAsset *asset) {
self.assetRepresentation = [asset defaultRepresentation];
self.assetSize = [self.assetRepresentation size];
// Even though we don't really have any data, this will enable the response headers to be sent
// It will call our delayResponseHeaders method, which will now return NO, since we've set self.repr
[self.connection responseHasAvailableData:self];
}
failureBlock:^(NSError *error) {
// recover from error, then
NSLog(@"error in the failureBlock: %@",[error localizedDescription]);
}];
}
return self;
}
- (NSData *)readDataOfLength:(NSUInteger)lengthParameter{
HTTPLogTrace2(@"%@[%p]: readDataOfLength:%lu", THIS_FILE, self, (unsigned long)lengthParameter);
NSUInteger remaining = self.assetSize - offset;
NSUInteger length = lengthParameter < remaining ? lengthParameter : remaining;
Byte *buffer = (Byte *)malloc(length);
NSError *error;
NSUInteger buffered = [self.assetRepresentation getBytes:buffer fromOffset:offset length:length error:&error];
NSLog(@"Error: %@",[error localizedDescription]);
NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
// now that we've read data of length, update the offset for the next invocation
offset += length;
return data;
}