2011-01-26 12 views
53

में परिवर्तनीय तर्क विधियों को कैसे बनाएँ, यह शायद आप में से अधिकांश के लिए स्पष्ट रूप से सरल होगा, लेकिन क्या आप कृपया उदाहरण दे सकते हैं कि समान तरीकों (उद्देश्य-सी में) कैसे बनाएं और सी में फ़ंक्शंस जैसे कार्यों को बनाने के लिए NSString के stringWithFormat:, या NSLog()उद्देश्य-सी

बस याद दिलाने के लिए:

[NSString stringWithFormat:@"example tekst %i %@ %.2f",122,@"sth",3.1415"]; 
NSLog(@"account ID %i email %@",accountID,email); 

मैं NSString के समान बनाना चाहते हैं जो की विधि stringWithFormat:, NSURL - urlWithFormat

अग्रिम धन्यवाद।

उत्तर

115

इन क्या कहा जाता है, आम तौर पर, (, या तरीकों क्योंकि यह थे) "variadic कार्यों" है ।

इस बनाने के लिए, बस अंत अपने , ... साथ विधि declartion, के रूप में

- (void)logMessage:(NSString *)message, ...; 

इस बिंदु पर में आप शायद एक printf की तरह समारोह में लपेट के लिए, खरोंच से उन में से एक को लागू करने के रूप में चाहते हैं सबसे अच्छा प्रयास कर रहा है।

- (void)logMessage:(NSString *)format, ... { 
    va_list args; 
    va_start(args, format); 
    NSLogv(format, args); 
    va_end(args); 
} 

नोट NSLogv के उपयोग और नहीं NSLog; NSLog(NSString *, ...); बनाम NSLogv(NSString *, va_list); पर विचार करें, या यदि आप एक स्ट्रिंग चाहते हैं; initWithFormat:arguments:NSString * पर।


हैं, तो दूसरी ओर, आप तार के साथ काम नहीं कर रहे, बल्कि

की तरह कुछ
+ (NSArray *)arrayWithObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION; 

चीजें बहुत आसान मिलता है।

उस स्थिति में, vprintf-स्टाइल फ़ंक्शन के बजाय, args के माध्यम से जा रहे लूप का उपयोग करें, आईडी को मानते हुए, और किसी भी लूप में उन्हें पार्स करें।

- (void)logMessage:(NSString *)format, ... { 
    va_list args; 
    va_start(args, format); 

    id arg = nil; 
    while ((arg = va_arg(args,id))) { 
    /// Do your thing with arg here 
    } 

    va_end(args); 
} 

यह अंतिम नमूना, मान लीजिए कि va_args सूची शून्य-समाप्त हो गई है।

नोट: आदेश में इस काम करने के लिए में आप हो सकता है<stdarg.h> शामिल करने के लिए है, लेकिन अगर स्मृति परोसता है, तो यह NSLogv के संबंध में शामिल हो जाता है, जिसका अर्थ है कि यह "Foundation.h" के माध्यम से नीचे आता है, इसलिए "AppKit.h" और "Cocoa.h", साथ ही साथ कई अन्य; तो यह बॉक्स से बाहर काम करना चाहिए।

+4

यहां उल्लेख करने की एक बात यह है कि, पहला NSString पैरामीटर यहां प्रारूप के रूप में आता है, और अन्य चरणीय तर्क में पारित होते हैं। सही? तो लूप के लिए प्रवेश करने से पहले, आपके पास हैंडल करने के लिए एक पैरामीटर है। – karim

+0

हालांकि, क्या 'शून्य' समाप्ति की बात से बचना संभव है? जैसे परिवर्तनीय तर्क की लंबाई प्राप्त करें? – karim

+0

@karim: सी varargs तर्कों की संख्या और प्रकारों को जानने के लिए संभव नहीं है। बुलाए गए फ़ंक्शन को किसी प्रकार को जानना है और कब रुकना है। – newacct

19
- (void)methodWithFormat:(NSString*)format, ... { 
    va_list args; 
    va_start(args,format); 
    //loop, get every next arg by calling va_arg(args,<type>) 
    // e.g. NSString *arg=va_arg(args,NSString*) or int arg=(args,int) 
    va_end(args); 
} 

आप stringWithFormat को चर तर्क पास करना चाहते हैं :, की तरह कुछ का उपयोग करें:

NSString *s=[[[NSString alloc] initWithFormat:format arguments:args] autorelease]; 
+1

एआरसी संस्करण: एनएसएसटींग * एस = [[एनएसएसटींग आवंटन] initWithFormat: प्रारूप तर्क: तर्क]; – godzilla

8

यहां उल्लेख करने की एक बात यह है कि, यहां पहला एनएसएसटींग पैरामीटर स्वरूप के रूप में आता है, और अन्य चरणीय तर्क में पारित होते हैं। सही? तो लूप के लिए प्रवेश करने से पहले, आपके पास हैंडल करने के लिए एक पैरामीटर है।

- (NSString *) append:(NSString *)list, ... 
{ 
    NSMutableString * res = [NSMutableString string]; 
    [res appendString:list]; 

    va_list args; 
    va_start(args, list); 
    id arg = nil; 

    while((arg = va_arg(args, id))){ 
     [res appendString:arg]; 
    } 
    va_end(args); 
    return res; 
} 

- (void) test_va_arg 
{ 
    NSString * t = [self append:@"a", @"b", @"c", nil]; 
    STAssertEqualObjects(@"abc", t, @""); 
}