2013-10-16 12 views
5

Devo effettuare una connessione al mio server per ottenere alcuni dati JSON e devo supportare sia iOS 6 sia iOS 7.NSURLSession o NSURLConnection - Supporto iOS 6

Devo creare due classi? Uno con NSURLSession per iOS 7 e uno con NSURLConnection per iOS 6? O dovrei semplicemente usare NSURLConnection per entrambi?

+0

controlla questo link per vedere un ottimo tutorial su NSURLSession: http://www.raywenderlich.com/51127/nsurlsession-tutorial – whyoz

risposta

3

Quale vantaggio otterresti creando due classi separate che essenzialmente fanno la stessa cosa? Se non è possibile utilizzare NSURLSession perché è supportato solo in iOS 7 e si può ottenere la stessa funzionalità utilizzando NSURLConnection, che funziona in entrambi, quindi utilizzare solo NSURLConnection. Avrai meno codice da mantenere.

+0

Questo è esattamente quello che pensavo, ma non dovresti usare sempre le classi più recenti? O è una cosa cattiva che ho imparato da solo? – yoeriboven

+1

Beh, c'è sempre un compromesso tra l'utilizzo delle nuove e fresche API e il supporto dei sistemi operativi meno recenti. Le nuove API sono grandi quando ti evitano di fare del lavoro extra che avresti dovuto fare nella versione precedente. Ma se implementare la nuova API significa più lavoro (specialmente lavoro duplicato), allora dovrei passarlo. – Brian

+0

che non sembra essere il caso ... sembra che tu abbia bisogno di entrambi se hai bisogno di persistere sessioni o hai bisogno di mantenere una nuova sessione ogni volta che fai una richiesta, o almeno di passare attraverso il processo di credenziali e non persistere, a seconda di quanto tempo hai bisogno della connessione. – whyoz

0

Se è necessario utilizzare NSURLCredentialPersistenceForSession se si deve entrare in una rete di autenticazione di Windows ... quindi utilizzando NSURLConnection creerà più problemi per voi. Sto attraversando il dolore in questo momento e sono giunto alla conclusione che ho bisogno di entrambi per supportare iOS 7. Fondamentalmente, se usi NSURLConnection e willSendRequestForAuthenticationChallenge, scoprirai che in iOS 7, la tua sessione finirà con la mente di proprio (sembra una durata mentale di 30 secondi). Quindi, se devi mantenere una credenziale per accedere a più SOAP o altro, benvenuto alla cupola del terrore! Ti riferirò con codice se trovo una soluzione semplice.

3

Ottima domanda. In effetti ho avuto la stessa domanda e l'ho studiata parecchio e penso che sia un buon posto per usare un protocollo (un'interfaccia a.k.a. in altre lingue). Questo è basato sulla citazione "Programma su un'interfaccia, non su un'implementazione" dal famoso Quaderno di "Gang of Four". Penso che sia meglio provare e programmare per il futuro in modo da non essere mai martellato se decidono di deprecare qualcosa (che non è il caso qui, ma non si sa mai).

Invece di scrivere classi, scrivere un protocollo che definisce i metodi che si desidera utilizzare e quindi creare 2 classi diverse che implementano tali metodi. Nella tua app crei un puntatore che può puntare a qualsiasi classe che implementa tutti i metodi dei protocolli e quindi ogni classe di implementazione può usare qualunque framework/librerie/altro codice che desidera realizzare.

A titolo di esempio, è possibile creare un protocollo Server come questo:

// Server.h 
@protocol Server <NSObject> 
@required 
- (void)callService:(NSString *)service withData:(NSData *)data; 
@end 

e quindi creare una classe RestServer come questo:

// RestServer.h 
#import "Server.h" 
@interface RestServer : NSObject <Server> 
@end 

// RestServer.m 
#import "RestServer.h" 
@implementation RestServer 
- (void)callService:(NSString *)service withData:(NSData *)data { 
// Code using REST 
} 
@end 

