Merge branch 'experimental-0.9'

This commit is contained in:
Mattt Thompson 2012-01-23 09:11:32 -08:00
commit 1c64c6c374
22 changed files with 601 additions and 453 deletions

View file

@ -1,11 +1,12 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'AFNetworking' s.name = 'AFNetworking'
s.version = '0.8.0' s.version = '0.9.0'
s.license = 'MIT'
s.summary = 'A delightful iOS and OS X networking framework' s.summary = 'A delightful iOS and OS X networking framework'
s.homepage = 'https://github.com/AFNetworking/AFNetworking' s.homepage = 'https://github.com/AFNetworking/AFNetworking'
s.authors = {'Mattt Thompson' => 'm@mattt.me', 'Scott Raymond' => 'sco@gowalla.com'} s.authors = {'Mattt Thompson' => 'm@mattt.me', 'Scott Raymond' => 'sco@gowalla.com'}
s.source = { :git => 'https://github.com/AFNetworking/AFNetworking.git', s.source = { :git => 'https://github.com/AFNetworking/AFNetworking.git', :tag => '0.9.0' }
:tag => '0.8.0' }
s.source_files = 'AFNetworking' s.source_files = 'AFNetworking'
s.clean_paths = ['iOS Example', 'Mac Example', 'AFNetworking.xcworkspace']
s.framework = 'SystemConfiguration'
end end

View file

@ -160,9 +160,24 @@ extern NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *paramete
*/ */
- (id)initWithBaseURL:(NSURL *)url; - (id)initWithBaseURL:(NSURL *)url;
///---------------------------------- ///-----------------------------------
/// @name Managing Reachability Status
///-----------------------------------
/**
Sets a callback to be executed when the network availability of the `baseURL` host changes.
@param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument, which is `YES` if the host is available, otherwise `NO`.
@warning This method requires the `SystemConfiguration` framework. Add it in the active target's "Link Binary With Library" build phase, and add `#import <SystemConfiguration/SystemConfiguration.h>` to the header prefix of the project (Prefix.pch).
*/
#ifdef _SYSTEMCONFIGURATION_H
- (void)setReachabilityStatusChangeBlock:(void (^)(BOOL isNetworkReachable))block;
#endif
///-------------------------------
/// @name Managing HTTP Operations /// @name Managing HTTP Operations
///---------------------------------- ///-------------------------------
/** /**
Attempts to register a subclass of `AFHTTPRequestOperation`, adding it to a chain to automatically generate request operations from a URL request. Attempts to register a subclass of `AFHTTPRequestOperation`, adding it to a chain to automatically generate request operations from a URL request.
@ -294,12 +309,40 @@ extern NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *paramete
- (void)enqueueHTTPRequestOperation:(AFHTTPRequestOperation *)operation; - (void)enqueueHTTPRequestOperation:(AFHTTPRequestOperation *)operation;
/** /**
Cancels all operations in the HTTP client's operation queue that match the specified HTTP method and URL. Cancels all operations in the HTTP client's operation queue whose URLs match the specified HTTP method and path.
@param method The HTTP method to match for the cancelled requests, such as `GET`, `POST`, `PUT`, or `DELETE`. @param method The HTTP method to match for the cancelled requests, such as `GET`, `POST`, `PUT`, or `DELETE`. If `nil`, all request operations with URLs matching the path will be cancelled.
@param url The URL to match for the cancelled requests. @param url The path to match for the cancelled requests.
*/ */
- (void)cancelHTTPOperationsWithMethod:(NSString *)method andURL:(NSURL *)url; - (void)cancelAllHTTPOperationsWithMethod:(NSString *)method path:(NSString *)path;
///---------------------------------------
/// @name Batching HTTP Request Operations
///---------------------------------------
/**
Creates and enqueues an `AFHTTPRequestOperation` to the HTTP client's operation queue for each specified request object into a batch. When each request operation finishes, the specified progress block is executed, until all of the request operations have finished, at which point the completion block also executes.
@param requests The `NSURLRequest` objects used to create and enqueue operations.
@param progressBlock A block object to be executed upon the completion of each request operation in the batch. This block has no return value and takes two arguments: the number of operations that have already finished execution, and the total number of operations.
@param completionBlock A block object to be executed upon the completion of all of the request operations in the batch. This block has no return value and takes a single argument: the batched request operations.
@discussion Operations are created by passing the specified `NSURLRequest` objects in `requests`, using `-HTTPRequestOperationWithRequest:success:failure:`, with `nil` for both the `success` and `failure` parameters.
*/
- (void)enqueueBatchOfHTTPRequestOperationsWithRequests:(NSArray *)requests
progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock
completionBlock:(void (^)(NSArray *operations))completionBlock;
/**
Enqueues the specified request operations into a batch. When each request operation finishes, the specified progress block is executed, until all of the request operations have finished, at which point the completion block also executes.
@param operations The request operations used to be batched and enqueued.
@param progressBlock A block object to be executed upon the completion of each request operation in the batch. This block has no return value and takes two arguments: the number of operations that have already finished execution, and the total number of operations.
@param completionBlock A block object to be executed upon the completion of all of the request operations in the batch. This block has no return value and takes a single argument: the batched request operations.
*/
- (void)enqueueBatchOfHTTPRequestOperations:(NSArray *)operations
progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock
completionBlock:(void (^)(NSArray *operations))completionBlock;
///--------------------------- ///---------------------------
/// @name Making HTTP Requests /// @name Making HTTP Requests

View file

@ -32,6 +32,11 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#endif #endif
#ifdef _SYSTEMCONFIGURATION_H
#import <SystemConfiguration/SystemConfiguration.h>
#endif
static NSString * const kAFMultipartFormLineDelimiter = @"\r\n"; // CRLF
static NSString * const kAFMultipartFormBoundary = @"Boundary+0xAbCdEfGbOuNdArY"; static NSString * const kAFMultipartFormBoundary = @"Boundary+0xAbCdEfGbOuNdArY";
@interface AFMultipartFormData : NSObject <AFMultipartFormData> { @interface AFMultipartFormData : NSObject <AFMultipartFormData> {
@ -48,6 +53,15 @@ static NSString * const kAFMultipartFormBoundary = @"Boundary+0xAbCdEfGbOuNdArY"
#pragma mark - #pragma mark -
#ifdef _SYSTEMCONFIGURATION_H
typedef SCNetworkReachabilityRef AFNetworkReachabilityRef;
#else
typedef id AFNetworkReachabilityRef;
#endif
typedef void (^AFNetworkReachabilityStatusBlock)(BOOL isNetworkReachable);
typedef void (^AFCompletionBlock)(void);
static NSUInteger const kAFHTTPClientDefaultMaxConcurrentOperationCount = 4; static NSUInteger const kAFHTTPClientDefaultMaxConcurrentOperationCount = 4;
static NSString * AFBase64EncodedStringFromString(NSString *string) { static NSString * AFBase64EncodedStringFromString(NSString *string) {
@ -132,6 +146,8 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
@property (readwrite, nonatomic, retain) NSMutableArray *registeredHTTPOperationClassNames; @property (readwrite, nonatomic, retain) NSMutableArray *registeredHTTPOperationClassNames;
@property (readwrite, nonatomic, retain) NSMutableDictionary *defaultHeaders; @property (readwrite, nonatomic, retain) NSMutableDictionary *defaultHeaders;
@property (readwrite, nonatomic, retain) NSOperationQueue *operationQueue; @property (readwrite, nonatomic, retain) NSOperationQueue *operationQueue;
@property (readwrite, nonatomic, assign) AFNetworkReachabilityRef networkReachability;
@property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock;
@end @end
@implementation AFHTTPClient @implementation AFHTTPClient
@ -141,6 +157,8 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
@synthesize registeredHTTPOperationClassNames = _registeredHTTPOperationClassNames; @synthesize registeredHTTPOperationClassNames = _registeredHTTPOperationClassNames;
@synthesize defaultHeaders = _defaultHeaders; @synthesize defaultHeaders = _defaultHeaders;
@synthesize operationQueue = _operationQueue; @synthesize operationQueue = _operationQueue;
@synthesize networkReachability = _networkReachability;
@synthesize networkReachabilityStatusBlock = _networkReachabilityStatusBlock;
+ (AFHTTPClient *)clientWithBaseURL:(NSURL *)url { + (AFHTTPClient *)clientWithBaseURL:(NSURL *)url {
return [[[self alloc] initWithBaseURL:url] autorelease]; return [[[self alloc] initWithBaseURL:url] autorelease];
@ -186,9 +204,43 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
[_registeredHTTPOperationClassNames release]; [_registeredHTTPOperationClassNames release];
[_defaultHeaders release]; [_defaultHeaders release];
[_operationQueue release]; [_operationQueue release];
[_networkReachabilityStatusBlock release];
if (_networkReachability) {
CFRelease(_networkReachability);
}
[super dealloc]; [super dealloc];
} }
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p, baseURL: %@, defaultHeaders: %@, registeredOperationClasses: %@, operationQueue: %@>", NSStringFromClass([self class]), self, [self.baseURL absoluteString], self.defaultHeaders, self.registeredHTTPOperationClassNames, self.operationQueue];
}
#pragma mark -
#ifdef _SYSTEMCONFIGURATION_H
static void AFReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
if (info) {
AFNetworkReachabilityStatusBlock block = (AFNetworkReachabilityStatusBlock)info;
BOOL isNetworkReachable = (flags & kSCNetworkReachabilityFlagsReachable);
block(isNetworkReachable);
}
}
- (void)setReachabilityStatusChangeBlock:(void (^)(BOOL isNetworkReachable))block {
if (_networkReachability) {
SCNetworkReachabilityUnscheduleFromRunLoop(_networkReachability, CFRunLoopGetMain(), (CFStringRef)NSRunLoopCommonModes);
CFRelease(_networkReachability);
}
self.networkReachabilityStatusBlock = block;
self.networkReachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [[self.baseURL host] UTF8String]);
SCNetworkReachabilityContext context = {0, self.networkReachabilityStatusBlock, NULL, NULL, NULL};
SCNetworkReachabilitySetCallback(self.networkReachability, AFReachabilityCallback, &context);
SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), (CFStringRef)NSRunLoopCommonModes);
}
#endif
#pragma mark - #pragma mark -
- (BOOL)registerHTTPOperationClass:(Class)operationClass { - (BOOL)registerHTTPOperationClass:(Class)operationClass {
@ -326,18 +378,64 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) {
return operation; return operation;
} }
#pragma mark -
- (void)enqueueHTTPRequestOperation:(AFHTTPRequestOperation *)operation { - (void)enqueueHTTPRequestOperation:(AFHTTPRequestOperation *)operation {
[self.operationQueue addOperation:operation]; [self.operationQueue addOperation:operation];
} }
- (void)cancelHTTPOperationsWithMethod:(NSString *)method andURL:(NSURL *)url { - (void)cancelAllHTTPOperationsWithMethod:(NSString *)method path:(NSString *)path {
for (AFHTTPRequestOperation *operation in [self.operationQueue operations]) { for (AFHTTPRequestOperation *operation in [self.operationQueue operations]) {
if ([[[operation request] HTTPMethod] isEqualToString:method] && [[[operation request] URL] isEqual:url]) { if ((!method || [method isEqualToString:[[operation request] HTTPMethod]]) && [path isEqualToString:[[[operation request] URL] path]]) {
[operation cancel]; [operation cancel];
} }
} }
} }
- (void)enqueueBatchOfHTTPRequestOperationsWithRequests:(NSArray *)requests
progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock
completionBlock:(void (^)(NSArray *operations))completionBlock
{
NSMutableArray *mutableOperations = [NSMutableArray array];
for (NSURLRequest *request in requests) {
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:nil failure:nil];
[mutableOperations addObject:operation];
}
[self enqueueBatchOfHTTPRequestOperations:mutableOperations progressBlock:progressBlock completionBlock:completionBlock];
}
- (void)enqueueBatchOfHTTPRequestOperations:(NSArray *)operations
progressBlock:(void (^)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations))progressBlock
completionBlock:(void (^)(NSArray *operations))completionBlock
{
NSBlockOperation *batchedOperation = [NSBlockOperation blockOperationWithBlock:^{
if (completionBlock) {
completionBlock(operations);
}
}];
[self.operationQueue addOperation:batchedOperation];
NSPredicate *finishedOperationPredicate = [NSPredicate predicateWithFormat:@"isFinished == YES"];
for (AFHTTPRequestOperation *operation in operations) {
AFCompletionBlock originalCompletionBlock = [[operation.completionBlock copy] autorelease];
operation.completionBlock = ^{
if (progressBlock) {
progressBlock([[batchedOperation.dependencies filteredArrayUsingPredicate:finishedOperationPredicate] count], [batchedOperation.dependencies count]);
}
if (originalCompletionBlock) {
originalCompletionBlock();
}
};
[batchedOperation addDependency:operation];
[self enqueueHTTPRequestOperation:operation];
}
}
#pragma mark - #pragma mark -
- (void)getPath:(NSString *)path - (void)getPath:(NSString *)path

