From 4bb4815cd1e193639788fd6de3dac9df59eaa8df Mon Sep 17 00:00:00 2001 From: Andrea Busi Date: Fri, 25 Sep 2020 13:04:10 +0200 Subject: [PATCH] refactor: Better ServerRequest class - Remove dead code - Always call completion when handle the request - Remove crazy checks when handle responses --- Sources/Earthquake Network/Costanti.h | 5 + Sources/Earthquake Network/ServerRequest.h | 23 +- Sources/Earthquake Network/ServerRequest.m | 546 +++++---------------- 3 files changed, 139 insertions(+), 435 deletions(-) diff --git a/Sources/Earthquake Network/Costanti.h b/Sources/Earthquake Network/Costanti.h index 795bb15..37e1a7d 100644 --- a/Sources/Earthquake Network/Costanti.h +++ b/Sources/Earthquake Network/Costanti.h @@ -9,6 +9,11 @@ #ifndef Costanti_h #define Costanti_h +#pragma mark - Debug + +/// Stampa le risposte delle chiamate al server +static BOOL const EQNDebugPrintResponse = NO; + #pragma mark - Urls static NSString * const EQNWebsiteAddress = @"https://www.sismo.app"; diff --git a/Sources/Earthquake Network/ServerRequest.h b/Sources/Earthquake Network/ServerRequest.h index 41fa632..52d98d3 100644 --- a/Sources/Earthquake Network/ServerRequest.h +++ b/Sources/Earthquake Network/ServerRequest.h @@ -1,30 +1,31 @@ // // ServerRequest.h -// Telegea +// Earthquake Network // -// Created by Luca Beretta on 15/02/17. -// Copyright © 2017 Luca Beretta. All rights reserved. +// Refactored by Andrea Busi on 25/09/2020. +// Copyright © 2020 Earthquake Network. All rights reserved. // #import #import #import "Costanti.h" +NS_ASSUME_NONNULL_BEGIN + +typedef void (^successCompletionHandler)(id _Nullable result); +typedef void (^errorCompletionHandler)(NSError * _Nullable error); @interface ServerRequest : NSObject @property (nonatomic) BOOL isConnect; -+(ServerRequest *) defaultServerConnectionSingleton; ++ (instancetype)defaultServerConnectionSingleton; --(void)inviaInformazioniAlServerWithURL:(NSURL *)url richiesta:(EQNTipoChiamata )chiamata success:(void(^)(id result)) success failure:(void(^)(NSError *))failure; +- (void)inviaInformazioniAlServerWithURL:(NSURL *)url richiesta:(EQNTipoChiamata)chiamata success:(successCompletionHandler)onSuccess failure:(errorCompletionHandler)onFailure; --(void)inviaRicevuta:(NSData *)ricevuta success:(void(^)(id result)) success failure:(void(^)(NSError *))failure; +- (void)inviaRicevuta:(NSData *)ricevuta success:(successCompletionHandler)onSuccess failure:(errorCompletionHandler)onFailure; -/* --(void)sendGetMethod:(NSURLRequest *)request typeRequest:(TypeRequest)type success:(void(^)(id dictionary)) success failure:(void(^)(NSError *))failure; - --(UIAlertController *)mostraAllertWithMessage:(NSString *)messaggio close:(void(^)(BOOL terminato))terminato; -*/ @end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Earthquake Network/ServerRequest.m b/Sources/Earthquake Network/ServerRequest.m index 6c42472..3eaa091 100644 --- a/Sources/Earthquake Network/ServerRequest.m +++ b/Sources/Earthquake Network/ServerRequest.m @@ -1,9 +1,9 @@ // // ServerRequest.m -// Telegea +// Earthquake Network // -// Created by Luca Beretta on 15/02/17. -// Copyright © 2017 Luca Beretta. All rights reserved. +// Refactored by Andrea Busi on 25/09/2020. +// Copyright © 2020 Earthquake Network. All rights reserved. // #import "ServerRequest.h" @@ -12,91 +12,76 @@ #import "EQNUtility.h" #import "NSDictionary+BVJSONString.h" -//#import "User.h" -//#import "Portachiavi.h" -@interface ServerRequest (){ - - NSURLSession *session; - -} -@property (nonatomic) Reachability *hostReachability; +@interface ServerRequest () +@property (strong, nonatomic) NSURLSession *session; @property (nonatomic) Reachability *internetReachability; - @end @implementation ServerRequest -static ServerRequest *_sharedInstance = nil; +#pragma mark - Singleton -+(ServerRequest *) defaultServerConnectionSingleton{ - - @synchronized (_sharedInstance) { ++ (instancetype)defaultServerConnectionSingleton +{ + static ServerRequest *sharedMyManager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedMyManager = [[self alloc] init]; + }); + return sharedMyManager; +} + +#pragma mark - Init + +- (instancetype)init +{ + self = [super init]; + if (self) { + NSURLSessionConfiguration *config = [NSURLSessionConfiguration ephemeralSessionConfiguration]; + self.session = [NSURLSession sessionWithConfiguration:config]; - if (_sharedInstance == nil){ - _sharedInstance = [[ServerRequest alloc] init]; - - } - [_sharedInstance initSingleton]; - - return _sharedInstance; + // registro notifiche rilevamento connessione + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil]; + + self.internetReachability = [Reachability reachabilityForInternetConnection]; + [self.internetReachability startNotifier]; + [self setValue:@([self updateConnectionReachability:self.internetReachability]) forKey:@"isConnect"]; + } + return self; +} + +#pragma mark - Reachability notifications + +/// Called by Reachability whenever status changes. +- (void)reachabilityChanged:(NSNotification *)notification +{ + if ([notification.object isKindOfClass:[Reachability class]]) { + Reachability *curReach = [notification object]; + [self setValue:@([self updateConnectionReachability:curReach]) forKey:@"isConnect"]; } } --(void)initSingleton{ - - NSURLSessionConfiguration *config = [NSURLSessionConfiguration ephemeralSessionConfiguration]; - session = [NSURLSession sessionWithConfiguration:config]; - - // registro notifiche rilevamento connessione - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil]; - NSString *remoteHostName = @"http://srv.earthquakenetwork.it"; - - self.hostReachability = [Reachability reachabilityWithHostName:remoteHostName]; - [self.hostReachability startNotifier]; - [self setValue:@([self updateConnectionhReachability:self.hostReachability]) forKey:@"isConnect"]; - // self.isConnect = [self updateConnectionhReachability:self.hostReachability]; - - self.internetReachability = [Reachability reachabilityForInternetConnection]; - [self.internetReachability startNotifier]; - // self.isConnect = [self updateConnectionhReachability:self.internetReachability]; - [self setValue:@([self updateConnectionhReachability:self.internetReachability]) forKey:@"isConnect"]; +#pragma mark - Private -} - -/*! - * Called by Reachability whenever status changes. - */ -- (void) reachabilityChanged:(NSNotification *)note -{ - Reachability* curReach = [note object]; - NSParameterAssert([curReach isKindOfClass:[Reachability class]]); - // self.isConnect = [self updateConnectionhReachability:curReach]; - - [self setValue:@([self updateConnectionhReachability:curReach]) forKey:@"isConnect"]; -} - -- (BOOL)updateConnectionhReachability:(Reachability *)reachability +- (BOOL)updateConnectionReachability:(Reachability *)reachability { NetworkStatus netStatus = [reachability currentReachabilityStatus]; switch (netStatus) { - case NotReachable: - return NO; - break; - default: - return YES; - break; + case NotReachable: return NO; + default: return YES; } - } --(void)inviaInformazioniAlServerWithURL:(NSURL *)url richiesta:(EQNTipoChiamata )chiamata success:(void(^)(id result)) success failure:(void(^)(NSError *))failure{ - +#pragma mark - Public + +- (void)inviaInformazioniAlServerWithURL:(NSURL *)url richiesta:(EQNTipoChiamata)chiamata success:(successCompletionHandler)onSuccess failure:(errorCompletionHandler)onFailure +{ if (!self.isConnect) { - + NSLog(@"[ServerRequest] not connected, return error"); NSError *error = [NSError errorWithDomain:NSMachErrorDomain code:401 userInfo:@{MESSAGGIO : NSLocalizedString(@"Nessuna connessione", @"messaggio assenza connesione")}]; - failure(error); - + onFailure(error); + // todo Andrea: perchè non viene fatto return? era già così } NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:url]; @@ -106,166 +91,76 @@ static ServerRequest *_sharedInstance = nil; [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; }); - NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){ - + NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSHTTPURLResponse *httpResp = (NSHTTPURLResponse *)response; + if (error) { + NSLog(@"[ServerRequest] response error: %@", error.localizedDescription); + onFailure(error); + return; + } - - if(!error){ - - NSError *jsonError; - // NSData *myRequestData = [response dataUsingEncoding:NSUTF8StringEncoding]; - id JSON = [NSJSONSerialization JSONObjectWithData:data - options:NSJSONReadingAllowFragments - error:&jsonError]; - - if (!jsonError){ - - switch (httpResp.statusCode) { - case 200: - switch (chiamata) { - case registrazione: - success(JSON); - break; - case posizione: - success(@"success"); - break; - case calibrazione: - success(JSON); - break; - case rilevamento: - success(JSON); - break; - case downloadDati: - success(JSON); - break; - case graficoSmartPhone: - success(JSON); - break; - case areaCheck: - success(JSON); - break; - case pastquakes: - success(JSON); - break; - case utentiDisponibili: - success(JSON); - break; - case segnalazioneManuale: - success(JSON); - break; - case tsunami: - success(JSON); - break; - case segnalazzioneTerremoto: - success(JSON); - break; - case commentoTerremoto: - success(JSON); - break; - case tempoDisponibile: - success(JSON); - break; - case impostazioniNotifiche: - success(JSON); - break; - case offerTimeRemaining: - success(JSON); - default: - break; - } - // NSLog(@"Risultato richiesta server %@", JSON); - // success(@""); - dispatch_async(dispatch_get_main_queue(), ^{ - - [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; - }); - } + NSError *jsonError; + id JSON = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonError]; + if (!jsonError){ + if (EQNDebugPrintResponse) { + NSLog(@"[ServerRequest] response json: %@", JSON); } - else{ - - NSString* newStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - if (newStr) { - if (chiamata == segnalazzioneTerremoto) { - - NSLog(@"risultato segnalazione %@", [EQNUtility clearStringMessaggi:newStr]); - success([EQNUtility clearStringMessaggi:newStr]); + switch (httpResp.statusCode) { + case 200: + switch (chiamata) { + case posizione: + onSuccess(@"success"); + break; + default: + onSuccess(JSON); + break; } - - if (chiamata == rilevamento) { - - /// NSLog(@"newStr %@", newStr); - - success([EQNUtility clearStringMessaggi:newStr]); - - - } - - if (chiamata == registrazione) { - - NSLog(@"newStr %@", newStr); - - } - if (chiamata == tempoDisponibile) { - - NSLog(@"newStr %@", newStr); - - } - - if (chiamata == calibrazione) { - - NSLog(@"calibrazione %@", newStr); - success(newStr); - - } - if (chiamata == rilevamento) { - - success(newStr); - - } - if (chiamata == impostazioniNotifiche) { - - NSLog(@"impostazioniNotifiche %@", newStr); - - success(newStr); - - } - if (chiamata == segnalazioneManuale) { - - NSLog(@"segnalazioneManuale %@", newStr); - - } - } else{ - - - NSLog(@"Error %@", [jsonError description]); - - NSError *error = [NSError errorWithDomain:NSMachErrorDomain code:0 userInfo:@{MESSAGGIO : NSLocalizedString(@"Username e Password sbagliati", @"messaggio errore inserimento credenziali")}]; - failure(error); dispatch_async(dispatch_get_main_queue(), ^{ [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; }); - - - } } - + } else { + NSString *newStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (newStr) { + if (EQNDebugPrintResponse) { + NSLog(@"[ServerRequest] response string: %@", newStr); + } + + switch (chiamata) { + case segnalazzioneTerremoto: + onSuccess([EQNUtility clearStringMessaggi:newStr]); + break; + case rilevamento: + onSuccess([EQNUtility clearStringMessaggi:newStr]); + break; + case calibrazione: + onSuccess(newStr); + break; + case impostazioniNotifiche: + onSuccess(newStr); + default: + // don't call the callback + break; + } + } else { + NSLog(@"[ServerRequest] Unable to create string with response: %@", [jsonError description]); + + NSError *error = [NSError errorWithDomain:NSMachErrorDomain code:0 userInfo:@{MESSAGGIO : NSLocalizedString(@"Username e Password sbagliati", @"messaggio errore inserimento credenziali")}]; + onFailure(error); + dispatch_async(dispatch_get_main_queue(), ^{ + [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; + }); + } } - }]; [dataTask resume]; - } --(void)inviaRicevuta:(NSData *)ricevuta success:(void(^)(id result)) success failure:(void(^)(NSError *))failure{ - - +- (void)inviaRicevuta:(NSData *)ricevuta success:(successCompletionHandler)onSuccess failure:(errorCompletionHandler)onFailure +{ NSString *jsonObjectString = [ricevuta base64EncodedStringWithOptions:0]; - - // NSString* BASEURl = @"XXXXXXXXX/XXX/XXXX"; - // NSString *testReceipt= [BASEURl stringByAppendingString:@"/InApp/iOS/updatePurchase"]; NSDictionary *params = @{@"ricevuta" :jsonObjectString}; NSString *parametri = [params bv_jsonStringWithPrettyPrint:YES]; @@ -275,226 +170,29 @@ static ServerRequest *_sharedInstance = nil; [urlRequest addValue:@"application/json" forHTTPHeaderField:@"Accept"]; [urlRequest setHTTPBody:[parametri dataUsingEncoding:NSUTF8StringEncoding]]; - NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){ - + NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSHTTPURLResponse *httpResp = (NSHTTPURLResponse *)response; - - if(!error){ - - NSError *jsonError; - // NSData *myRequestData = [response dataUsingEncoding:NSUTF8StringEncoding]; - NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:data - options:NSJSONReadingAllowFragments - error:&jsonError]; - - if (!jsonError){ - - switch (httpResp.statusCode) { - case 200: - success(JSON); - - break; - - default: - NSLog(@"httpResp.statusCode %ld", (long)httpResp.statusCode); - - break; - - } - - } - } - else{ - - failure(error.userInfo[@"NSLocalizedDescription"]); - NSLog(@"Error %@", error.userInfo); - + if (error) { + NSLog(@"[ServerRequest] inviaRicevuta | response error: %@", error.localizedDescription); + onFailure(error.userInfo[@"NSLocalizedDescription"]); + return; } - }]; - - [dataTask resume]; - - -} - -/* --(void)sendGetMethod:(NSURLRequest *)request typeRequest:(TypeRequest)type success:(void(^)(id dictionary)) success failure:(void(^)(NSError *))failure{ - - if (!self.isConnect) { - - NSError *error = [NSError errorWithDomain:NSMachErrorDomain code:401 userInfo:@{MESSAGGIO : NSLocalizedString(@"Nessuna connessione", @"messaggio assenza connesione")}]; - failure(error); - - } - - [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; - - NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){ - - NSHTTPURLResponse *httpResp = (NSHTTPURLResponse *)response; - - if(!error){ - - NSError *jsonError; - - NSDictionary *showJSON = [NSJSONSerialization JSONObjectWithData:data - options:NSJSONReadingAllowFragments - error:&jsonError]; - if (!jsonError){ - - switch (httpResp.statusCode) { - case 200: - success(showJSON); - [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; - break; - } + NSError *jsonError; + NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonError]; + if (!jsonError) { + switch (httpResp.statusCode) { + case 200: + onSuccess(JSON); + break; + default: + NSLog(@"[ServerRequest] inviaRicevuta | response error, status code: %ld", (long)httpResp.statusCode); + break; } - else{ - - NSError *error; - switch (type) { - case login: - error = [NSError errorWithDomain:NSMachErrorDomain code:login userInfo:@{MESSAGGIO : NSLocalizedString(@"Username e Password sbagliati", @"messaggio errore inserimento credenziali")}]; - break; - case reading: - error = [NSError errorWithDomain:NSMachErrorDomain code:reading userInfo:@{MESSAGGIO : NSLocalizedString(@"Errore! Impossibile accedere all'impianto", @"messaggio errore richiesta apikey impianto")}]; - break; - case sending: - // error = [NSError errorWithDomain:NSMachErrorDomain code:httpResp.statusCode userInfo:@{MESSAGGIO : NSLocalizedString(@"sending", @"")}]; - case zona: - error = [NSError errorWithDomain:NSMachErrorDomain code:zona userInfo:@{MESSAGGIO : NSLocalizedString(@"Sì è verificato un errore sulla centralina", @"messaggio errore richiesta dev_cmd")}]; - break; - default: - error = [NSError errorWithDomain:NSMachErrorDomain code:httpResp.statusCode userInfo:@{MESSAGGIO : NSLocalizedString(@"Errore sconosciuto", @"")}]; - - break; - } - failure(error); - [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; - - - } - } - }]; [dataTask resume]; } - - --(void)caricaImpianto:(Plant *)plant success:(void(^)(BOOL))success failure:(void(^)(NSError *))failure{ - - NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:[self urlWithInfo:plant]]; - [urlRequest setHTTPMethod:@"GET"]; - - - [self sendGetMethod:urlRequest - typeRequest:login - success:^(NSDictionary *result){ - - plant.apikey = result[@"apikey"]; - [self caricaZoneiWithPlant:plant success:^(BOOL result){ - - - // caricamento zone - success(result); - - }failure:^(NSError *error){ - // caricamento zone - failure(error); - }]; - } - failure:^(NSError *error){ - - // caricamento impianto - - failure(error); - - }]; - -} - --(NSURL *)urlWithInfo:(Plant *)plant{ - - NSURL *url =[NSURL URLWithString:[NSString stringWithFormat:@"%@?%@=%@&%@=%@&%@=%@", LOGIN_URL, USERNAME, [User defaultUser].nome, PSW, [Portachiavi getCredenziali:[User defaultUser].nome], PLANT_ID, plant.plant_id]]; - - return url; - -} - --(void)caricaZoneiWithPlant:(Plant *)plant success:(void(^)(BOOL))success failure:(void(^)(NSError *))failure{ - - - NSString *url = [NSString stringWithFormat:@"%@?%@=%@&%@=%@&%@=[{\"mod\":10,\"reg\":100}]", DEVICE_COMMANDS_URL, APIKEY, plant.apikey, PLANT_ID, plant.plant_id, DEV_CMD]; - - NSURL *theUrl = [NSURL URLWithString:[url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]]]; - - NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:theUrl]; - [urlRequest setHTTPMethod:@"GET"]; - [self sendGetMethod:urlRequest - typeRequest:reading - success:^(NSDictionary *result){ - - NSArray *valori = result[@"result"]; - NSNumber *numeroZone; - - if(valori.count == 0){ - //numeroZone = @1; - NSError *error = [NSError errorWithDomain:NSMachErrorDomain code:0 userInfo:@{MESSAGGIO : NSLocalizedString(@"Errore! Impossibile accedere all'impianto", @"messaggio errore richiesta apikey impianto")}]; - failure(error); - return ; - - } - else if([[valori firstObject][@"val"] isEqual:[NSNull null]]){ - //numeroZone = @1; - NSError *error = [NSError errorWithDomain:NSMachErrorDomain code:0 userInfo:@{MESSAGGIO : NSLocalizedString(@"Errore! Impossibile accedere all'impianto", @"messaggio errore richiesta apikey impianto")}]; - failure(error); - return ; - - } - else - numeroZone = [valori firstObject][@"val"]; - - - [plant creaZone:[numeroZone intValue]]; - success(YES); - } - - failure:^(NSError *error){ - failure(error); - - }]; - -} - --(UIAlertController *)mostraAllertWithMessage:(NSString *)messaggio close:(void(^)(BOOL terminato))terminato{ - - NSString *titolo = @""; - if ([messaggio isEqualToString:NSLocalizedString(@"Nessuna connessione", @"messaggio assenza connesione")]) - titolo = NSLocalizedString(@"Attenzione", @""); - - UIAlertController* alert = [UIAlertController alertControllerWithTitle:titolo//NSLocalizedString(@"Attenzione", @"") - message:messaggio - preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"") - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { - - terminato(YES); - - }]; - [alert addAction:defaultAction]; - - return alert; -} - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self name:kReachabilityChangedNotification object:nil]; -} - */ - @end