Adding documentation for NSCoding / NSCopying behavior

Minor fixes to -copyWithZone:

Minor refactoring of -encodeWithCoder:
This commit is contained in:
Mattt Thompson 2012-08-15 09:59:00 -07:00
parent a862d3b596
commit 7132b96124
2 changed files with 24 additions and 16 deletions

View File

@ -73,6 +73,20 @@ extern NSString * const AFNetworkingOperationDidFinishNotification;
@warning Subclasses are strongly discouraged from overriding `setCompletionBlock:`, as `AFURLConnectionOperation`'s implementation includes a workaround to mitigate retain cycles, and what Apple rather ominously refers to as "The Deallocation Problem" (See http://developer.apple.com/library/ios/technotes/tn2109/_index.html#//apple_ref/doc/uid/DTS40010274-CH1-SUBSECTION11)
## NSCoding & NSCopying Conformance
`AFURLConnectionOperation` conforms to the `NSCoding` and `NSCopying` protocols, allowing operations to be archived to disk, and copied in memory, respectively. However, because of the intrinsic limitations of capturing the exact state of an operation at a particular moment, there are some important caveats to keep in mind:
### NSCoding Caveats
- Encoded operations do not include any block properties. Be sure to set `completionBlock` and any other callback blocks as necessary when using `-initWithCoder:` or `NSKeyedUnarchiver`, for example.
- Operations are paused on `encodeWithCoder:`. If the operation was encoded while paused or still executing, its archived state will return `YES` for `isReady`. Otherwise, the state of an operation when encoding will remain unchanged.
### NSCopying Caveats
- `-copy` and `-copyWithZone:` return a new operation with the `NSURLRequest` of the original. So rather than an exact copy of the operation at that particular instant, the copying mechanism returns a completely new instance, which can be useful for retrying operations.
- Operation copies do not include `completionBlock`, but do include any other callback blocks of the original. `completionBlock` often strongly captures a reference to `self`, which, perhaps surprisingly, would otherwise point to the _original_ operation when copied.
@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 <NSCoding, NSCopying>

View File

@ -608,13 +608,10 @@ didReceiveResponse:(NSURLResponse *)response
- (id)initWithCoder:(NSCoder *)aDecoder {
NSURLRequest *request = [aDecoder decodeObjectForKey:@"request"];
self = [self initWithRequest:request];
if (!self) {
if (!request || ![self initWithRequest:request]) {
return nil;
}
self.runLoopModes = [aDecoder decodeObjectForKey:@"runLoopModes"];
self.state = [aDecoder decodeIntegerForKey:@"state"];
self.cancelled = [aDecoder decodeBoolForKey:@"isCancelled"];
self.response = [aDecoder decodeObjectForKey:@"response"];
@ -628,7 +625,6 @@ didReceiveResponse:(NSURLResponse *)response
- (void)encodeWithCoder:(NSCoder *)aCoder {
[self pause];
[aCoder encodeObject:self.runLoopModes forKey:@"runLoopModes"];
[aCoder encodeObject:self.request forKey:@"request"];
switch (self.state) {
@ -652,16 +648,14 @@ didReceiveResponse:(NSURLResponse *)response
- (id)copyWithZone:(NSZone *)zone {
AFURLConnectionOperation *operation = [[[self class] allocWithZone:zone] initWithRequest:self.request];
operation.runLoopModes = [self.runLoopModes copyWithZone:zone];
operation.uploadProgress = [self.uploadProgress copy];
operation.downloadProgress = [self.downloadProgress copy];
operation.authenticationAgainstProtectionSpace = [self.authenticationAgainstProtectionSpace copy];
operation.authenticationChallenge = [self.authenticationChallenge copy];
operation.cacheResponse = [self.cacheResponse copy];
operation.redirectResponse = [self.redirectResponse copy];
operation.uploadProgress = self.uploadProgress;
operation.downloadProgress = self.downloadProgress;
operation.authenticationAgainstProtectionSpace = self.authenticationAgainstProtectionSpace;
operation.authenticationChallenge = self.authenticationChallenge;
operation.cacheResponse = self.cacheResponse;
operation.redirectResponse = self.redirectResponse;
return operation;
}