View file

@ -24,7 +24,6 @@
@interface AFHTTPRequestOperation () @interface AFHTTPRequestOperation ()
@property (readwrite, nonatomic, retain) NSError *HTTPError; @property (readwrite, nonatomic, retain) NSError *HTTPError;
@property (readonly, nonatomic, assign) BOOL hasContent;
@end @end
@implementation AFHTTPRequestOperation @implementation AFHTTPRequestOperation
@ -62,7 +61,7 @@
[userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey]; [userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey];
self.HTTPError = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo] autorelease]; self.HTTPError = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo] autorelease];
} else if ([self hasContent] && ![self hasAcceptableContentType]) { // Don't invalidate content type if there is no content } else if ([self.responseData length] > 0 && ![self hasAcceptableContentType]) { // Don't invalidate content type if there is no content
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
[userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected content type %@, got %@", nil), self.acceptableContentTypes, [self.response MIMEType]] forKey:NSLocalizedDescriptionKey]; [userInfo setValue:[NSString stringWithFormat:NSLocalizedString(@"Expected content type %@, got %@", nil), self.acceptableContentTypes, [self.response MIMEType]] forKey:NSLocalizedDescriptionKey];
[userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey]; [userInfo setValue:[self.request URL] forKey:NSURLErrorFailingURLErrorKey];
@ -71,17 +70,13 @@
} }
} }
if (_HTTPError) { if (self.HTTPError) {
return _HTTPError; return self.HTTPError;
} else { } else {
return [super error]; return [super error];
} }
} }
- (BOOL)hasContent {
return [self.responseData length] > 0;
}
- (BOOL)hasAcceptableStatusCode { - (BOOL)hasAcceptableStatusCode {
return !self.acceptableStatusCodes || [self.acceptableStatusCodes containsIndex:[self.response statusCode]]; return !self.acceptableStatusCodes || [self.acceptableStatusCodes containsIndex:[self.response statusCode]];
} }

View file

@ -1,76 +0,0 @@
// AFImageCache.h
//
// Copyright (c) 2011 Gowalla (http://gowalla.com/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Foundation/Foundation.h>
#import "AFImageRequestOperation.h"
#import <Availability.h>
/**
`AFImageCache` is an `NSCache` that stores and retrieves images from cache.
@discussion `AFImageCache` is used to cache images for successful `AFImageRequestOperations` with the proper cache policy.
*/
@interface AFImageCache : NSCache
#if __IPHONE_OS_VERSION_MIN_REQUIRED
/**
The scale factor used when interpreting the cached image data. Specifying a scale factor of 1.0 results in an image whose size matches the pixel-based dimensions of the image. Applying a different scale factor changes the size of the image as reported by the size property. This is set to the value of `[[UIScreen mainScreen] scale]` by default, which automatically scales images for retina displays, for instance.
*/
@property (nonatomic, assign) CGFloat imageScale;
#endif
/**
Returns the shared image cache object for the system.
@return The systemwide image cache.
*/
+ (AFImageCache *)sharedImageCache;
/**
Returns the image associated with a given URL and cache name.
@param url The URL associated with the image in the cache.
@param cacheName The cache name associated with the image in the cache. This allows for multiple versions of an image to be associated for a single URL, such as image thumbnails, for instance.
@return The image associated with the URL and cache name, or `nil` if not image exists.
*/
#if __IPHONE_OS_VERSION_MIN_REQUIRED
- (UIImage *)cachedImageForURL:(NSURL *)url
cacheName:(NSString *)cacheName;
#elif __MAC_OS_X_VERSION_MIN_REQUIRED
- (NSImage *)cachedImageForURL:(NSURL *)url
cacheName:(NSString *)cacheName;
#endif
/**
Stores image data into cache, associated with a given URL and cache name.
@param imageData The image data to be stored in cache.
@param url The URL to be associated with the image.
@param cacheName The cache name to be associated with the image in the cache. This allows for multiple versions of an image to be associated for a single URL, such as image thumbnails, for instance.
*/
- (void)cacheImageData:(NSData *)imageData
forURL:(NSURL *)url
cacheName:(NSString *)cacheName;
@end

View file

@ -1,83 +0,0 @@
// AFImageCache.m
//
// Copyright (c) 2011 Gowalla (http://gowalla.com/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "AFImageCache.h"
static inline NSString * AFImageCacheKeyFromURLAndCacheName(NSURL *url, NSString *cacheName) {
return [[url absoluteString] stringByAppendingFormat:@"#%@", cacheName];
}
@implementation AFImageCache
#if __IPHONE_OS_VERSION_MIN_REQUIRED
@synthesize imageScale = _imageScale;
#endif
+ (AFImageCache *)sharedImageCache {
static AFImageCache *_sharedImageCache = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedImageCache = [[self alloc] init];
});
return _sharedImageCache;
}
- (id)init {
self = [super init];
if (!self) {
return nil;
}
#if __IPHONE_OS_VERSION_MIN_REQUIRED
self.imageScale = [[UIScreen mainScreen] scale];
#endif
return self;
}
#if __IPHONE_OS_VERSION_MIN_REQUIRED
- (UIImage *)cachedImageForURL:(NSURL *)url
cacheName:(NSString *)cacheName
{
UIImage *image = [UIImage imageWithData:[self objectForKey:AFImageCacheKeyFromURLAndCacheName(url, cacheName)]];
if (image) {
return [UIImage imageWithCGImage:[image CGImage] scale:self.imageScale orientation:image.imageOrientation];
}
return image;
}
#elif __MAC_OS_X_VERSION_MIN_REQUIRED
- (NSImage *)cachedImageForURL:(NSURL *)url
cacheName:(NSString *)cacheName
{
return [[[NSImage alloc] initWithData:[self objectForKey:AFImageCacheKeyFromURLAndCacheName(url, cacheName)]] autorelease];
}
#endif
- (void)cacheImageData:(NSData *)imageData
forURL:(NSURL *)url
cacheName:(NSString *)cacheName
{
[self setObject:[NSPurgeableData dataWithData:imageData] forKey:AFImageCacheKeyFromURLAndCacheName(url, cacheName)];
}
@end

