Replacing NSMutableData accumulator with NSOutputStream

This commit is contained in:
Mattt Thompson 2012-03-25 11:47:51 -07:00
parent f2ae5c40ba
commit 7bd7ee609b
2 changed files with 32 additions and 46 deletions

View file

@ -80,7 +80,7 @@ extern NSString * const kAFNetworkingIncompleteDownloadDirectoryName;
@warning Attempting to load a `file://` URL in iOS 4 may result in an `NSInvalidArgumentException`, caused by the connection returning `NSURLResponse` rather than `NSHTTPURLResponse`, which is the behavior as of iOS 5. @warning Attempting to load a `file://` URL in iOS 4 may result in an `NSInvalidArgumentException`, caused by the connection returning `NSURLResponse` rather than `NSHTTPURLResponse`, which is the behavior as of iOS 5.
*/ */
@interface AFURLConnectionOperation : NSOperation <NSURLConnectionDataDelegate> { @interface AFURLConnectionOperation : NSOperation <NSURLConnectionDataDelegate, NSStreamDelegate> {
@private @private
unsigned short _state; unsigned short _state;
BOOL _cancelled; BOOL _cancelled;
@ -95,7 +95,6 @@ extern NSString * const kAFNetworkingIncompleteDownloadDirectoryName;
NSData *_responseData; NSData *_responseData;
long long _totalBytesRead; long long _totalBytesRead;
NSMutableData *_dataAccumulator;
NSOutputStream *_outputStream; NSOutputStream *_outputStream;
} }

View file

