2013-09-03 6 views
8

के साथ सिंगलटन पैटर्न, मैं एक बाकी वेब सेवा तक पहुंचने के लिए AFHTTPClient के उप-वर्ग का उपयोग कर रहा हूं। मैं अपने सभी अनुरोधों को अपने एपीआई क्लाइंट के एक उदाहरण से संभालना चाहता हूं, इसलिए मैं सिंगलटन पैटर्न का उपयोग करता हूं।मेरे आईफोन एप्लिकेशन में पैरामीटर

यह ठीक काम करता है जब सेवा केवल एक बार यूआरएल पर चल रही है। मैं यूआरएल सेट करने के लिए निरंतर मूल्य का उपयोग कर सकता हूं।

अब, आवेदन के अंतिम संस्करण में, प्रत्येक ऐप वास्तव में किसी अन्य सेवा से बात करेगा जो कॉर्पोरेट नेटवर्क में स्थापित होगा।

तो मुझे रिमोट कॉन्फ़िगरेशन से सेवा यूआरएल मिल जाएगा। क्या सिंगलटन पैटर्न अभी भी एक अच्छी पसंद है? यदि एप के रनटाइम के दौरान यूआरएल वास्तव में भी बदल सकता है तो मुझे इसे पैरामीटर करना कैसा लगता है?

चियर्स

#import "FooAPIClient.h" 
#import "AFJSONRequestOperation.h" 

static NSString * const kFooAPIBaseURLString = @"http://192.168.0.1"; 

@implementation FooAPIClient 

+ (instancetype)sharedClient { 
    static FooAPIClient *_sharedClient = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     _sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:kFooAPIBaseURLString]]; 
    }); 

    return _sharedClient; 
} 

- (id)initWithBaseURL:(NSURL *)url { 
    self = [super initWithBaseURL:url]; 
    if (!self) { 
     return nil; 
    } 

    [self registerHTTPOperationClass:[AFJSONRequestOperation class]]; 
    [self setDefaultHeader:@"Accept" value:@"application/json"]; 

    return self; 
} 

@end 
+0

मुझे लगता है कि आप वास्तव में कुछ कोड लिखने के लिए होगा। यदि URL क्रमशः बदलता है तो यह आपके सिंगलटन पर "परिवर्तन URL" फ़ंक्शन का एक साधारण मामला है। यदि आपके पास एक ही समय में कई यूआरएल सक्रिय हो सकते हैं तो आपको किसी प्रकार की निर्देशिका या उदाहरणों की सरणी की आवश्यकता होती है, या फिर इसका उपयोग करके कोड द्वारा "स्वामित्व" उदाहरण है, बनाम एक सिंगलटन के माध्यम से संबोधित किया जा रहा है। –

+0

एक बार में केवल एक ही यूआरएल हो सकता है। समस्या यह थी कि, एक बार तत्काल, AFHTTPClient अपना यूआरएल नहीं बदल सकता है। तो समाधान पूरे AFHTTPClient को अपने ग्राहक की निजी संपत्ति के रूप में विस्तारित करने के बजाय है। यदि यूआरएल बदलता है, तो मैं अपने सिंगलटन में बस एक नया AFHTTP क्लाइंट चालू कर सकता हूं। इससे हो जाना चाहिए। – Jan

उत्तर

1

यह समाधान हो सकता है। इसके बजाय AFHTTPClient उपवर्गीकरण की, बस संपत्ति के रूप में सेट है और यह अगर URL परिवर्तन फिर से दृष्टांत:

#import "FooAPIClient.h" 
#import "AFJSONRequestOperation.h" 
#import "AFHTTPClient.h" 

static NSString * const kFooAPIBaseURLString = @"http://192.168.0.1"; 

@interface FooAPIClient() 
@property AFHTTPClient * httpClient; 
@end 

@implementation FooAPIClient 

+ (instancetype)sharedClient { 
    static FooAPIClient *_sharedClient = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     _sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:kFooAPIBaseURLString]]; 
    }); 

    return _sharedClient; 
} 

- (id)initWithBaseURL:(NSURL *)url { 

    self = [super init]; 
    if (!self) { 
     self.httpClient = [self setupClientForURL:url]; 
    } 
    return self; 
} 

-(AFHTTPClient*) setupClientForURL:(NSURL*) url { 
    AFHTTPClient * httpClient = [[AFHTTPClient alloc] initWithBaseURL:url]; 
    [httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]]; 
    [httpClient setDefaultHeader:@"Accept" value:@"application/json"]; 
    return httpClient; 
} 

#pragma mark - RemoteConfigurationDelegate 

-(void) apiURLChanged:(NSURL*) newURL { 
    self.httpClient = [self setupClientForURL:newURL]; 
} 


#pragma mark - Public 

-(void) consumeAPI:(CompletionBlock) completion { 
    [self.httpClient getPath:@"foo" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
     if(completion) { 
      completion(responseObject, nil); 
     } 
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
     if(completion) { 
      completion(nil, error); 
     } 
    }]; 
} 



@end 
1

सिंगलटन पैटर्न एक स्ट्रेट होने की जरूरत नहीं है।

यह पाठ मैंने कोको टच से सीखा। ढांचे में कई कक्षाएं हैं जो साझा उदाहरणों का उपयोग करती हैं, लेकिन यदि आपको उनकी आवश्यकता होती है तो आप अपने स्वयं के उदाहरण बनाने की लचीलापन की अनुमति देते हैं। NSNumberFormatter, NSDateFormatter, NSBundle, NSFileManager और कई अन्य कक्षाएं कक्षाओं के उदाहरण हैं जहां आप की आवश्यकता होने पर आप अपने स्वयं के उदाहरण बना सकते हैं।

आपके मामले में, मैं दो वर्ग तरीकों कि उदाहरणों लौट होगा:

+ (instancetype)sharedClient { 
    static FooAPIClient *instance = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     instance = [[self alloc] initWithBaseURL:[NSURL URLWithString:kFooAPIBaseURLString]]; 
    }); 

    return instance; 
} 

static FooAPIClient *FooSharedCorporateInstance; 

+ (instancetype)sharedCorporateClient { 
    @syncronized (FooSharedCorporateInstance) { 
     return FooSharedCorporateInstance; 
    } 
} 

+ (void)setSharedCorporateClientWithURL:(NSURL *)URL { 
    @syncronized (FooSharedCorporateInstance) { 
     FooSharedCorporateInstance = [[self alloc] initWithBaseURL:URL]; 
    } 
} 

एक तरफ लाभ के रूप में, यह अलग वर्ग और उदाहरण जिम्मेदारियों कि सिंगलटन कक्षाओं में धुंधला करने के लिए करते हैं बाध्य करती है।

+0

नहीं, यह कोई समाधान नहीं है। यूआरएल निरंतर नहीं हो सकता है। यूआरएल गतिशील रूप से रनटाइम पर सेट किया जाएगा। – Jan

+0

@ जैन मैंने अपना जवाब अपडेट किया। आप प्रारंभिक मान के साथ शुरू होने पर '+ setSharedCorporateClientWithURL: 'पर कॉल कर सकते हैं, या कॉर्पोरेट क्लाइंट को इंगित करने के लिए शून्य का उपयोग कर सकते हैं। –

+0

'+ setSharedCorporateClientWithURL: 'समाधान के साथ, ऑब्जेक्ट्स जिनमें पुराने" साझा उदाहरण "का संदर्भ है, पुराने URL से बात करते रहेंगे। तो यह अब सिंगलटन पैटर्न नहीं होगा। – Jan

संबंधित मुद्दे