Permalink
Browse files

I think we've finally got this blocks stuff sorted!

Small fixes to iPad sample
  • Loading branch information...
pokeb committed Oct 31, 2010
1 parent 25f8c54 commit 8e1ca638eaac5477557d2881cc6ce23ef8b70d2f
View
@@ -62,6 +62,7 @@ typedef enum _ASINetworkErrorType {
} ASINetworkErrorType;
#if NS_BLOCKS_AVAILABLE
+typedef void (^ASIBasicBlock)(void);
typedef void (^ASIHTTPRequestBlock)(ASIHTTPRequest *request);
typedef void (^ASIHTTPRequestSizeBlock)(ASIHTTPRequest *request, long long size);
typedef void (^ASIHTTPRequestProgressBlock)(ASIHTTPRequest *request, unsigned long long size, unsigned long long total);
@@ -613,7 +614,7 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
+ (void)updateProgressIndicator:(id *)indicator withProgress:(unsigned long long)progress ofTotal:(unsigned long long)total;
// Helper method used for performing invocations on the main thread (used for progress)
-+ (void)performSelector:(SEL)selector onTarget:(id *)target withObject:(id)object amount:(void *)amount;
++ (void)performSelector:(SEL)selector onTarget:(id *)target withObject:(id)object amount:(void *)amount callerToRetain:(id)caller;
#pragma mark talking to delegates
View
@@ -24,7 +24,7 @@
#import "ASIDataCompressor.h"
// Automatically set on build
-NSString *ASIHTTPRequestVersion = @"v1.7-120 2010-10-23";
+NSString *ASIHTTPRequestVersion = @"v1.7-121 2010-10-31";
NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain";
@@ -173,9 +173,11 @@ + (void)registerForNetworkReachabilityNotifications;
+ (void)unsubscribeFromNetworkReachabilityNotifications;
// Called when the status of the network changes
+ (void)reachabilityChanged:(NSNotification *)note;
-
- (void)failAuthentication;
+#endif
+#if NS_BLOCKS_AVAILABLE
+- (void)performBlockOnMainThread:(ASIBasicBlock)block;
#endif
@property (assign) BOOL complete;
@@ -1518,7 +1520,7 @@ - (void)setUploadProgressDelegate:(id)newDelegate
#if !TARGET_OS_IPHONE
// If the uploadProgressDelegate is an NSProgressIndicator, we set its MaxValue to 1.0 so we can update it as if it were a UIProgressView
double max = 1.0;
- [ASIHTTPRequest performSelector:@selector(setMaxValue:) onTarget:&uploadProgressDelegate withObject:nil amount:&max];
+ [ASIHTTPRequest performSelector:@selector(setMaxValue:) onTarget:&uploadProgressDelegate withObject:nil amount:&max callerToRetain:nil];
#endif
[[self cancelledLock] unlock];
}
@@ -1539,7 +1541,7 @@ - (void)setDownloadProgressDelegate:(id)newDelegate
#if !TARGET_OS_IPHONE
// If the downloadProgressDelegate is an NSProgressIndicator, we set its MaxValue to 1.0 so we can update it as if it were a UIProgressView
double max = 1.0;
- [ASIHTTPRequest performSelector:@selector(setMaxValue:) onTarget:&downloadProgressDelegate withObject:nil amount:&max];
+ [ASIHTTPRequest performSelector:@selector(setMaxValue:) onTarget:&downloadProgressDelegate withObject:nil amount:&max callerToRetain:nil];
#endif
[[self cancelledLock] unlock];
}
@@ -1568,28 +1570,20 @@ - (void)updateDownloadProgress
return;
}
- [ASIHTTPRequest performSelector:@selector(request:didReceiveBytes:) onTarget:&queue withObject:self amount:&value];
- [ASIHTTPRequest performSelector:@selector(request:didReceiveBytes:) onTarget:&downloadProgressDelegate withObject:self amount:&value];
+ [ASIHTTPRequest performSelector:@selector(request:didReceiveBytes:) onTarget:&queue withObject:self amount:&value callerToRetain:self];
+ [ASIHTTPRequest performSelector:@selector(request:didReceiveBytes:) onTarget:&downloadProgressDelegate withObject:self amount:&value callerToRetain:self];
+
[ASIHTTPRequest updateProgressIndicator:&downloadProgressDelegate withProgress:[self totalBytesRead]+[self partialDownloadSize] ofTotal:[self contentLength]+[self partialDownloadSize]];
#if NS_BLOCKS_AVAILABLE
if (bytesReceivedBlock) {
- [ASIHTTPRequest performSelector:@selector(callBytesReceivedBlockWithLength:) onTarget:&self withObject:nil amount:&value];
+ __block ASIHTTPRequest *blockCopy = self;
+ [self performBlockOnMainThread:^{ bytesReceivedBlock(blockCopy, value, [self contentLength] + [self partialDownloadSize]); }];
}
#endif
[self setLastBytesRead:bytesReadSoFar];
}
-#if NS_BLOCKS_AVAILABLE
-- (void)callBytesReceivedBlockWithLength:(unsigned long long)value
-{
- if (bytesReceivedBlock) {
- __block ASIHTTPRequest *blockCopy = self;
- bytesReceivedBlock(blockCopy, value, blockCopy->contentLength + blockCopy->partialDownloadSize);
- }
-}
-#endif
-
- (void)updateUploadProgress
{
if ([self isCancelled] || [self totalBytesSent] == 0) {
@@ -1621,92 +1615,75 @@ - (void)updateUploadProgress
return;
}
- [ASIHTTPRequest performSelector:@selector(request:didSendBytes:) onTarget:&queue withObject:self amount:&value];
- [ASIHTTPRequest performSelector:@selector(request:didSendBytes:) onTarget:&uploadProgressDelegate withObject:self amount:&value];
+ [ASIHTTPRequest performSelector:@selector(request:didSendBytes:) onTarget:&queue withObject:self amount:&value callerToRetain:self];
+ [ASIHTTPRequest performSelector:@selector(request:didSendBytes:) onTarget:&uploadProgressDelegate withObject:self amount:&value callerToRetain:self];
[ASIHTTPRequest updateProgressIndicator:&uploadProgressDelegate withProgress:[self totalBytesSent]-[self uploadBufferSize] ofTotal:[self postLength]-[self uploadBufferSize]];
#if NS_BLOCKS_AVAILABLE
if(bytesSentBlock){
- [ASIHTTPRequest performSelector:@selector(callBytesSentBlockWithLength:) onTarget:&self withObject:nil amount:&value];
- }
- #endif
-}
-
-#if NS_BLOCKS_AVAILABLE
-- (void)callBytesSentBlockWithLength:(unsigned long long)value
-{
- if (bytesSentBlock) {
__block ASIHTTPRequest *blockCopy = self;
- bytesSentBlock(blockCopy, value, blockCopy->postLength);
+ [self performBlockOnMainThread:^{ bytesSentBlock(blockCopy, value, blockCopy->postLength); }];
}
+ #endif
}
-#endif
- (void)incrementDownloadSizeBy:(long long)length
{
- [ASIHTTPRequest performSelector:@selector(request:incrementDownloadSizeBy:) onTarget:&queue withObject:self amount:&length];
- [ASIHTTPRequest performSelector:@selector(request:incrementDownloadSizeBy:) onTarget:&downloadProgressDelegate withObject:self amount:&length];
+ [ASIHTTPRequest performSelector:@selector(request:incrementDownloadSizeBy:) onTarget:&queue withObject:self amount:&length callerToRetain:self];
+ [ASIHTTPRequest performSelector:@selector(request:incrementDownloadSizeBy:) onTarget:&downloadProgressDelegate withObject:self amount:&length callerToRetain:self];
#if NS_BLOCKS_AVAILABLE
if(downloadSizeIncrementedBlock){
- [ASIHTTPRequest performSelector:@selector(callDownloadSizeIncrementedBlockWithLength:) onTarget:&self withObject:nil amount:&length];
+ __block ASIHTTPRequest *blockCopy = self;
+ [self performBlockOnMainThread:^{ downloadSizeIncrementedBlock(blockCopy, length); }];
}
#endif
}
-#if NS_BLOCKS_AVAILABLE
-- (void)callDownloadSizeIncrementedBlockWithLength:(unsigned long long)length
-{
- if (downloadSizeIncrementedBlock) {
- __block ASIHTTPRequest *blockCopy = self;
- downloadSizeIncrementedBlock(blockCopy, length);
- }
-}
-#endif
-
-
-
- (void)incrementUploadSizeBy:(long long)length
{
- [ASIHTTPRequest performSelector:@selector(request:incrementUploadSizeBy:) onTarget:&queue withObject:self amount:&length];
- [ASIHTTPRequest performSelector:@selector(request:incrementUploadSizeBy:) onTarget:&uploadProgressDelegate withObject:self amount:&length];
+ [ASIHTTPRequest performSelector:@selector(request:incrementUploadSizeBy:) onTarget:&queue withObject:self amount:&length callerToRetain:self];
+ [ASIHTTPRequest performSelector:@selector(request:incrementUploadSizeBy:) onTarget:&uploadProgressDelegate withObject:self amount:&length callerToRetain:self];
#if NS_BLOCKS_AVAILABLE
if(uploadSizeIncrementedBlock){
- [ASIHTTPRequest performSelector:@selector(callUploadSizeIncrementedBlockWithLength:) onTarget:&self withObject:nil amount:&length];
+ __block ASIHTTPRequest *blockCopy = self;
+ [self performBlockOnMainThread:^{ uploadSizeIncrementedBlock(blockCopy, length); }];
}
#endif
}
-#if NS_BLOCKS_AVAILABLE
-- (void)callUploadSizeIncrementedBlockWithLength:(unsigned long long)length
-{
- if(uploadSizeIncrementedBlock){
- __block ASIHTTPRequest *blockCopy = self;
- uploadSizeIncrementedBlock(blockCopy, length);
- }
-}
-#endif
-
-(void)removeUploadProgressSoFar
{
long long progressToRemove = -[self totalBytesSent];
- [ASIHTTPRequest performSelector:@selector(request:didSendBytes:) onTarget:&queue withObject:self amount:&progressToRemove];
- [ASIHTTPRequest performSelector:@selector(request:didSendBytes:) onTarget:&uploadProgressDelegate withObject:self amount:&progressToRemove];
+ [ASIHTTPRequest performSelector:@selector(request:didSendBytes:) onTarget:&queue withObject:self amount:&progressToRemove callerToRetain:self];
+ [ASIHTTPRequest performSelector:@selector(request:didSendBytes:) onTarget:&uploadProgressDelegate withObject:self amount:&progressToRemove callerToRetain:self];
[ASIHTTPRequest updateProgressIndicator:&uploadProgressDelegate withProgress:0 ofTotal:[self postLength]];
#if NS_BLOCKS_AVAILABLE
if(bytesSentBlock){
- [ASIHTTPRequest performSelector:@selector(callBytesSentBlockWithLength:) onTarget:&self withObject:nil amount:&progressToRemove];
-
+ __block ASIHTTPRequest *blockCopy = self;
+ [self performBlockOnMainThread:^{ bytesSentBlock(blockCopy, progressToRemove, blockCopy->postLength); }];
}
#endif
}
+#if NS_BLOCKS_AVAILABLE
+- (void)performBlockOnMainThread:(ASIBasicBlock)block
+{
+ [self performSelectorOnMainThread:@selector(callBlock:) withObject:[[block copy] autorelease] waitUntilDone:NO];
+}
-+ (void)performSelector:(SEL)selector onTarget:(id *)target withObject:(id)object amount:(void *)amount
+- (void)callBlock:(ASIBasicBlock)block
+{
+ block();
+}
+#endif
+
+
++ (void)performSelector:(SEL)selector onTarget:(id *)target withObject:(id)object amount:(void *)amount callerToRetain:(id)callerToRetain
{
if ([*target respondsToSelector:selector]) {
NSMethodSignature *signature = nil;
@@ -1720,36 +1697,45 @@ + (void)performSelector:(SEL)selector onTarget:(id *)target withObject:(id)objec
// If we got an object parameter, we pass a pointer to the object pointer
if (object) {
[invocation setArgument:&object atIndex:argumentNumber];
- argumentNumber++;
+ argumentNumber++;
}
// For the amount we'll just pass the pointer directly so NSInvocation will call the method using the number itself rather than a pointer to it
if (amount) {
[invocation setArgument:amount atIndex:argumentNumber];
}
- SEL callback = @selector(performInvocation:onTarget:);
+ SEL callback = @selector(performInvocation:onTarget:releasingObject:);
NSMethodSignature *cbSignature = [ASIHTTPRequest methodSignatureForSelector:callback];
NSInvocation *cbInvocation = [NSInvocation invocationWithMethodSignature:cbSignature];
[cbInvocation setSelector:callback];
[cbInvocation setTarget:self];
[cbInvocation setArgument:&invocation atIndex:2];
[cbInvocation setArgument:&target atIndex:3];
-
- // Ensure both of these stay around for the duration of the callback. Don't worry - we get CFReleased in the very next method!
+ if (callerToRetain) {
+ [cbInvocation setArgument:&callerToRetain atIndex:4];
+ }
+
CFRetain(invocation);
- CFRetain(self);
+
+ // Used to pass in a request that we must retain until after the call
+ // We're using CFRetain rather than [callerToRetain retain] so things to avoid earthquakes when using garbage collection
+ if (callerToRetain) {
+ CFRetain(callerToRetain);
+ }
[cbInvocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:[NSThread isMainThread]];
}
}
-+ (void)performInvocation:(NSInvocation *)invocation onTarget:(id *)target
++ (void)performInvocation:(NSInvocation *)invocation onTarget:(id *)target releasingObject:(id)objectToRelease
{
if (*target && [*target respondsToSelector:[invocation selector]]) {
[invocation invokeWithTarget:*target];
}
CFRelease(invocation);
- CFRelease(self);
+ if (objectToRelease) {
+ CFRelease(objectToRelease);
+ }
}
@@ -1771,7 +1757,7 @@ + (void)updateProgressIndicator:(id *)indicator withProgress:(unsigned long long
}
[progressLock lock];
- [ASIHTTPRequest performSelector:selector onTarget:indicator withObject:nil amount:&progressAmount];
+ [ASIHTTPRequest performSelector:selector onTarget:indicator withObject:nil amount:&progressAmount callerToRetain:nil];
[progressLock unlock];
}
@@ -96,18 +96,18 @@ - (void)resetProgressDelegate:(id *)progressDelegate
SEL selector = @selector(setMaxValue:);
if ([*progressDelegate respondsToSelector:selector]) {
double max = 1.0;
- [ASIHTTPRequest performSelector:selector onTarget:progressDelegate withObject:nil amount:&max];
+ [ASIHTTPRequest performSelector:selector onTarget:progressDelegate withObject:nil amount:&max callerToRetain:nil];
}
selector = @selector(setDoubleValue:);
if ([*progressDelegate respondsToSelector:selector]) {
double value = 0.0;
- [ASIHTTPRequest performSelector:selector onTarget:progressDelegate withObject:nil amount:&value];
+ [ASIHTTPRequest performSelector:selector onTarget:progressDelegate withObject:nil amount:&value callerToRetain:nil];
}
#else
SEL selector = @selector(setProgress:);
if ([*progressDelegate respondsToSelector:selector]) {
float value = 0.0f;
- [ASIHTTPRequest performSelector:selector onTarget:progressDelegate withObject:nil amount:&value];
+ [ASIHTTPRequest performSelector:selector onTarget:progressDelegate withObject:nil amount:&value callerToRetain:nil];
}
#endif
}
@@ -0,0 +1,16 @@
+//
+// BlocksTests.h
+// Mac
+//
+// Created by Ben Copsey on 18/10/2010.
+// Copyright 2010 All-Seeing Interactive. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "ASITestCase.h"
+
+@interface BlocksTests : ASITestCase {
+
+}
+
+@end
Oops, something went wrong.

0 comments on commit 8e1ca63

Please sign in to comment.