View file

@ -21,7 +21,6 @@
// THE SOFTWARE. // THE SOFTWARE.
#import "AFImageRequestOperation.h" #import "AFImageRequestOperation.h"
#import "AFImageCache.h"
static dispatch_queue_t af_image_request_operation_processing_queue; static dispatch_queue_t af_image_request_operation_processing_queue;
static dispatch_queue_t image_request_operation_processing_queue() { static dispatch_queue_t image_request_operation_processing_queue() {
@ -157,7 +156,7 @@ static dispatch_queue_t image_request_operation_processing_queue() {
#if __IPHONE_OS_VERSION_MIN_REQUIRED #if __IPHONE_OS_VERSION_MIN_REQUIRED
- (UIImage *)responseImage { - (UIImage *)responseImage {
if (!_responseImage && [self isFinished]) { if (!_responseImage && [self.responseData length] > 0 && [self isFinished]) {
UIImage *image = [UIImage imageWithData:self.responseData]; UIImage *image = [UIImage imageWithData:self.responseData];
self.responseImage = [UIImage imageWithCGImage:[image CGImage] scale:self.imageScale orientation:image.imageOrientation]; self.responseImage = [UIImage imageWithCGImage:[image CGImage] scale:self.imageScale orientation:image.imageOrientation];
@ -179,7 +178,7 @@ static dispatch_queue_t image_request_operation_processing_queue() {
} }
#elif __MAC_OS_X_VERSION_MIN_REQUIRED #elif __MAC_OS_X_VERSION_MIN_REQUIRED
- (NSImage *)responseImage { - (NSImage *)responseImage {
if (!_responseImage && [self isFinished]) { if (!_responseImage && [self.responseData length] > 0 && [self isFinished]) {
// Ensure that the image is set to it's correct pixel width and height // Ensure that the image is set to it's correct pixel width and height
NSBitmapImageRep *bitimage = [[NSBitmapImageRep alloc] initWithData:self.responseData]; NSBitmapImageRep *bitimage = [[NSBitmapImageRep alloc] initWithData:self.responseData];
self.responseImage = [[[NSImage alloc] initWithSize:NSMakeSize([bitimage pixelsWide], [bitimage pixelsHigh])] autorelease]; self.responseImage = [[[NSImage alloc] initWithSize:NSMakeSize([bitimage pixelsWide], [bitimage pixelsHigh])] autorelease];

View file

@ -92,7 +92,7 @@ static dispatch_queue_t json_request_operation_processing_queue() {
} }
- (id)responseJSON { - (id)responseJSON {
if (!_responseJSON && [self isFinished]) { if (!_responseJSON && [self.responseData length] > 0 && [self isFinished]) {
NSError *error = nil; NSError *error = nil;
if ([self.responseData length] == 0) { if ([self.responseData length] == 0) {

View file

@ -22,148 +22,5 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
static NSData * AFJSONEncode(id object, NSError **error) { extern NSData * AFJSONEncode(id object, NSError **error);
NSData *data = nil; extern id AFJSONDecode(NSData *data, NSError **error);
SEL _JSONKitSelector = NSSelectorFromString(@"JSONDataWithOptions:error:");
SEL _SBJSONSelector = NSSelectorFromString(@"JSONRepresentation");
SEL _YAJLSelector = NSSelectorFromString(@"yajl_JSONString");
id _NSJSONSerializationClass = NSClassFromString(@"NSJSONSerialization");
SEL _NSJSONSerializationSelector = NSSelectorFromString(@"dataWithJSONObject:options:error:");
#ifdef _AFNETWORKING_PREFER_NSJSONSERIALIZATION_
if (_NSJSONSerializationClass && [_NSJSONSerializationClass respondsToSelector:_NSJSONSerializationSelector]) {
goto _af_nsjson_encode;
}
#endif
if (_JSONKitSelector && [object respondsToSelector:_JSONKitSelector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[object methodSignatureForSelector:_JSONKitSelector]];
invocation.target = object;
invocation.selector = _JSONKitSelector;
NSUInteger serializeOptionFlags = 0;
[invocation setArgument:&serializeOptionFlags atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[invocation setArgument:error atIndex:3];
[invocation invoke];
[invocation getReturnValue:&data];
} else if (_SBJSONSelector && [object respondsToSelector:_SBJSONSelector]) {
NSString *JSONString = nil;
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[object methodSignatureForSelector:_SBJSONSelector]];
invocation.target = object;
invocation.selector = _SBJSONSelector;
[invocation invoke];
[invocation getReturnValue:&JSONString];
data = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
} else if (_YAJLSelector && [object respondsToSelector:_YAJLSelector]) {
@try {
NSString *JSONString = nil;
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[object methodSignatureForSelector:_YAJLSelector]];
invocation.target = object;
invocation.selector = _YAJLSelector;
[invocation invoke];
[invocation getReturnValue:&JSONString];
data = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
}
@catch (NSException *exception) {
*error = [[[NSError alloc] initWithDomain:NSStringFromClass([exception class]) code:0 userInfo:[exception userInfo]] autorelease];
}
} else if (_NSJSONSerializationClass && [_NSJSONSerializationClass respondsToSelector:_NSJSONSerializationSelector]) {
#ifdef _AFNETWORKING_PREFER_NSJSONSERIALIZATION_
_af_nsjson_encode:
#endif
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[_NSJSONSerializationClass methodSignatureForSelector:_NSJSONSerializationSelector]];
invocation.target = _NSJSONSerializationClass;
invocation.selector = _NSJSONSerializationSelector;
[invocation setArgument:&object atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
NSUInteger writeOptions = 0;
[invocation setArgument:&writeOptions atIndex:3];
[invocation setArgument:error atIndex:4];
[invocation invoke];
[invocation getReturnValue:&data];
} else {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedString(@"Please either target a platform that supports NSJSONSerialization or add one of the following libraries to your project: JSONKit, SBJSON, or YAJL", nil) forKey:NSLocalizedRecoverySuggestionErrorKey];
[[NSException exceptionWithName:NSInternalInconsistencyException reason:NSLocalizedString(@"No JSON generation functionality available", nil) userInfo:userInfo] raise];
}
return data;
}
static id AFJSONDecode(NSData *data, NSError **error) {
id JSON = nil;
SEL _JSONKitSelector = NSSelectorFromString(@"objectFromJSONDataWithParseOptions:error:");
SEL _SBJSONSelector = NSSelectorFromString(@"JSONValue");
SEL _YAJLSelector = NSSelectorFromString(@"yajl_JSONWithOptions:error:");
id _NSJSONSerializationClass = NSClassFromString(@"NSJSONSerialization");
SEL _NSJSONSerializationSelector = NSSelectorFromString(@"JSONObjectWithData:options:error:");
#ifdef _AFNETWORKING_PREFER_NSJSONSERIALIZATION_
if (_NSJSONSerializationClass && [_NSJSONSerializationClass respondsToSelector:_NSJSONSerializationSelector]) {
goto _af_nsjson_decode;
}
#endif
if (_JSONKitSelector && [data respondsToSelector:_JSONKitSelector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[data methodSignatureForSelector:_JSONKitSelector]];
invocation.target = data;
invocation.selector = _JSONKitSelector;
NSUInteger parseOptionFlags = 0;
[invocation setArgument:&parseOptionFlags atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[invocation setArgument:error atIndex:3];
[invocation invoke];
[invocation getReturnValue:&JSON];
} else if (_SBJSONSelector && [NSString instancesRespondToSelector:_SBJSONSelector]) {
// Create a string representation of JSON, to use SBJSON -`JSONValue` category method
NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[string methodSignatureForSelector:_SBJSONSelector]];
invocation.target = string;
invocation.selector = _SBJSONSelector;
[invocation invoke];
[invocation getReturnValue:&JSON];
} else if (_YAJLSelector && [data respondsToSelector:_YAJLSelector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[data methodSignatureForSelector:_YAJLSelector]];
invocation.target = data;
invocation.selector = _YAJLSelector;
NSUInteger yajlParserOptions = 0;
[invocation setArgument:&yajlParserOptions atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[invocation setArgument:error atIndex:3];
[invocation invoke];
[invocation getReturnValue:&JSON];
} else if (_NSJSONSerializationClass && [_NSJSONSerializationClass respondsToSelector:_NSJSONSerializationSelector]) {
#ifdef _AFNETWORKING_PREFER_NSJSONSERIALIZATION_
_af_nsjson_decode:
#endif
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[_NSJSONSerializationClass methodSignatureForSelector:_NSJSONSerializationSelector]];
invocation.target = _NSJSONSerializationClass;
invocation.selector = _NSJSONSerializationSelector;
[invocation setArgument:&data atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
NSUInteger readOptions = 0;
[invocation setArgument:&readOptions atIndex:3];
[invocation setArgument:error atIndex:4];
[invocation invoke];
[invocation getReturnValue:&JSON];
} else {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedString(@"Please either target a platform that supports NSJSONSerialization or add one of the following libraries to your project: JSONKit, SBJSON, or YAJL", nil) forKey:NSLocalizedRecoverySuggestionErrorKey];
[[NSException exceptionWithName:NSInternalInconsistencyException reason:NSLocalizedString(@"No JSON parsing functionality available", nil) userInfo:userInfo] raise];
}
return JSON;
}

View file

@ -0,0 +1,169 @@
// AFJSONUtilities.m
//
// Copyright (c) 2011 Gowalla (http://gowalla.com/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "AFJSONUtilities.h"
NSData * AFJSONEncode(id object, NSError **error) {
NSData *data = nil;
SEL _JSONKitSelector = NSSelectorFromString(@"JSONDataWithOptions:error:");
SEL _SBJSONSelector = NSSelectorFromString(@"JSONRepresentation");
SEL _YAJLSelector = NSSelectorFromString(@"yajl_JSONString");
id _NSJSONSerializationClass = NSClassFromString(@"NSJSONSerialization");
SEL _NSJSONSerializationSelector = NSSelectorFromString(@"dataWithJSONObject:options:error:");
#ifdef _AFNETWORKING_PREFER_NSJSONSERIALIZATION_
if (_NSJSONSerializationClass && [_NSJSONSerializationClass respondsToSelector:_NSJSONSerializationSelector]) {
goto _af_nsjson_encode;
}
#endif
if (_JSONKitSelector && [object respondsToSelector:_JSONKitSelector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[object methodSignatureForSelector:_JSONKitSelector]];
invocation.target = object;
invocation.selector = _JSONKitSelector;
NSUInteger serializeOptionFlags = 0;
[invocation setArgument:&serializeOptionFlags atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[invocation setArgument:error atIndex:3];
[invocation invoke];
[invocation getReturnValue:&data];
} else if (_SBJSONSelector && [object respondsToSelector:_SBJSONSelector]) {
NSString *JSONString = nil;
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[object methodSignatureForSelector:_SBJSONSelector]];
invocation.target = object;
invocation.selector = _SBJSONSelector;
[invocation invoke];
[invocation getReturnValue:&JSONString];
data = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
} else if (_YAJLSelector && [object respondsToSelector:_YAJLSelector]) {
@try {
NSString *JSONString = nil;
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[object methodSignatureForSelector:_YAJLSelector]];
invocation.target = object;
invocation.selector = _YAJLSelector;
[invocation invoke];
[invocation getReturnValue:&JSONString];
data = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
}
@catch (NSException *exception) {
*error = [[[NSError alloc] initWithDomain:NSStringFromClass([exception class]) code:0 userInfo:[exception userInfo]] autorelease];
}
} else if (_NSJSONSerializationClass && [_NSJSONSerializationClass respondsToSelector:_NSJSONSerializationSelector]) {
#ifdef _AFNETWORKING_PREFER_NSJSONSERIALIZATION_
_af_nsjson_encode:
#endif
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[_NSJSONSerializationClass methodSignatureForSelector:_NSJSONSerializationSelector]];
invocation.target = _NSJSONSerializationClass;
invocation.selector = _NSJSONSerializationSelector;
[invocation setArgument:&object atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
NSUInteger writeOptions = 0;
[invocation setArgument:&writeOptions atIndex:3];
[invocation setArgument:error atIndex:4];
[invocation invoke];
[invocation getReturnValue:&data];
} else {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedString(@"Please either target a platform that supports NSJSONSerialization or add one of the following libraries to your project: JSONKit, SBJSON, or YAJL", nil) forKey:NSLocalizedRecoverySuggestionErrorKey];
[[NSException exceptionWithName:NSInternalInconsistencyException reason:NSLocalizedString(@"No JSON generation functionality available", nil) userInfo:userInfo] raise];
}
return data;
}
id AFJSONDecode(NSData *data, NSError **error) {
id JSON = nil;
SEL _JSONKitSelector = NSSelectorFromString(@"objectFromJSONDataWithParseOptions:error:");
SEL _SBJSONSelector = NSSelectorFromString(@"JSONValue");
SEL _YAJLSelector = NSSelectorFromString(@"yajl_JSONWithOptions:error:");
id _NSJSONSerializationClass = NSClassFromString(@"NSJSONSerialization");
SEL _NSJSONSerializationSelector = NSSelectorFromString(@"JSONObjectWithData:options:error:");
#ifdef _AFNETWORKING_PREFER_NSJSONSERIALIZATION_
if (_NSJSONSerializationClass && [_NSJSONSerializationClass respondsToSelector:_NSJSONSerializationSelector]) {
goto _af_nsjson_decode;
}
#endif
if (_JSONKitSelector && [data respondsToSelector:_JSONKitSelector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[data methodSignatureForSelector:_JSONKitSelector]];
invocation.target = data;
invocation.selector = _JSONKitSelector;
NSUInteger parseOptionFlags = 0;
[invocation setArgument:&parseOptionFlags atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[invocation setArgument:error atIndex:3];
[invocation invoke];
[invocation getReturnValue:&JSON];
} else if (_SBJSONSelector && [NSString instancesRespondToSelector:_SBJSONSelector]) {
// Create a string representation of JSON, to use SBJSON -`JSONValue` category method
NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[string methodSignatureForSelector:_SBJSONSelector]];
invocation.target = string;
invocation.selector = _SBJSONSelector;
[invocation invoke];
[invocation getReturnValue:&JSON];
} else if (_YAJLSelector && [data respondsToSelector:_YAJLSelector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[data methodSignatureForSelector:_YAJLSelector]];
invocation.target = data;
invocation.selector = _YAJLSelector;
NSUInteger yajlParserOptions = 0;
[invocation setArgument:&yajlParserOptions atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[invocation setArgument:error atIndex:3];
[invocation invoke];
[invocation getReturnValue:&JSON];
} else if (_NSJSONSerializationClass && [_NSJSONSerializationClass respondsToSelector:_NSJSONSerializationSelector]) {
#ifdef _AFNETWORKING_PREFER_NSJSONSERIALIZATION_
_af_nsjson_decode:
#endif
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[_NSJSONSerializationClass methodSignatureForSelector:_NSJSONSerializationSelector]];
invocation.target = _NSJSONSerializationClass;
invocation.selector = _NSJSONSerializationSelector;
[invocation setArgument:&data atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
NSUInteger readOptions = 0;
[invocation setArgument:&readOptions atIndex:3];
[invocation setArgument:error atIndex:4];
[invocation invoke];
[invocation getReturnValue:&JSON];
} else {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedString(@"Please either target a platform that supports NSJSONSerialization or add one of the following libraries to your project: JSONKit, SBJSON, or YAJL", nil) forKey:NSLocalizedRecoverySuggestionErrorKey];
[[NSException exceptionWithName:NSInternalInconsistencyException reason:NSLocalizedString(@"No JSON parsing functionality available", nil) userInfo:userInfo] raise];
}
return JSON;
}

View file

@ -35,7 +35,6 @@
#import "AFHTTPClient.h" #import "AFHTTPClient.h"
#import "AFImageRequestOperation.h" #import "AFImageRequestOperation.h"
#import "AFImagecache.h"
#if __IPHONE_OS_VERSION_MIN_REQUIRED #if __IPHONE_OS_VERSION_MIN_REQUIRED
#import "AFNetworkActivityIndicatorManager.h" #import "AFNetworkActivityIndicatorManager.h"

View file

@ -92,7 +92,7 @@ static dispatch_queue_t property_list_request_operation_processing_queue() {
} }
- (id)responsePropertyList { - (id)responsePropertyList {
if (!_responsePropertyList && [self isFinished]) { if (!_responsePropertyList && [self.responseData length] > 0 && [self isFinished]) {
NSPropertyListFormat format; NSPropertyListFormat format;
NSError *error = nil; NSError *error = nil;
self.responsePropertyList = [NSPropertyListSerialization propertyListWithData:self.responseData options:self.propertyListReadOptions format:&format error:&error]; self.responsePropertyList = [NSPropertyListSerialization propertyListWithData:self.responseData options:self.propertyListReadOptions format:&format error:&error];

View file

@ -75,6 +75,10 @@ extern NSString * const AFNetworkingOperationDidFinishNotification;
*/ */
@interface AFURLConnectionOperation : NSOperation { @interface AFURLConnectionOperation : NSOperation {
@private @private
unsigned short _state;
BOOL _cancelled;
NSRecursiveLock *_lock;
NSSet *_runLoopModes; NSSet *_runLoopModes;
NSURLConnection *_connection; NSURLConnection *_connection;

View file

@ -22,14 +22,18 @@
#import "AFURLConnectionOperation.h" #import "AFURLConnectionOperation.h"
static NSUInteger const kAFHTTPMinimumInitialDataCapacity = 1024;
static NSUInteger const kAFHTTPMaximumInitialDataCapacity = 1024 * 1024 * 8;
typedef enum { typedef enum {
AFHTTPOperationReadyState = 1, AFHTTPOperationReadyState = 1,
AFHTTPOperationExecutingState = 2, AFHTTPOperationExecutingState = 2,
AFHTTPOperationFinishedState = 3, AFHTTPOperationFinishedState = 3,
} AFOperationState; } _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";
NSString * const AFNetworkingErrorDomain = @"com.alamofire.networking.error"; NSString * const AFNetworkingErrorDomain = @"com.alamofire.networking.error";
@ -52,9 +56,34 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
} }
} }
static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperationState toState, BOOL isCancelled) {
switch (fromState) {
case AFHTTPOperationReadyState:
switch (toState) {
case AFHTTPOperationExecutingState:
return YES;
case AFHTTPOperationFinishedState:
return isCancelled;
default:
return NO;
}
case AFHTTPOperationExecutingState:
switch (toState) {
case AFHTTPOperationFinishedState:
return YES;
default:
return NO;
}
case AFHTTPOperationFinishedState:
return NO;
default:
return YES;
}
}
@interface AFURLConnectionOperation () @interface AFURLConnectionOperation ()
@property (readwrite, nonatomic, assign) AFOperationState state; @property (readwrite, nonatomic, assign) AFOperationState state;
@property (readwrite, nonatomic, assign, getter = isCancelled) BOOL cancelled; @property (readwrite, nonatomic, retain) NSRecursiveLock *lock;
@property (readwrite, nonatomic, assign) NSURLConnection *connection; @property (readwrite, nonatomic, assign) NSURLConnection *connection;
@property (readwrite, nonatomic, retain) NSURLRequest *request; @property (readwrite, nonatomic, retain) NSURLRequest *request;
@property (readwrite, nonatomic, retain) NSURLResponse *response; @property (readwrite, nonatomic, retain) NSURLResponse *response;
@ -67,14 +96,12 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
@property (readwrite, nonatomic, copy) AFURLConnectionOperationProgressBlock downloadProgress; @property (readwrite, nonatomic, copy) AFURLConnectionOperationProgressBlock downloadProgress;
@property (readwrite, nonatomic, copy) AFURLConnectionOperationAuthenticationChallengeBlock authenticationBlock; @property (readwrite, nonatomic, copy) AFURLConnectionOperationAuthenticationChallengeBlock authenticationBlock;
- (BOOL)shouldTransitionToState:(AFOperationState)state;
- (void)operationDidStart; - (void)operationDidStart;
- (void)finish; - (void)finish;
@end @end
@implementation AFURLConnectionOperation @implementation AFURLConnectionOperation
@synthesize state = _state; @synthesize state = _state;
@synthesize cancelled = _cancelled;
@synthesize connection = _connection; @synthesize connection = _connection;
@synthesize runLoopModes = _runLoopModes; @synthesize runLoopModes = _runLoopModes;
@synthesize request = _request; @synthesize request = _request;
@ -89,12 +116,22 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
@synthesize uploadProgress = _uploadProgress; @synthesize uploadProgress = _uploadProgress;
@synthesize downloadProgress = _downloadProgress; @synthesize downloadProgress = _downloadProgress;
@synthesize authenticationBlock = _authenticationBlock; @synthesize authenticationBlock = _authenticationBlock;
@synthesize lock = _lock;
+ (void)networkRequestThreadEntryPoint:(id)__unused object { + (void)networkRequestThreadEntryPoint:(id)__unused object {
do { do {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool *exceptionPool = [[NSAutoreleasePool alloc] init];
NSException *caughtException = nil;
@try {
NSAutoreleasePool *runLoopPool = [[NSAutoreleasePool alloc] init];
[[NSRunLoop currentRunLoop] run]; [[NSRunLoop currentRunLoop] run];
[pool drain]; [runLoopPool drain];
}
@catch(NSException *e) { caughtException = e; }
if(caughtException) {
NSLog(NSLocalizedString(@"Unhandled exception on %@ networking thread: %@, userInfo: %@", nil), NSStringFromClass([self class]), caughtException, [caughtException userInfo]);
}
[exceptionPool drain];
} while (YES); } while (YES);
} }
@ -116,6 +153,9 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
return nil; return nil;
} }
self.lock = [[[NSRecursiveLock alloc] init] autorelease];
self.lock.name = kAFNetworkingLockName;
self.runLoopModes = [NSSet setWithObject:NSRunLoopCommonModes]; self.runLoopModes = [NSSet setWithObject:NSRunLoopCommonModes];
self.request = urlRequest; self.request = urlRequest;
@ -126,6 +166,8 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
} }
- (void)dealloc { - (void)dealloc {
[_lock release];
[_runLoopModes release]; [_runLoopModes release];
[_request release]; [_request release];
@ -135,7 +177,12 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
[_responseData release]; [_responseData release];
[_responseString release]; [_responseString release];
[_dataAccumulator release]; [_dataAccumulator release];
[_outputStream release]; _outputStream = nil;
if (_outputStream) {
[_outputStream close];
[_outputStream release];
_outputStream = nil;
}
[_uploadProgress release]; [_uploadProgress release];
[_downloadProgress release]; [_downloadProgress release];
@ -144,7 +191,12 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
[super dealloc]; [super dealloc];
} }
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p, state: %@, cancelled: %@ request: %@, response: %@>", NSStringFromClass([self class]), self, AFKeyPathFromOperationState(self.state), ([self isCancelled] ? @"YES" : @"NO"), self.request, self.response];
}
- (void)setCompletionBlock:(void (^)(void))block { - (void)setCompletionBlock:(void (^)(void))block {
[self.lock lock];
if (!block) { if (!block) {
[super setCompletionBlock:nil]; [super setCompletionBlock:nil];
} else { } else {
@ -154,6 +206,7 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
[_blockSelf setCompletionBlock:nil]; [_blockSelf setCompletionBlock:nil];
}]; }];
} }
[self.lock unlock];
} }
- (NSInputStream *)inputStream { - (NSInputStream *)inputStream {
@ -179,10 +232,8 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
} }
- (void)setState:(AFOperationState)state { - (void)setState:(AFOperationState)state {
if (![self shouldTransitionToState:state]) { [self.lock lock];
return; if (AFStateTransitionIsValid(self.state, state, [self isCancelled])) {
}
NSString *oldStateKey = AFKeyPathFromOperationState(self.state); NSString *oldStateKey = AFKeyPathFromOperationState(self.state);
NSString *newStateKey = AFKeyPathFromOperationState(state); NSString *newStateKey = AFKeyPathFromOperationState(state);
@ -202,42 +253,12 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
default: default:
break; break;
} }
}
- (BOOL)shouldTransitionToState:(AFOperationState)state {
switch (self.state) {
case AFHTTPOperationReadyState:
switch (state) {
case AFHTTPOperationExecutingState:
return YES;
default:
return NO;
}
case AFHTTPOperationExecutingState:
switch (state) {
case AFHTTPOperationFinishedState:
return YES;
default:
return NO;
}
case AFHTTPOperationFinishedState:
return NO;
default:
return YES;
}
}
- (void)setCancelled:(BOOL)cancelled {
[self willChangeValueForKey:@"isCancelled"];
_cancelled = cancelled;
[self didChangeValueForKey:@"isCancelled"];
if ([self isCancelled]) {
self.state = AFHTTPOperationFinishedState;
} }
[self.lock unlock];
} }
- (NSString *)responseString { - (NSString *)responseString {
[self.lock lock];
if (!_responseString && self.response && self.responseData) { if (!_responseString && self.response && self.responseData) {
NSStringEncoding textEncoding = NSUTF8StringEncoding; NSStringEncoding textEncoding = NSUTF8StringEncoding;
if (self.response.textEncodingName) { if (self.response.textEncodingName) {
@ -246,6 +267,7 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
self.responseString = [[[NSString alloc] initWithData:self.responseData encoding:textEncoding] autorelease]; self.responseString = [[[NSString alloc] initWithData:self.responseData encoding:textEncoding] autorelease];
} }
[self.lock unlock];
return _responseString; return _responseString;
} }
@ -264,26 +286,29 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
return self.state == AFHTTPOperationFinishedState; return self.state == AFHTTPOperationFinishedState;
} }
- (BOOL)isCancelled {
return _cancelled;
}
- (BOOL)isConcurrent { - (BOOL)isConcurrent {
return YES; return YES;
} }
- (void)start { - (void)start {
if (![self isReady]) { [self.lock lock];
return; if ([self isReady]) {
}
self.state = AFHTTPOperationExecutingState; self.state = AFHTTPOperationExecutingState;
[self performSelector:@selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:YES modes:[self.runLoopModes allObjects]]; [self performSelector:@selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
}
[self.lock unlock];
} }
- (void)operationDidStart { - (void)operationDidStart {
[self.lock lock];
if ([self isCancelled]) { if ([self isCancelled]) {
[self finish]; [self finish];
return; } else {
}
self.connection = [[[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO] autorelease]; self.connection = [[[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO] autorelease];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
@ -293,6 +318,8 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
} }
[self.connection start]; [self.connection start];
}
[self.lock unlock];
} }
- (void)finish { - (void)finish {
@ -300,15 +327,22 @@ static inline NSString * AFKeyPathFromOperationState(AFOperationState state) {
} }
- (void)cancel { - (void)cancel {
if ([self isFinished]) { [self.lock lock];
return; if (![self isFinished] && ![self isCancelled]) {
}
[super cancel]; [super cancel];
self.cancelled = YES; [self willChangeValueForKey:@"isCancelled"];
_cancelled = YES;
if (self.connection) {
[self.connection cancel]; [self.connection cancel];
// We must send this delegate protcol message ourselves since the above [self.connection cancel] causes the connection to never send another message to its delegate.
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[self.request URL] forKey:NSURLErrorFailingURLErrorKey];
[self performSelector:@selector(connection:didFailWithError:) withObject:self.connection withObject:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:userInfo]];
}
[self didChangeValueForKey:@"isCancelled"];
}
[self.lock unlock];
} }
#pragma mark - NSURLConnectionDelegate #pragma mark - NSURLConnectionDelegate