@ -30,9 +30,6 @@ typedef enum {
typedef unsigned short AFOperationState; typedef unsigned short AFOperationState;
static NSUInteger const kAFHTTPMinimumInitialDataCapacity = 1024;
static NSUInteger const kAFHTTPMaximumInitialDataCapacity = 1024 * 1024 * 8;
static NSString * const kAFNetworkingLockName = @"com.alamofire.networking.operation.lock"; static NSString * const kAFNetworkingLockName = @"com.alamofire.networking.operation.lock";
NSString * const AFNetworkingErrorDomain = @"com.alamofire.networking.error"; NSString * const AFNetworkingErrorDomain = @"com.alamofire.networking.error";
@ -128,7 +125,6 @@ static NSString * AFIncompleteDownloadDirectory() {
@property (readwrite, nonatomic, copy) NSString *responseString; @property (readwrite, nonatomic, copy) NSString *responseString;
@property (readwrite, nonatomic, copy) NSString *responseFilePath; @property (readwrite, nonatomic, copy) NSString *responseFilePath;
@property (readwrite, nonatomic, assign) long long totalBytesRead; @property (readwrite, nonatomic, assign) long long totalBytesRead;
@property (readwrite, nonatomic, retain) NSMutableData *dataAccumulator;
@property (readwrite, nonatomic, copy) AFURLConnectionOperationProgressBlock uploadProgress; @property (readwrite, nonatomic, copy) AFURLConnectionOperationProgressBlock uploadProgress;
@property (readwrite, nonatomic, copy) AFURLConnectionOperationProgressBlock downloadProgress; @property (readwrite, nonatomic, copy) AFURLConnectionOperationProgressBlock downloadProgress;
@property (readwrite, nonatomic, copy) AFURLConnectionOperationAuthenticationAgainstProtectionSpaceBlock authenticationAgainstProtectionSpace; @property (readwrite, nonatomic, copy) AFURLConnectionOperationAuthenticationAgainstProtectionSpaceBlock authenticationAgainstProtectionSpace;
@ -150,7 +146,6 @@ static NSString * AFIncompleteDownloadDirectory() {
@synthesize responseString = _responseString; @synthesize responseString = _responseString;
@synthesize responseFilePath = _responseFilePath; @synthesize responseFilePath = _responseFilePath;
@synthesize totalBytesRead = _totalBytesRead; @synthesize totalBytesRead = _totalBytesRead;
@synthesize dataAccumulator = _dataAccumulator;
@dynamic inputStream; @dynamic inputStream;
@synthesize outputStream = _outputStream; @synthesize outputStream = _outputStream;
@synthesize uploadProgress = _uploadProgress; @synthesize uploadProgress = _uploadProgress;
@ -201,7 +196,10 @@ static NSString * AFIncompleteDownloadDirectory() {
self.runLoopModes = [NSSet setWithObject:NSRunLoopCommonModes]; self.runLoopModes = [NSSet setWithObject:NSRunLoopCommonModes];
self.request = urlRequest; self.request = urlRequest;
self.outputStream = [NSOutputStream outputStreamToMemory];
self.outputStream.delegate = self;
self.state = AFHTTPOperationReadyState; self.state = AFHTTPOperationReadyState;
return self; return self;
@ -218,7 +216,6 @@ static NSString * AFIncompleteDownloadDirectory() {
[_responseData release]; [_responseData release];
[_responseString release]; [_responseString release];
[_dataAccumulator release];
if (_outputStream) { if (_outputStream) {
[_outputStream close]; [_outputStream close];
@ -289,9 +286,7 @@ static NSString * AFIncompleteDownloadDirectory() {
self.request = mutableURLRequest; self.request = mutableURLRequest;
} }
} }
NSLog(@"Request: %@", [self.request allHTTPHeaderFields]);
self.outputStream = [NSOutputStream outputStreamToFileAtPath:temporaryFilePath append:!![self.request valueForHTTPHeaderField:@"Range"]]; self.outputStream = [NSOutputStream outputStreamToFileAtPath:temporaryFilePath append:!![self.request valueForHTTPHeaderField:@"Range"]];
} }
@ -516,10 +511,6 @@ didReceiveResponse:(NSURLResponse *)response
if (self.outputStream) { if (self.outputStream) {
[self.outputStream open]; [self.outputStream open];
} else {
NSUInteger maxCapacity = MAX((NSUInteger)llabs(response.expectedContentLength), kAFHTTPMinimumInitialDataCapacity);
NSUInteger capacity = MIN(maxCapacity, kAFHTTPMaximumInitialDataCapacity);
self.dataAccumulator = [NSMutableData dataWithCapacity:capacity];
} }
NSHTTPURLResponse *HTTPResponse = (NSHTTPURLResponse *)response; NSHTTPURLResponse *HTTPResponse = (NSHTTPURLResponse *)response;
@ -550,13 +541,9 @@ didReceiveResponse:(NSURLResponse *)response
{ {
self.totalBytesRead += [data length]; self.totalBytesRead += [data length];
if (self.outputStream) { if ([self.outputStream hasSpaceAvailable]) {
if ([self.outputStream hasSpaceAvailable]) { const uint8_t *dataBuffer = (uint8_t *) [data bytes];
const uint8_t *dataBuffer = (uint8_t *) [data bytes]; [self.outputStream write:&dataBuffer[0] maxLength:[data length]];
[self.outputStream write:&dataBuffer[0] maxLength:[data length]];
}
} else {
[self.dataAccumulator appendData:data];
} }
if (self.downloadProgress) { if (self.downloadProgress) {
@ -565,27 +552,18 @@ didReceiveResponse:(NSURLResponse *)response
} }
- (void)connectionDidFinishLoading:(NSURLConnection *)__unused connection { - (void)connectionDidFinishLoading:(NSURLConnection *)__unused connection {
if (self.outputStream) { if (self.responseFilePath) {
@synchronized(self) {
if (self.responseFilePath) { NSString *temporaryFilePath = [AFIncompleteDownloadDirectory() stringByAppendingPathComponent:[[NSNumber numberWithInteger:[self.responseFilePath hash]] stringValue]];
NSLog(@"responseFilePath"); NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
@synchronized(self) { [fileManager moveItemAtPath:temporaryFilePath toPath:self.responseFilePath error:&_error];
NSString *temporaryFilePath = [AFIncompleteDownloadDirectory() stringByAppendingPathComponent:[[NSNumber numberWithInteger:[self.responseFilePath hash]] stringValue]];
NSLog(@"temporaryFilePath: %@", temporaryFilePath);
NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
[fileManager moveItemAtPath:temporaryFilePath toPath:self.responseFilePath error:&_error];
NSLog(@"Error: %@", _error);
}
} }
[self.outputStream close];
} else {
self.responseData = [NSData dataWithData:self.dataAccumulator];
[_dataAccumulator release]; _dataAccumulator = nil;
} }
self.responseData = [self.outputStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
[self.outputStream close];
[self finish]; [self finish];
self.connection = nil; self.connection = nil;
@ -596,11 +574,7 @@ didReceiveResponse:(NSURLResponse *)response
{ {
self.error = error; self.error = error;
if (self.outputStream) { [self.outputStream close];
[self.outputStream close];
} else {
[_dataAccumulator release]; _dataAccumulator = nil;
}
[self finish]; [self finish];
@ -621,4 +595,17 @@ didReceiveResponse:(NSURLResponse *)response
} }
} }
#pragma mark - NSStreamDelegate
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
switch (eventCode) {
case NSStreamEventErrorOccurred:
self.error = [stream streamError];
[self cancel];
break;
default:
break;
}
}
@end @end