-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Added AFNetworking using CocoaPods, JBMessage.
- Loading branch information
Josip Bernat
committed
Mar 26, 2014
1 parent
233b2cc
commit 572145d
Showing
2 changed files
with
384 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
// | ||
// VCMessage.h | ||
// VectorChat | ||
// | ||
// Created by Josip Bernat on 25/03/14. | ||
// Copyright (c) 2014 Josip-Bernat. All rights reserved. | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
typedef NSString *JBHTTPMethod; | ||
|
||
extern JBHTTPMethod const JBHTTPMethodGET; | ||
extern JBHTTPMethod const JBHTTPMethodPOST; | ||
extern JBHTTPMethod const JBHTTPMethodPUT; | ||
extern JBHTTPMethod const JBHTTPMethodDELETE; | ||
|
||
/** | ||
* Response block object can be a single model or a collection depending on the message. | ||
*/ | ||
typedef void (^JBResponseBlock)(id responseObject, NSError *error); | ||
|
||
/** | ||
* Upload block object containing information about upload progress. Can be called multiple times during the upload. | ||
*/ | ||
typedef void (^JBUploadBlock)(NSUInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite); | ||
|
||
@interface JBMessage : NSOperation | ||
|
||
/** | ||
* Response block to be called once the request finishes. | ||
*/ | ||
@property (copy) JBResponseBlock responseBlock; | ||
|
||
/** | ||
* Upload block object called when upload sends bytes. Can be called multiply times during the upload. | ||
*/ | ||
@property (copy) JBUploadBlock uploadBlock; | ||
|
||
/** | ||
* Action for the request, i.e login.php. | ||
*/ | ||
@property (nonatomic, copy) NSString *action; | ||
|
||
/** | ||
* HTTP method for the request. Default is JBHTTPMethodPOST. | ||
*/ | ||
@property (nonatomic, readwrite) JBHTTPMethod httpMethod; | ||
|
||
/** | ||
* Determents whether response block should be called on main queue or not. Setting to NO enables you to do heavy parsing on background queue. Default is YES. | ||
*/ | ||
@property (nonatomic, readwrite) BOOL shouldCompleteOnMainQueue; | ||
|
||
/** | ||
* A file URL for the multipart request. | ||
*/ | ||
@property (nonatomic, copy) NSURL *fileURL; | ||
|
||
/** | ||
* A filename field used in multpart request. Default is "filename". | ||
*/ | ||
@property (nonatomic, copy) NSString *filename; | ||
|
||
/** | ||
* Parameters to be send in the request. | ||
*/ | ||
@property (nonatomic, strong, readonly) NSDictionary *parameters; | ||
|
||
#pragma mark - URL Registration | ||
|
||
/** | ||
* Register baseUrl in order to enable request execution. The easiest way is to call it directly from application:didFinishLaunchingWithOptions:. | ||
* | ||
* @param baseUrl Url to register, i.e. http://example.com/api/. | ||
*/ | ||
+ (void)registerBaseUrl:(NSString *)baseUrl; | ||
|
||
#pragma mark - Initialization | ||
|
||
/** | ||
* Initializes the message with parameters | ||
* | ||
* @param parameters Web service parameters to be sent. | ||
* @param responseBlock Response callback. Will contain parsed objects depending on the message or an error if there was one. | ||
* | ||
* @return an instance of VCMessage | ||
*/ | ||
+ (instancetype)messageWithParameters:(NSDictionary *) parameters | ||
responseBlock:(JBResponseBlock) responseBlock; | ||
|
||
/** | ||
* Initializes the message with parameters | ||
* | ||
* @param parameters Web service parameters to be sent. | ||
* @param responseBlock Response callback. Will contain parsed objects depending on the message or an error if there was one. | ||
* | ||
* @return an instance of VCMessage | ||
*/ | ||
- (id)initWithParameters:(NSDictionary *)parameters | ||
responseBlock:(JBResponseBlock) responseBlock; | ||
|
||
#pragma mark - Parsing Response | ||
/** | ||
* Parses the raw response from the server and returns a callback. | ||
* | ||
* @param rawResponse Raw server response. | ||
* @param error Error generated by parsing. | ||
* | ||
* @return returns RawResponse if JSON parsing fails by default. Override in subclasses to return other object types. | ||
*/ | ||
- (id)parseResponse:(id)rawResponse error:(NSError **) error; | ||
|
||
@end | ||
|
||
@interface JBMessage (JBMessageCenter) | ||
|
||
/** | ||
* Enqueues message on message center and starts server communication. Uses shared operationQueue. Override this method in your subclass in case you need to use some other operation queue. | ||
*/ | ||
- (void)send; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,261 @@ | ||
// | ||
// VCMessage.m | ||
// VectorChat | ||
// | ||
// Created by Josip Bernat on 25/03/14. | ||
// Copyright (c) 2014 Josip-Bernat. All rights reserved. | ||
// | ||
|
||
#import "JBMessage.h" | ||
#import "AFHTTPRequestOperationManager.h" | ||
|
||
JBHTTPMethod const JBHTTPMethodGET = @"GET"; | ||
JBHTTPMethod const JBHTTPMethodPOST = @"POST"; | ||
JBHTTPMethod const JBHTTPMethodPUT = @"PUT"; | ||
JBHTTPMethod const JBHTTPMethodDELETE = @"DELETE"; | ||
|
||
@interface JBMessage () { | ||
|
||
BOOL _isCancelled; | ||
BOOL _isFinished; | ||
BOOL _isExecuting; | ||
} | ||
|
||
@property (nonatomic) UIBackgroundTaskIdentifier backgroundTaskIdentifier; | ||
@property (nonatomic, strong) NSDictionary *parameters; | ||
|
||
@end | ||
|
||
@implementation JBMessage | ||
|
||
#pragma mark - Memory Management | ||
|
||
- (void) dealloc { | ||
_responseBlock = nil; | ||
_uploadBlock = nil; | ||
} | ||
|
||
#pragma mark - URL Registration | ||
|
||
static NSString *baseUrlString = nil; | ||
+ (void)registerBaseUrl:(NSString *)baseUrl { | ||
|
||
static dispatch_once_t onceToken; | ||
dispatch_once(&onceToken, ^{ | ||
baseUrlString = baseUrl; | ||
}); | ||
} | ||
|
||
#pragma mark - Initialization | ||
|
||
+ (instancetype)messageWithParameters:(NSDictionary *) parameters | ||
responseBlock:(JBResponseBlock) responseBlock { | ||
|
||
JBMessage *message = [[self alloc] initWithParameters:parameters | ||
responseBlock:responseBlock]; | ||
return message; | ||
} | ||
|
||
- (id)initWithParameters:(NSDictionary *)parameters | ||
responseBlock:(JBResponseBlock)responseBlock { | ||
|
||
if (self = [super init]) { | ||
|
||
self.parameters = parameters; | ||
self.responseBlock = responseBlock; | ||
|
||
_filename = @"filename"; | ||
_fileURL = nil; | ||
_httpMethod = JBHTTPMethodPOST; | ||
_shouldCompleteOnMainQueue = YES; | ||
} | ||
|
||
return self; | ||
} | ||
|
||
#pragma mark - Background Task | ||
|
||
- (void)beginBackgroundTask { | ||
|
||
self.backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ | ||
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier]; | ||
self.backgroundTaskIdentifier = UIBackgroundTaskInvalid; | ||
}]; | ||
} | ||
|
||
- (void)endBackgroundTask { | ||
|
||
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier]; | ||
self.backgroundTaskIdentifier = UIBackgroundTaskInvalid; | ||
} | ||
|
||
#pragma mark - Operations | ||
|
||
-(void) start { | ||
|
||
_isExecuting = YES; | ||
_isFinished = NO; | ||
|
||
[self executeRequest]; | ||
} | ||
|
||
- (void) finish { | ||
[self endBackgroundTask]; | ||
} | ||
|
||
- (void) cancel { | ||
_isCancelled = YES; | ||
} | ||
|
||
- (BOOL) isConcurrent { | ||
return YES; | ||
} | ||
|
||
- (BOOL) isExecuting { | ||
return _isExecuting; | ||
} | ||
|
||
- (BOOL) isFinished { | ||
return _isFinished; | ||
} | ||
|
||
- (void)operationDidFinish { | ||
|
||
if (!_isExecuting) return; | ||
[self willChangeValueForKey:@"isExecuting"]; | ||
_isExecuting = NO; | ||
[self didChangeValueForKey:@"isExecuting"]; | ||
|
||
[self willChangeValueForKey:@"isFinished"]; | ||
_isFinished = YES; | ||
[self didChangeValueForKey:@"isFinished"]; | ||
|
||
[self finish]; | ||
} | ||
|
||
#pragma mark - Executing Request | ||
|
||
- (void)executeRequest { | ||
|
||
__block NSError *uploadError = nil; | ||
|
||
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; | ||
|
||
__weak id this = self; | ||
|
||
NSMutableURLRequest *request = nil; | ||
|
||
NSString *urlString = [NSString stringWithFormat:@"%@%@", baseUrlString, self.action]; | ||
if (self.httpMethod == JBHTTPMethodGET || !self.fileURL) { | ||
|
||
NSError *error = nil; | ||
request = [manager.requestSerializer requestWithMethod:self.httpMethod | ||
URLString:urlString | ||
parameters:self.parameters | ||
error:&error]; | ||
#ifdef DEBUG | ||
if (error) { | ||
NSLog(@"Error while creating NSMutableRequest: %@", error); | ||
} | ||
#endif | ||
} | ||
else { | ||
|
||
request = [manager.requestSerializer multipartFormRequestWithMethod:self.httpMethod | ||
URLString:urlString | ||
parameters:[self parameters] | ||
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { | ||
|
||
__strong JBMessage *strongThis = this; | ||
[formData appendPartWithFileURL:strongThis.fileURL | ||
name:strongThis.filename | ||
error:&uploadError]; | ||
} error:nil]; | ||
} | ||
|
||
|
||
AFHTTPRequestOperation *operation = [manager HTTPRequestOperationWithRequest:request | ||
success:^(AFHTTPRequestOperation *operation, id responseObject) { | ||
|
||
__strong JBMessage *strongThis = this; | ||
[strongThis receivedResponse:responseObject error:nil]; | ||
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { | ||
|
||
__strong JBMessage *strongThis = this; | ||
[strongThis receivedResponse:nil error:error]; | ||
}]; | ||
|
||
|
||
[operation setUploadProgressBlock:self.uploadBlock]; | ||
|
||
[manager.operationQueue addOperation:operation]; | ||
} | ||
|
||
#pragma mark - Handling Response | ||
|
||
- (void)receivedResponse:(id)result error:(NSError *)error { | ||
|
||
NSError *parseError = nil; | ||
id parsedObject = nil; | ||
|
||
if (result && !error) { | ||
parsedObject = [self parseResponse:result error:&parseError]; | ||
error = parseError; | ||
} | ||
|
||
if (_shouldCompleteOnMainQueue) { | ||
//return response on the main queue | ||
dispatch_async(dispatch_get_main_queue(), ^{ | ||
self.responseBlock(parsedObject, error); | ||
}); | ||
} | ||
else { | ||
self.responseBlock(parsedObject, error); | ||
} | ||
|
||
[self operationDidFinish]; | ||
} | ||
|
||
|
||
- (id)parseResponse:(id)rawResponse error:(NSError *__autoreleasing *)error{ | ||
|
||
if ([rawResponse isKindOfClass:[NSData class]]) { | ||
|
||
NSError *jsonError = nil; | ||
id response = [NSJSONSerialization JSONObjectWithData:rawResponse | ||
options:0 | ||
error:&jsonError]; | ||
*error = jsonError; | ||
|
||
#ifdef DEBUG | ||
if(jsonError) { | ||
NSLog(@"%@, %@", [jsonError localizedDescription], [[NSString alloc] initWithData:rawResponse encoding:NSUTF8StringEncoding]); | ||
} | ||
#endif | ||
return response; | ||
} | ||
return rawResponse; | ||
} | ||
|
||
@end | ||
|
||
@implementation JBMessage (VCMessageCenter) | ||
|
||
+ (NSOperationQueue *)sharedQueue { | ||
|
||
static NSOperationQueue *queue = nil; | ||
static dispatch_once_t onceToken; | ||
dispatch_once(&onceToken, ^{ | ||
queue = [[NSOperationQueue alloc] init]; | ||
queue.maxConcurrentOperationCount = 1; | ||
}); | ||
|
||
return queue; | ||
} | ||
|
||
- (void)send { | ||
|
||
[[[self class] sharedQueue] addOperation:self]; | ||
} | ||
|
||
@end |