View file

@ -139,7 +139,7 @@ static dispatch_queue_t xml_request_operation_processing_queue() {
} }
- (NSXMLParser *)responseXMLParser { - (NSXMLParser *)responseXMLParser {
if (!_responseXMLParser && [self isFinished]) { if (!_responseXMLParser && [self.responseData length] > 0 && [self isFinished]) {
self.responseXMLParser = [[[NSXMLParser alloc] initWithData:self.responseData] autorelease]; self.responseXMLParser = [[[NSXMLParser alloc] initWithData:self.responseData] autorelease];
} }
@ -148,7 +148,7 @@ static dispatch_queue_t xml_request_operation_processing_queue() {
#if __MAC_OS_X_VERSION_MIN_REQUIRED #if __MAC_OS_X_VERSION_MIN_REQUIRED
- (NSXMLDocument *)responseXMLDocument { - (NSXMLDocument *)responseXMLDocument {
if (!_responseXMLDocument && [self isFinished]) { if (!_responseXMLDocument && [self.responseData length] > 0 && [self isFinished]) {
NSError *error = nil; NSError *error = nil;
self.responseXMLDocument = [[[NSXMLDocument alloc] initWithData:self.responseData options:0 error:&error] autorelease]; self.responseXMLDocument = [[[NSXMLDocument alloc] initWithData:self.responseData options:0 error:&error] autorelease];
self.error = error; self.error = error;

View file

@ -24,10 +24,20 @@
#import <objc/runtime.h> #import <objc/runtime.h>
#if __IPHONE_OS_VERSION_MIN_REQUIRED #if __IPHONE_OS_VERSION_MIN_REQUIRED
#import "UIImageView+AFNetworking.h" #import "UIImageView+AFNetworking.h"
#import "AFImageCache.h" @interface AFImageCache : NSCache
@property (nonatomic, assign) CGFloat imageScale;
- (UIImage *)cachedImageForURL:(NSURL *)url
cacheName:(NSString *)cacheName;
- (void)cacheImageData:(NSData *)imageData
forURL:(NSURL *)url
cacheName:(NSString *)cacheName;
@end
#pragma mark -
static char kAFImageRequestOperationObjectKey; static char kAFImageRequestOperationObjectKey;
@ -52,14 +62,24 @@ static char kAFImageRequestOperationObjectKey;
} }
+ (NSOperationQueue *)af_sharedImageRequestOperationQueue { + (NSOperationQueue *)af_sharedImageRequestOperationQueue {
static NSOperationQueue *_imageRequestOperationQueue = nil; static NSOperationQueue *_af_imageRequestOperationQueue = nil;
if (!_imageRequestOperationQueue) { if (!_af_imageRequestOperationQueue) {
_imageRequestOperationQueue = [[NSOperationQueue alloc] init]; _af_imageRequestOperationQueue = [[NSOperationQueue alloc] init];
[_imageRequestOperationQueue setMaxConcurrentOperationCount:8]; [_af_imageRequestOperationQueue setMaxConcurrentOperationCount:8];
} }
return _imageRequestOperationQueue; return _af_imageRequestOperationQueue;
}
+ (AFImageCache *)af_sharedImageCache {
static AFImageCache *_af_imageCache = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_af_imageCache = [[AFImageCache alloc] init];
});
return _af_imageCache;
} }
#pragma mark - #pragma mark -
@ -89,7 +109,7 @@ static char kAFImageRequestOperationObjectKey;
[self cancelImageRequestOperation]; [self cancelImageRequestOperation];
} }
UIImage *cachedImage = [[AFImageCache sharedImageCache] cachedImageForURL:[urlRequest URL] cacheName:nil]; UIImage *cachedImage = [[[self class] af_sharedImageCache] cachedImageForURL:[urlRequest URL] cacheName:nil];
if (cachedImage) { if (cachedImage) {
self.image = cachedImage; self.image = cachedImage;
self.af_imageRequestOperation = nil; self.af_imageRequestOperation = nil;
@ -104,15 +124,13 @@ static char kAFImageRequestOperationObjectKey;
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) { if ([[urlRequest URL] isEqual:[[self.af_imageRequestOperation request] URL]]) {
self.image = responseObject; self.image = responseObject;
} else {
self.image = placeholderImage;
} }
if (success) { if (success) {
success(operation.request, operation.response, responseObject); success(operation.request, operation.response, responseObject);
} }
[[AFImageCache sharedImageCache] cacheImageData:operation.responseData forURL:[urlRequest URL] cacheName:nil]; [[[self class] af_sharedImageCache] cacheImageData:operation.responseData forURL:[urlRequest URL] cacheName:nil];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (failure) { if (failure) {
failure(operation.request, operation.response, error); failure(operation.request, operation.response, error);
@ -131,4 +149,43 @@ static char kAFImageRequestOperationObjectKey;
@end @end
#pragma mark -
static inline NSString * AFImageCacheKeyFromURLAndCacheName(NSURL *url, NSString *cacheName) {
return [[url absoluteString] stringByAppendingFormat:@"#%@", cacheName];
}
@implementation AFImageCache
@synthesize imageScale = _imageScale;
- (id)init {
self = [super init];
if (!self) {
return nil;
}
self.imageScale = [[UIScreen mainScreen] scale];
return self;
}
- (UIImage *)cachedImageForURL:(NSURL *)url
cacheName:(NSString *)cacheName
{
UIImage *image = [UIImage imageWithData:[self objectForKey:AFImageCacheKeyFromURLAndCacheName(url, cacheName)]];
if (image) {
return [UIImage imageWithCGImage:[image CGImage] scale:self.imageScale orientation:image.imageOrientation];
}
return image;
}
- (void)cacheImageData:(NSData *)imageData
forURL:(NSURL *)url
cacheName:(NSString *)cacheName
{
[self setObject:[NSPurgeableData dataWithData:imageData] forKey:AFImageCacheKeyFromURLAndCacheName(url, cacheName)];
}
@end
#endif #endif

57
CHANGES Normal file
View file

@ -0,0 +1,57 @@
= 0.9.0 / 2012-01-23
* Add thread-safe behavior to `AFURLConnectionOperation` (Mattt Thompson)
* Add batching of operations for `AFHTTPClient` (Mattt Thompson)
* Add authentication challenge callback block to override default implementation of `connection:didReceiveAuthenticationChallenge:` in `AFURLConnectionOperation` (Mattt Thompson)
* Add `_AFNETWORKING_PREFER_NSJSONSERIALIZATION_`, which, when defined, short-circuits the standard preference ordering used in `AFJSONEncode` and `AFJSONDecode` to use `NSJSONSerialization` when available, falling back on third-party-libraries. (Mattt Thompson, Shane Vitarana)
* Add custom `description` for `AFURLConnectionOperation` and `AFHTTPClient` (Mattt Thompson)
* Add `text/javascript` to default acceptable content types for `AFJSONRequestOperation` (Jake Boxer)
* Add `imageScale` property to change resolution of images constructed from cached data (Štěpán Petrů)
* Add note about third party JSON libraries in README (David Keegan)
* `AFQueryStringFromParametersWithEncoding` formats `NSArray` values in the form `key[]=value1&key[]=value2` instead of `key=(value1,value2)` (Dan Thorpe)
* `AFImageRequestOperation -responseImage` on OS X uses `NSBitmapImageRep` to determine the correct pixel dimensions of the image (David Keegan)
* `AFURLConnectionOperation` `connection` has memory management policy `assign` to avoid retain cycles caused by `NSURLConnection` retaining its delegate (Mattt Thompson)
* `AFURLConnectionOperation` calls super implementation for `-isReady`, following the guidelines for `NSOperation` subclasses (Mattt Thompson)
* `UIImageView -setImageWithURL:` and related methods call success callback after setting image (Cameron Boehmer)
* Cancel request if an authentication challenge has no suitable credentials in `AFURLConnectionOperation -connection:didReceiveAuthenticationChallenge:` (Jorge Bernal)
* Remove exception from `multipartFormRequestWithMethod:path:parameters:constructingBodyWithBlock:` raised when certain HTTP methods are used. (Mattt Thompson)
* Remove `AFImageCache` from public API, moving it into private implementation of `UIImageView+AFNetworking` (Mattt Thompson)
* Mac example application makes better use of AppKit technologies and conventions (Mattt Thompson)
* Fix issue with multipart form boundaries in `AFHTTPClient -multipartFormRequestWithMethod:path:parameters:constructingBodyWithBlock:` (Ray Morgan, Mattt Thompson, Sam Soffes)
* Fix "File Upload with Progress Callback" code snippet in README (Larry Legend)
* Fix to SBJSON invocations in `AFJSONEncode` and `AFJSONDecode` (Matthias Tretter, James Frye)
* Fix documentation for `AFHTTPClient requestWithMethod:path:parameters:` (Michael Parker)
* Fix `Content-Disposition` headers used for multipart form construction (Michael Parker)
* Add network reachability status change callback property to `AFHTTPClient`. (Mattt Thompson, Kevin Harwood)
* Fix exception handling in `AFJSONEncode` and `AFJSONDecode` (David Keegan)
* Fix `NSData` initialization with string in `AFBase64EncodedStringFromString` (Adam Ernst, Mattt Thompson)
* Fix error check in `appendPartWithFileURL:name:error:` (Warren Moore, Baldoph, Mattt Thompson)
* Fix compiler warnings for certain configurations (Charlie Williams)
* Fix bug caused by passing zero-length `responseData` to response object initializers (Mattt Thompson, Serge Paquet)

View file

@ -7,6 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
F8689A9C14CC9F780087F357 /* AFJSONUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = F8689A9B14CC9F780087F357 /* AFJSONUtilities.m */; };
F87A159F1444926300318955 /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F87A159E1444926300318955 /* AFURLConnectionOperation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; F87A159F1444926300318955 /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F87A159E1444926300318955 /* AFURLConnectionOperation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
F87A15A21444926A00318955 /* AFXMLRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F87A15A11444926900318955 /* AFXMLRequestOperation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; F87A15A21444926A00318955 /* AFXMLRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F87A15A11444926900318955 /* AFXMLRequestOperation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
F87A15A51444927300318955 /* AFPropertyListRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F87A15A41444927300318955 /* AFPropertyListRequestOperation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; F87A15A51444927300318955 /* AFPropertyListRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F87A15A41444927300318955 /* AFPropertyListRequestOperation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
@ -17,7 +18,6 @@
F87A15DD1444A86600318955 /* placeholder-stamp.png in Resources */ = {isa = PBXBuildFile; fileRef = F87A15DB1444A86600318955 /* placeholder-stamp.png */; }; F87A15DD1444A86600318955 /* placeholder-stamp.png in Resources */ = {isa = PBXBuildFile; fileRef = F87A15DB1444A86600318955 /* placeholder-stamp.png */; };
F897DE78142CFEDC000DDD35 /* AFHTTPClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F897DE6A142CFEDC000DDD35 /* AFHTTPClient.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; F897DE78142CFEDC000DDD35 /* AFHTTPClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F897DE6A142CFEDC000DDD35 /* AFHTTPClient.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
F897DE79142CFEDC000DDD35 /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F897DE6C142CFEDC000DDD35 /* AFHTTPRequestOperation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; F897DE79142CFEDC000DDD35 /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F897DE6C142CFEDC000DDD35 /* AFHTTPRequestOperation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
F897DE7A142CFEDC000DDD35 /* AFImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F897DE6E142CFEDC000DDD35 /* AFImageCache.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
F897DE7B142CFEDC000DDD35 /* AFImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F897DE70142CFEDC000DDD35 /* AFImageRequestOperation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; F897DE7B142CFEDC000DDD35 /* AFImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F897DE70142CFEDC000DDD35 /* AFImageRequestOperation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
F897DE7C142CFEDC000DDD35 /* AFJSONRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F897DE72142CFEDC000DDD35 /* AFJSONRequestOperation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; F897DE7C142CFEDC000DDD35 /* AFJSONRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F897DE72142CFEDC000DDD35 /* AFJSONRequestOperation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
F8A27AC7142CFE1300F5E0D6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A27AB2142CFE1300F5E0D6 /* AppDelegate.m */; }; F8A27AC7142CFE1300F5E0D6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F8A27AB2142CFE1300F5E0D6 /* AppDelegate.m */; };
@ -30,6 +30,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
F8323C901455B4FE00190CCB /* AFJSONUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFJSONUtilities.h; sourceTree = "<group>"; }; F8323C901455B4FE00190CCB /* AFJSONUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFJSONUtilities.h; sourceTree = "<group>"; };
F8689A9B14CC9F780087F357 /* AFJSONUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFJSONUtilities.m; sourceTree = "<group>"; };
F87A159D1444926300318955 /* AFURLConnectionOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLConnectionOperation.h; sourceTree = "<group>"; }; F87A159D1444926300318955 /* AFURLConnectionOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLConnectionOperation.h; sourceTree = "<group>"; };
F87A159E1444926300318955 /* AFURLConnectionOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLConnectionOperation.m; sourceTree = "<group>"; }; F87A159E1444926300318955 /* AFURLConnectionOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLConnectionOperation.m; sourceTree = "<group>"; };
F87A15A01444926900318955 /* AFXMLRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFXMLRequestOperation.h; sourceTree = "<group>"; }; F87A15A01444926900318955 /* AFXMLRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFXMLRequestOperation.h; sourceTree = "<group>"; };
@ -48,8 +49,6 @@
F897DE6A142CFEDC000DDD35 /* AFHTTPClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPClient.m; sourceTree = "<group>"; }; F897DE6A142CFEDC000DDD35 /* AFHTTPClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPClient.m; sourceTree = "<group>"; };
F897DE6B142CFEDC000DDD35 /* AFHTTPRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPRequestOperation.h; sourceTree = "<group>"; }; F897DE6B142CFEDC000DDD35 /* AFHTTPRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPRequestOperation.h; sourceTree = "<group>"; };
F897DE6C142CFEDC000DDD35 /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperation.m; sourceTree = "<group>"; }; F897DE6C142CFEDC000DDD35 /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperation.m; sourceTree = "<group>"; };
F897DE6D142CFEDC000DDD35 /* AFImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFImageCache.h; sourceTree = "<group>"; };
F897DE6E142CFEDC000DDD35 /* AFImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFImageCache.m; sourceTree = "<group>"; };
F897DE6F142CFEDC000DDD35 /* AFImageRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFImageRequestOperation.h; sourceTree = "<group>"; }; F897DE6F142CFEDC000DDD35 /* AFImageRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFImageRequestOperation.h; sourceTree = "<group>"; };
F897DE70142CFEDC000DDD35 /* AFImageRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFImageRequestOperation.m; sourceTree = "<group>"; }; F897DE70142CFEDC000DDD35 /* AFImageRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFImageRequestOperation.m; sourceTree = "<group>"; };
F897DE71142CFEDC000DDD35 /* AFJSONRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFJSONRequestOperation.h; sourceTree = "<group>"; }; F897DE71142CFEDC000DDD35 /* AFJSONRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFJSONRequestOperation.h; sourceTree = "<group>"; };
@ -139,9 +138,8 @@
F897DE6A142CFEDC000DDD35 /* AFHTTPClient.m */, F897DE6A142CFEDC000DDD35 /* AFHTTPClient.m */,
F897DE6F142CFEDC000DDD35 /* AFImageRequestOperation.h */, F897DE6F142CFEDC000DDD35 /* AFImageRequestOperation.h */,
F897DE70142CFEDC000DDD35 /* AFImageRequestOperation.m */, F897DE70142CFEDC000DDD35 /* AFImageRequestOperation.m */,
F897DE6D142CFEDC000DDD35 /* AFImageCache.h */,
F897DE6E142CFEDC000DDD35 /* AFImageCache.m */,
F8323C901455B4FE00190CCB /* AFJSONUtilities.h */, F8323C901455B4FE00190CCB /* AFJSONUtilities.h */,
F8689A9B14CC9F780087F357 /* AFJSONUtilities.m */,
); );
name = AFNetworking; name = AFNetworking;
path = ../../AFNetworking; path = ../../AFNetworking;
@ -288,7 +286,6 @@
F8A27ACB142CFE1300F5E0D6 /* JSONKit.m in Sources */, F8A27ACB142CFE1300F5E0D6 /* JSONKit.m in Sources */,
F897DE78142CFEDC000DDD35 /* AFHTTPClient.m in Sources */, F897DE78142CFEDC000DDD35 /* AFHTTPClient.m in Sources */,
F897DE79142CFEDC000DDD35 /* AFHTTPRequestOperation.m in Sources */, F897DE79142CFEDC000DDD35 /* AFHTTPRequestOperation.m in Sources */,
F897DE7A142CFEDC000DDD35 /* AFImageCache.m in Sources */,
F897DE7B142CFEDC000DDD35 /* AFImageRequestOperation.m in Sources */, F897DE7B142CFEDC000DDD35 /* AFImageRequestOperation.m in Sources */,
F897DE7C142CFEDC000DDD35 /* AFJSONRequestOperation.m in Sources */, F897DE7C142CFEDC000DDD35 /* AFJSONRequestOperation.m in Sources */,
F87A159F1444926300318955 /* AFURLConnectionOperation.m in Sources */, F87A159F1444926300318955 /* AFURLConnectionOperation.m in Sources */,
@ -297,6 +294,7 @@
F87A15CD1444A30800318955 /* AFGowallaAPIClient.m in Sources */, F87A15CD1444A30800318955 /* AFGowallaAPIClient.m in Sources */,
F87A15CE1444A30800318955 /* NearbySpotsController.m in Sources */, F87A15CE1444A30800318955 /* NearbySpotsController.m in Sources */,
F87A15CF1444A30800318955 /* Spot.m in Sources */, F87A15CF1444A30800318955 /* Spot.m in Sources */,
F8689A9C14CC9F780087F357 /* AFJSONUtilities.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View file

@ -251,7 +251,7 @@
<object class="NSWindowTemplate" id="972006081"> <object class="NSWindowTemplate" id="972006081">
<int key="NSWindowStyleMask">15</int> <int key="NSWindowStyleMask">15</int>
<int key="NSWindowBacking">2</int> <int key="NSWindowBacking">2</int>
<string key="NSWindowRect">{{50, 538}, {375, 500}}</string> <string key="NSWindowRect">{{60, 295}, {375, 500}}</string>
<int key="NSWTFlags">1954021376</int> <int key="NSWTFlags">1954021376</int>
<string key="NSWindowTitle">AFNetworking Mac Example</string> <string key="NSWindowTitle">AFNetworking Mac Example</string>
<string key="NSWindowClass">NSWindow</string> <string key="NSWindowClass">NSWindow</string>
@ -439,7 +439,6 @@
<string key="NSFrame">{{1, 526}, {374, 15}}</string> <string key="NSFrame">{{1, 526}, {374, 15}}</string>
<reference key="NSSuperview" ref="905625827"/> <reference key="NSSuperview" ref="905625827"/>
<reference key="NSWindow"/> <reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:1216</string> <string key="NSReuseIdentifierKey">_NS:1216</string>
<int key="NSsFlags">1</int> <int key="NSsFlags">1</int>
<reference key="NSTarget" ref="905625827"/> <reference key="NSTarget" ref="905625827"/>

View file

@ -7,9 +7,9 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
F8689A9914CC9F5E0087F357 /* AFJSONUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = F8689A9814CC9F5E0087F357 /* AFJSONUtilities.m */; };
F86E5529143A28F3002B438C /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F86E5528143A28F3002B438C /* AFURLConnectionOperation.m */; }; F86E5529143A28F3002B438C /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F86E5528143A28F3002B438C /* AFURLConnectionOperation.m */; };
F874B5D913E0AA6500B28E3E /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */; }; F874B5D913E0AA6500B28E3E /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */; };
F874B5DA13E0AA6500B28E3E /* AFImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CA13E0AA6500B28E3E /* AFImageCache.m */; };
F874B5DB13E0AA6500B28E3E /* AFImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */; }; F874B5DB13E0AA6500B28E3E /* AFImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */; };
F874B5DC13E0AA6500B28E3E /* AFJSONRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CC13E0AA6500B28E3E /* AFJSONRequestOperation.m */; }; F874B5DC13E0AA6500B28E3E /* AFJSONRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CC13E0AA6500B28E3E /* AFJSONRequestOperation.m */; };
F874B5DD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m */; }; F874B5DD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F874B5CD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m */; };
@ -41,16 +41,15 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
F8323C941455C03400190CCB /* AFJSONUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFJSONUtilities.h; path = ../AFNetworking/AFJSONUtilities.h; sourceTree = "<group>"; }; F8323C941455C03400190CCB /* AFJSONUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFJSONUtilities.h; path = ../AFNetworking/AFJSONUtilities.h; sourceTree = "<group>"; };
F8689A9814CC9F5E0087F357 /* AFJSONUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFJSONUtilities.m; path = ../AFNetworking/AFJSONUtilities.m; sourceTree = "<group>"; };
F86E5527143A28F3002B438C /* AFURLConnectionOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFURLConnectionOperation.h; path = ../AFNetworking/AFURLConnectionOperation.h; sourceTree = "<group>"; }; F86E5527143A28F3002B438C /* AFURLConnectionOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFURLConnectionOperation.h; path = ../AFNetworking/AFURLConnectionOperation.h; sourceTree = "<group>"; };
F86E5528143A28F3002B438C /* AFURLConnectionOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFURLConnectionOperation.m; path = ../AFNetworking/AFURLConnectionOperation.m; sourceTree = "<group>"; }; F86E5528143A28F3002B438C /* AFURLConnectionOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFURLConnectionOperation.m; path = ../AFNetworking/AFURLConnectionOperation.m; sourceTree = "<group>"; };
F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFHTTPRequestOperation.m; path = ../AFNetworking/AFHTTPRequestOperation.m; sourceTree = "<group>"; }; F874B5C913E0AA6500B28E3E /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFHTTPRequestOperation.m; path = ../AFNetworking/AFHTTPRequestOperation.m; sourceTree = "<group>"; };
F874B5CA13E0AA6500B28E3E /* AFImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageCache.m; path = ../AFNetworking/AFImageCache.m; sourceTree = "<group>"; };
F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageRequestOperation.m; path = ../AFNetworking/AFImageRequestOperation.m; sourceTree = "<group>"; }; F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFImageRequestOperation.m; path = ../AFNetworking/AFImageRequestOperation.m; sourceTree = "<group>"; };
F874B5CC13E0AA6500B28E3E /* AFJSONRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFJSONRequestOperation.m; path = ../AFNetworking/AFJSONRequestOperation.m; sourceTree = "<group>"; }; F874B5CC13E0AA6500B28E3E /* AFJSONRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFJSONRequestOperation.m; path = ../AFNetworking/AFJSONRequestOperation.m; sourceTree = "<group>"; };
F874B5CD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFNetworkActivityIndicatorManager.m; path = ../AFNetworking/AFNetworkActivityIndicatorManager.m; sourceTree = "<group>"; }; F874B5CD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AFNetworkActivityIndicatorManager.m; path = ../AFNetworking/AFNetworkActivityIndicatorManager.m; sourceTree = "<group>"; };
F874B5D013E0AA6500B28E3E /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+AFNetworking.m"; path = "../AFNetworking/UIImageView+AFNetworking.m"; sourceTree = "<group>"; }; F874B5D013E0AA6500B28E3E /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+AFNetworking.m"; path = "../AFNetworking/UIImageView+AFNetworking.m"; sourceTree = "<group>"; };
F874B5D113E0AA6500B28E3E /* AFHTTPRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFHTTPRequestOperation.h; path = ../AFNetworking/AFHTTPRequestOperation.h; sourceTree = "<group>"; }; F874B5D113E0AA6500B28E3E /* AFHTTPRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFHTTPRequestOperation.h; path = ../AFNetworking/AFHTTPRequestOperation.h; sourceTree = "<group>"; };
F874B5D213E0AA6500B28E3E /* AFImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFImageCache.h; path = ../AFNetworking/AFImageCache.h; sourceTree = "<group>"; };
F874B5D313E0AA6500B28E3E /* AFImageRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFImageRequestOperation.h; path = ../AFNetworking/AFImageRequestOperation.h; sourceTree = "<group>"; }; F874B5D313E0AA6500B28E3E /* AFImageRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFImageRequestOperation.h; path = ../AFNetworking/AFImageRequestOperation.h; sourceTree = "<group>"; };
F874B5D413E0AA6500B28E3E /* AFJSONRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFJSONRequestOperation.h; path = ../AFNetworking/AFJSONRequestOperation.h; sourceTree = "<group>"; }; F874B5D413E0AA6500B28E3E /* AFJSONRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFJSONRequestOperation.h; path = ../AFNetworking/AFJSONRequestOperation.h; sourceTree = "<group>"; };
F874B5D513E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFNetworkActivityIndicatorManager.h; path = ../AFNetworking/AFNetworkActivityIndicatorManager.h; sourceTree = "<group>"; }; F874B5D513E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AFNetworkActivityIndicatorManager.h; path = ../AFNetworking/AFNetworkActivityIndicatorManager.h; sourceTree = "<group>"; };
@ -246,13 +245,12 @@
F8FBFA97142AA238001409DB /* AFHTTPClient.m */, F8FBFA97142AA238001409DB /* AFHTTPClient.m */,
F874B5D313E0AA6500B28E3E /* AFImageRequestOperation.h */, F874B5D313E0AA6500B28E3E /* AFImageRequestOperation.h */,
F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */, F874B5CB13E0AA6500B28E3E /* AFImageRequestOperation.m */,
F874B5D213E0AA6500B28E3E /* AFImageCache.h */,
F874B5CA13E0AA6500B28E3E /* AFImageCache.m */,
F874B5D813E0AA6500B28E3E /* UIImageView+AFNetworking.h */, F874B5D813E0AA6500B28E3E /* UIImageView+AFNetworking.h */,
F874B5D013E0AA6500B28E3E /* UIImageView+AFNetworking.m */, F874B5D013E0AA6500B28E3E /* UIImageView+AFNetworking.m */,
F874B5D513E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.h */, F874B5D513E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.h */,
F874B5CD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m */, F874B5CD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m */,
F8323C941455C03400190CCB /* AFJSONUtilities.h */, F8323C941455C03400190CCB /* AFJSONUtilities.h */,
F8689A9814CC9F5E0087F357 /* AFJSONUtilities.m */,
); );
name = AFNetworking; name = AFNetworking;
sourceTree = "<group>"; sourceTree = "<group>";
@ -356,7 +354,6 @@
F8DA09E41396AC040057D0CC /* main.m in Sources */, F8DA09E41396AC040057D0CC /* main.m in Sources */,
F8DA09E81396AC220057D0CC /* AppDelegate.m in Sources */, F8DA09E81396AC220057D0CC /* AppDelegate.m in Sources */,
F874B5D913E0AA6500B28E3E /* AFHTTPRequestOperation.m in Sources */, F874B5D913E0AA6500B28E3E /* AFHTTPRequestOperation.m in Sources */,
F874B5DA13E0AA6500B28E3E /* AFImageCache.m in Sources */,
F874B5DB13E0AA6500B28E3E /* AFImageRequestOperation.m in Sources */, F874B5DB13E0AA6500B28E3E /* AFImageRequestOperation.m in Sources */,
F874B5DC13E0AA6500B28E3E /* AFJSONRequestOperation.m in Sources */, F874B5DC13E0AA6500B28E3E /* AFJSONRequestOperation.m in Sources */,
F874B5DD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m in Sources */, F874B5DD13E0AA6500B28E3E /* AFNetworkActivityIndicatorManager.m in Sources */,
@ -365,6 +362,7 @@
F86E5529143A28F3002B438C /* AFURLConnectionOperation.m in Sources */, F86E5529143A28F3002B438C /* AFURLConnectionOperation.m in Sources */,
F8F4B16E143CD1420064C9E6 /* AFPropertyListRequestOperation.m in Sources */, F8F4B16E143CD1420064C9E6 /* AFPropertyListRequestOperation.m in Sources */,
F8F4B17F143E07030064C9E6 /* AFXMLRequestOperation.m in Sources */, F8F4B17F143E07030064C9E6 /* AFXMLRequestOperation.m in Sources */,
F8689A9914CC9F5E0087F357 /* AFJSONUtilities.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View file

@ -27,7 +27,6 @@
#import "SpotTableViewCell.h" #import "SpotTableViewCell.h"
#import "TTTLocationFormatter.h" #import "TTTLocationFormatter.h"
#import "AFImageCache.h"
#import "UIImageView+AFNetworking.h" #import "UIImageView+AFNetworking.h"
@interface NearbySpotsViewController () @interface NearbySpotsViewController ()
@ -123,7 +122,6 @@
self.nearbySpots = [NSArray array]; self.nearbySpots = [NSArray array];
[self.tableView reloadData]; [self.tableView reloadData];
[[NSURLCache sharedURLCache] removeAllCachedResponses]; [[NSURLCache sharedURLCache] removeAllCachedResponses];
[[AFImageCache sharedImageCache] removeAllObjects];
if (self.locationManager.location) { if (self.locationManager.location) {
[self loadSpotsForLocation:self.locationManager.location]; [self loadSpotsForLocation:self.locationManager.location];

View file

@ -7,4 +7,5 @@
#ifdef __OBJC__ #ifdef __OBJC__
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#endif #endif