2012-07-24 12 views
15

मैं their example में सुझाए गए सिंगलटन मॉडल के साथ AFNetworking का उपयोग कर रहा हूं।बदलना AFNetworking baseURL

+ (SGStockRoomHTTPClient *)sharedClient 
{ 
    static SGStockRoomHTTPClient *_sharedClient = nil; 
    static dispatch_once_t oncePredicate; 
    dispatch_once(&oncePredicate, ^{ 
     NSString *baseUrlString = [[NSUserDefaults standardUserDefaults] stringForKey:@"server_root_url_preference"]; 
     _sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:baseUrlString]]; 
    }); 

    return _sharedClient; 
} 

- (id)initWithBaseURL:(NSURL *)url { 
    self = [super initWithBaseURL:url]; 
    if (!self) { 
     return nil; 
    } 
    [self registerHTTPOperationClass:[AFJSONRequestOperation class]]; 
    [self setDefaultHeader:@"Accept" value:@"text/html"]; 
return self; 
} 

आरंभिक उपयोगकर्ता डिफ़ॉल्ट से लिया गया बेसURL के साथ किया जाता है।

मेरी समस्या यह है कि बेसURL संपत्ति केवल पढ़ने के लिए है। यदि उपयोगकर्ता सेटिंग्स पर जाता है और बेसURL उपयोगकर्ता डिफ़ॉल्ट को बदलता है, तो मैं इसे अपने क्लाइंट में कैसे बदल सकता हूं?

बेसलर को बदलने की आवश्यकता के साथ मुझे एक और समान मामला एक एपीआई है जिसके लिए सही बेसURL को निर्धारित करने के लिए एकाधिक कॉल और तर्क की आवश्यकता होती है। और ऐप चल रहा है, जबकि बेस यूआरएल अभी भी बदल सकता है (उदाहरण के लिए उपयोगकर्ता नेटवर्किंग वातावरण में परिवर्तन करता है जो स्थानीय कनेक्शन से बाहरी प्रॉक्सी सर्वर के माध्यम से 3 जी कनेक्शन में परिवर्तन की आवश्यकता होती है।)।

मुझे लगता है कि बेसURL प्रॉपर्टी केवल पढ़ने के लिए क्यों है: नेटवर्क जैसी चीजें हैं जो पृष्ठभूमि में चलती हैं और उस सेटिंग से जुड़ी हैं। यह कहा गया है, यह एक सेटबेससेर विधि है जो निगरानी बंद कर देता है, मूल्य बदलता है, फिर फिर से निगरानी शुरू करता है ...

मुझे लगता है कि मेरा डिज़ाइन सही नहीं है, क्या मुझे इस मामले में सिंगलटन देना चाहिए और प्रत्येक बार बेसURL को बदलने के बाद क्लाइंट को फिर से बनाएं?

+1

स्पष्ट करने के सवाल AFNetworking के लिए काफी विशिष्ट है: कैसे एक एपीआई कि एक निश्चित आधार यूआरएल लेकिन कुछ उपयोगकर्ता (या कार्यक्रम तर्क) निर्दिष्ट करना चाहिए की जरूरत नहीं है के साथ AFHTTPClient इस्तेमाल करना चाहिए? उपयोगकर्ता डिफ़ॉल्ट के साथ उदाहरण एक अच्छा है, उपर्युक्त कोड काम करता है लेकिन उपयोगकर्ता को परिवर्तन को सक्रिय करने के लिए ऐप को छोड़ना और पुनः लॉन्च करना होता है। – caiman

+0

अच्छा सवाल! मुझे एक ही समस्या है। प्राथमिक सर्वर डाउन होने पर मुझे सर्वर को द्वितीयक सर्वर पर स्विच करना चाहिए। और स्विच जब वापस हो जाता है और फिर से चल रहा है। –

उत्तर

22

कक्षा AFHTTPClient एक एकल बेस यूआरएल के साथ काम करने के लिए डिज़ाइन किया गया है। यही कारण है कि यह केवल पढ़ने के लिए है।

  • अपने AFHTTPClient उपवर्ग में संपत्ति क्वालीफायर ओवरराइड:

    यहाँ अगर आप एक से अधिक आधार URL है कुछ समाधान कर रहे हैं। इस @interface अंदर रखें: @property (readwrite, nonatomic, retain) NSURL *baseURL;

  • सभी

  • पर AFHTTPClient का प्रयोग न करें AFHTTPClient

  • के कई उदाहरण बनाएं जब आप HTTP आपरेशन आप baseurl ओवरराइड कर सकते हैं पैदा करते हैं। बस एक सापेक्ष पथ के बजाय पथ में पूरा यूआरएल सेट करें।

