diff --git a/plugin.xml b/plugin.xml index 72ddbb5..b661917 100644 --- a/plugin.xml +++ b/plugin.xml @@ -34,6 +34,7 @@ + @@ -43,6 +44,7 @@ + diff --git a/src/ios/CordovaHttpPlugin.m b/src/ios/CordovaHttpPlugin.m index 8277a27..ddc4517 100644 --- a/src/ios/CordovaHttpPlugin.m +++ b/src/ios/CordovaHttpPlugin.m @@ -3,6 +3,7 @@ #import "TextResponseSerializer.h" #import "TextRequestSerializer.h" #import "AFHTTPSessionManager.h" +#import "SDNetworkActivityIndicator.h" @interface CordovaHttpPlugin() @@ -175,6 +176,7 @@ CordovaHttpPlugin* __weak weakSelf = self; manager.responseSerializer = [TextResponseSerializer serializer]; + [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity]; @try { [manager POST:url parameters:parameters progress:nil success:^(NSURLSessionTask *task, id responseObject) { @@ -183,15 +185,18 @@ CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; } failure:^(NSURLSessionTask *task, NSError *error) { NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error]; CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; }]; } @catch (NSException *exception) { + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; [self handleException:exception withCommand:command]; } } @@ -213,6 +218,7 @@ CordovaHttpPlugin* __weak weakSelf = self; manager.responseSerializer = [TextResponseSerializer serializer]; + [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity]; @try { [manager GET:url parameters:parameters progress:nil success:^(NSURLSessionTask *task, id responseObject) { @@ -221,15 +227,18 @@ CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; } failure:^(NSURLSessionTask *task, NSError *error) { NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error]; CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; }]; } @catch (NSException *exception) { + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; [self handleException:exception withCommand:command]; } } @@ -251,6 +260,7 @@ CordovaHttpPlugin* __weak weakSelf = self; manager.responseSerializer = [TextResponseSerializer serializer]; + [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity]; @try { [manager PUT:url parameters:parameters success:^(NSURLSessionTask *task, id responseObject) { @@ -259,15 +269,18 @@ CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; } failure:^(NSURLSessionTask *task, NSError *error) { NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error]; CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; }]; } @catch (NSException *exception) { + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; [self handleException:exception withCommand:command]; } } @@ -289,6 +302,7 @@ CordovaHttpPlugin* __weak weakSelf = self; manager.responseSerializer = [TextResponseSerializer serializer]; + [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity]; @try { [manager PATCH:url parameters:parameters success:^(NSURLSessionTask *task, id responseObject) { @@ -297,15 +311,18 @@ CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; } failure:^(NSURLSessionTask *task, NSError *error) { NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error]; CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; }]; } @catch (NSException *exception) { + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; [self handleException:exception withCommand:command]; } } @@ -326,6 +343,7 @@ CordovaHttpPlugin* __weak weakSelf = self; manager.responseSerializer = [TextResponseSerializer serializer]; + [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity]; @try { [manager DELETE:url parameters:parameters success:^(NSURLSessionTask *task, id responseObject) { @@ -334,15 +352,18 @@ CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; } failure:^(NSURLSessionTask *task, NSError *error) { NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error]; CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; }]; } @catch (NSException *exception) { + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; [self handleException:exception withCommand:command]; } } @@ -361,6 +382,7 @@ CordovaHttpPlugin* __weak weakSelf = self; manager.responseSerializer = [AFHTTPResponseSerializer serializer]; + [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity]; @try { [manager HEAD:url parameters:parameters success:^(NSURLSessionTask *task) { @@ -370,15 +392,18 @@ CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; } failure:^(NSURLSessionTask *task, NSError *error) { NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error]; CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; }]; } @catch (NSException *exception) { + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; [self handleException:exception withCommand:command]; } } @@ -402,6 +427,7 @@ CordovaHttpPlugin* __weak weakSelf = self; manager.responseSerializer = [TextResponseSerializer serializer]; + [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity]; @try { [manager POST:url parameters:parameters constructingBodyWithBlock:^(id formData) { @@ -413,6 +439,7 @@ [dictionary setObject:@"Could not add file to post body." forKey:@"error"]; CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; return; } } progress:nil success:^(NSURLSessionTask *task, id responseObject) { @@ -421,15 +448,18 @@ CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; } failure:^(NSURLSessionTask *task, NSError *error) { NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error]; CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; }]; } @catch (NSException *exception) { + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; [self handleException:exception withCommand:command]; } } @@ -455,6 +485,7 @@ CordovaHttpPlugin* __weak weakSelf = self; manager.responseSerializer = [AFHTTPResponseSerializer serializer]; + [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity]; @try { [manager GET:url parameters:parameters progress:nil success:^(NSURLSessionTask *task, id responseObject) { @@ -495,6 +526,7 @@ } CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; return; } NSData *data = (NSData *)responseObject; @@ -504,6 +536,7 @@ [dictionary setObject:@"Could not write the data to the given filePath." forKey:@"error"]; CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; return; } @@ -514,6 +547,7 @@ CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; } failure:^(NSURLSessionTask *task, NSError *error) { NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error]; @@ -521,9 +555,11 @@ CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary]; [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; }]; } @catch (NSException *exception) { + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; [self handleException:exception withCommand:command]; } } diff --git a/src/ios/SDNetworkActivityIndicator/LICENSE b/src/ios/SDNetworkActivityIndicator/LICENSE new file mode 100644 index 0000000..6a88659 --- /dev/null +++ b/src/ios/SDNetworkActivityIndicator/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2010 Olivier Poitrey + +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. + diff --git a/src/ios/SDNetworkActivityIndicator/README.md b/src/ios/SDNetworkActivityIndicator/README.md new file mode 100644 index 0000000..1fb11cf --- /dev/null +++ b/src/ios/SDNetworkActivityIndicator/README.md @@ -0,0 +1,52 @@ +# SDNetworkActivityIndicator + +Handle showing / hiding of the iOS network activity indicator to allow multiple concurrent threads to show / hide the indicator such that the indicator remains visible until all the requests have completed and requested the indicator to be hidden. + +## Requirements + +* iOS 5.0 or later. +* ARC memory management. + +## Installation + +The easiest way to install it is by copying the following files to your project: + +* SDNetworkActivityIndicator.h +* SDNetworkActivityIndicator.m + +## Usage + +* When you start a network activity (will show the network activity indicator): + + [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity]; + +* When you finish a network activity (will hide the network activity indicator only if the number of calls to `stopActivity` matches the number of calls to `startActivity`): + + [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity]; + +* To hide the network activity indicator regardless of whether all activities have finished (without having to call `stopActivity` for each `startActivity` called): + + [[SDNetworkActivityIndicator sharedActivityIndicator] stopAllActivity]; + + +## License +Copyright (c) 2010 Olivier Poitrey + +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. + diff --git a/src/ios/SDNetworkActivityIndicator/SDNetworkActivityIndicator.h b/src/ios/SDNetworkActivityIndicator/SDNetworkActivityIndicator.h new file mode 100644 index 0000000..2c43aa6 --- /dev/null +++ b/src/ios/SDNetworkActivityIndicator/SDNetworkActivityIndicator.h @@ -0,0 +1,18 @@ +/* + * This file is part of the SDNetworkActivityIndicator package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +#import + +@interface SDNetworkActivityIndicator : NSObject + ++ (id)sharedActivityIndicator; +- (void)startActivity; +- (void)stopActivity; +- (void)stopAllActivity; + +@end diff --git a/src/ios/SDNetworkActivityIndicator/SDNetworkActivityIndicator.m b/src/ios/SDNetworkActivityIndicator/SDNetworkActivityIndicator.m new file mode 100644 index 0000000..c917b9a --- /dev/null +++ b/src/ios/SDNetworkActivityIndicator/SDNetworkActivityIndicator.m @@ -0,0 +1,70 @@ +/* + * This file is part of the SDNetworkActivityIndicator package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +#import "SDNetworkActivityIndicator.h" + +@interface SDNetworkActivityIndicator() +{ + @private NSUInteger counter; +} +@end + + +@implementation SDNetworkActivityIndicator + ++ (instancetype) sharedActivityIndicator +{ + static id _sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _sharedInstance = [[self alloc] init]; + }); + + return _sharedInstance; +} + +- (id)init +{ + if ((self = [super init])) + { + counter = 0; + } + + return self; +} + +- (void)startActivity +{ + @synchronized(self) + { + counter++; + [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; + } +} + +- (void)stopActivity +{ + @synchronized(self) + { + if (counter > 0 && --counter == 0) + { + [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; + } + } +} + +- (void)stopAllActivity +{ + @synchronized(self) + { + counter = 0; + [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; + } +} + +@end