e quindi creare un'altra classe come SoapServer:

// SoapServer.h 
#import "Server.h" 
@interface SoapServer : NSObject <Server> 
@end 

// SoapServer.m 
#import “SoapServer.h" 
@implementation SoapServer 
- (void)callService:(NSString *)service withData:(NSData *)data { 
// Code using SOAP 
} 
@end 

Codifica l'app principale per utilizzare solo un puntatore all'interfaccia e ora puoi scambiare classe s, senza dover modificare il codice principale:

// SomeViewController.m 
#import “Server.h” 
#import “RestServer.h” 
#import “SoapServer.h” 
… 
- (void)someMethod() { 
    id<Server> myServer; 

    if ([self shouldIUseSoap]) 
     myServer = [[SoapServer alloc] init]; 
    else 
     myServer = [[RestServer alloc] init]; 

    [myServer callService:@"loginUser" withData:[self getData]]; 
} 

Ora è possibile modificare le classi di server ogni volta che si desidera e non hanno mai andare a caccia giù tutti i posti nel codice in cui si effettuano le chiamate a Callservice: Withdata :. QUESTO È IL VANTAGGIO DELLA PROGRAMMAZIONE ALLE INTERFACCE!

Ho usato Rest vs Soap perché pensavo che le persone più recenti su Objective-C potessero capirlo meglio, ma nel tuo caso potresti avere un ConnectionServer o un SessionServer o qualcosa del genere.

Un'altra buona lettura sulla programmazione di interfacce/protocolli può essere trovato qui: https://stackoverflow.com/a/384067/504873

0

Al momento della scrittura, NSURLConnection è stato deprecato in OS X 10.11 e iOS 9.0 ma le mie Apps necessario supportare OS X 10.7 e iOS 6. Quindi ora si deve utilizzare NSURLSession per i progetti in corso, ma supportano anche la classe NSURLConnection ora deprecata per le versioni del sistema operativo legacy supportate!

In questi giorni voterei per la soluzione TenaciousJay con la soppressione degli avvisi del compilatore attorno all'implementazione della classe NSURLConnection.

#pragma GCC diagnostic push 
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 
     /* NSURLConnection code here */ 
#pragma GCC diagnostic pop 

il beneficio che vuoi guadagnare con la creazione di due classi distinte che fanno essenzialmente la stessa cosa è che si può finalmente tagliare la vecchia soluzione deprecato quando si può finalmente rilasciare il supporto per le versioni di sistemi operativi precedenti.

La mia decisione codice per utilizzare una classe o l'altro non sarebbe basato su qualche proprietà di classe, ma il risultato di una macro come:

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) 

per iOS o per OS X:

NSString *systemVersion = nil; 
     if ([[NSProcessInfo processInfo] respondsToSelector:NSSelectorFromString(@"operatingSystemVersion")]) { 
      NSOperatingSystemVersion operatingSystemVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; 
      systemVersion  = [NSString stringWithFormat:@"%ld.%ld.%ld", (long)operatingSystemVersion.majorVersion, (long)operatingSystemVersion.minorVersion, (long)operatingSystemVersion.patchVersion]; 
     } else { 
      SInt32 versionMajor=0, versionMinor=0, versionPatch=0; 
#pragma GCC diagnostic push 
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 
      Gestalt(gestaltSystemVersionMajor, &versionMajor); 
      Gestalt(gestaltSystemVersionMinor, &versionMinor); 
      Gestalt(gestaltSystemVersionBugFix, &versionPatch); 
#pragma GCC diagnostic pop 
      systemVersion  = [NSString stringWithFormat:@"%ld.%ld.%ld", (long)versionMajor, (long)versionMinor, (long)versionPatch]; 
     } 
     NSLog(@"[Line %d] %s OS X Runtime Version: '%@'", __LINE__, __PRETTY_FUNCTION__, systemVersion); 
Problemi correlati