+4

आपके सुझावों के लिए धन्यवाद! बस ओवरराइडिंग और संपत्ति पठन लिखना खतरनाक है क्योंकि कक्षा बेसURL द्वारा संदर्भित सेवा की पहुंच क्षमता का ट्रैक रखती है। लेकिन इसे निगरानी के सावधान सदस्यता के साथ ओवरराइट किया जा सकता है, फिर पुन: सक्रियण। मैं सिंगलटन मॉडल से दूर जा रहा था, और अपने मुख्य नियंत्रक में AFHTTPClient उपclass ऑब्जेक्ट को पकड़ रहा था। जब मैं baseURL को बदलने की जरूरत है तो वहां मैं इसे एक नई ताजा वस्तु के साथ ओवरराइट कर सकता हूं। मैं विकल्प 2, 3 और 4 पर आपके साथ सहमत हूं ;-) – caiman

+4

मैंने पाया है कि @ phix23 विकल्प 3 मेरे लिए सबसे अच्छा काम करता है। सिंगलटन बहुत समय के मुकाबले ज्यादा दर्द होता है।प्रत्येक बार जब आपको किसी की आवश्यकता होती है तो AFHTTPClient का एक नया उदाहरण बनाना मेरे ऐप्स के लिए सबसे अधिक समझ में आया है जहां मैंने AFNetworking का उपयोग किया है। यह इस तरह से काफी दर्द मुक्त है। –

+1

मुझे @ मैटलोंग की तरह ज्ञान के गले से नफरत है, क्योंकि वे हमेशा मेरे कोड को बेहतर तरीके से दोबारा सुधारने के लिए मजबूर करते हैं! (लेकिन गंभीरता से, धन्यवाद। बदलते आधार यूआरएल के साथ गैर-सिंगलटन दृष्टिकोण का उपयोग करना बिल्कुल सही तरीका है।) –

0

उम्मीद है कि यह आपकी मदद करता है।

@interface EFApiClient : AFHTTPSessionManager 
@property (nonatomic,assign)BOOL isTestEnvironment ; 
+ (instancetype)sharedMClient; 
@end 


@implementation EFApiClient 
+ (instancetype)sharedMClient 
{ 
    if ([EFApiClient sharedClient].isTestEnvironment) { 
     return [EFApiClient sharedTestClient] ; 
    } 
    else{ 
     return [EFApiClient sharedClient]; 
    } 
} 

+ (instancetype)sharedClient 
{ 
    static EFApiClient *_sharedMClient = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     _sharedMClient = [[EFApiClient alloc] initWithBaseURL:[NSURL URLWithString:@"https://xxx.xxx.com"]]; 
     [EFApiClient clientConfigWithManager:_sharedMClient]; 
    }); 
    return _sharedMClient; 
} 
+ (instancetype)sharedTestClient 
{ 
    static EFApiClient *_sharedMClient = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     _sharedMClient = [[EFApiClient alloc] initWithBaseURL:[NSURL URLWithString:@"https://test.xxx.xxx.com"]]; 
     [EFApiClient clientConfigWithManager:_sharedMClient]; 
    }); 
    return _sharedMClient; 
} 

+ (void)clientConfigWithManager:(EFApiClient *)client 
{ 
    AFSecurityPolicy* policy = [[AFSecurityPolicy alloc] init]; 
    [policy setAllowInvalidCertificates:YES]; 
    [policy setValidatesDomainName:NO]; 
    [client setSecurityPolicy:policy]; 
    client.requestSerializer = [AFHTTPRequestSerializer serializer]; 
    client.responseSerializer = [AFHTTPResponseSerializer serializer]; 
    //client.requestSerializer.HTTPMethodsEncodingParametersInURI = [NSSet setWithArray:@[@"POST", @"GET", @"HEAD"]]; 
    client.responseSerializer = [AFJSONResponseSerializer serializer]; 
    client.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/x-javascript",@"application/json", @"text/json", @"text/html", nil]; 
} 
@end 
+0

एक सीधा समाधान स्वागत है, लेकिन कृपया सुनिश्चित करें कि आप इसके आसपास संदर्भ जोड़ दें ताकि आपके साथी उपयोगकर्ता समझ सकें कि यह समस्या को हल कैसे करता है – pratibha