जवाबों:
खैर, जो मैं आमतौर पर करता हूं वह मेरे तरीके हैं जो रनटाइम के समय त्रुटि-आउट एक NSError
पॉइंटर का संदर्भ ले सकते हैं । अगर वास्तव में उस पद्धति में कुछ गलत होता है, तो मैं NSError
त्रुटि डेटा के साथ संदर्भ को पॉप्युलेट कर सकता हूं और विधि से शून्य वापस कर सकता हूं ।
उदाहरण:
- (id) endWorldHunger:(id)largeAmountsOfMonies error:(NSError**)error {
// begin feeding the world's children...
// it's all going well until....
if (ohNoImOutOfMonies) {
// sad, we can't solve world hunger, but we can let people know what went wrong!
// init dictionary to be used to populate error object
NSMutableDictionary* details = [NSMutableDictionary dictionary];
[details setValue:@"ran out of money" forKey:NSLocalizedDescriptionKey];
// populate the error object with the details
*error = [NSError errorWithDomain:@"world" code:200 userInfo:details];
// we couldn't feed the world's children...return nil..sniffle...sniffle
return nil;
}
// wohoo! We fed the world's children. The world is now in lots of debt. But who cares?
return YES;
}
हम फिर इस तरह की विधि का उपयोग कर सकते हैं। जब तक यह विधि शून्य न हो जाए, तब तक त्रुटि ऑब्जेक्ट का निरीक्षण करने की जहमत न उठायें:
// initialize NSError object
NSError* error = nil;
// try to feed the world
id yayOrNay = [self endWorldHunger:smallAmountsOfMonies error:&error];
if (!yayOrNay) {
// inspect error
NSLog(@"%@", [error localizedDescription]);
}
// otherwise the world has been fed. Wow, your code must rock.
हम त्रुटि का उपयोग करने में सक्षम थे localizedDescription
क्योंकि हम इसके लिए एक मूल्य निर्धारित करते हैं NSLocalizedDescriptionKey
।
अधिक जानकारी के लिए सबसे अच्छी जगह Apple के प्रलेखन है । यह वास्तव में अच्छा है।
कोको इज़ माय गर्लफ्रेंड पर एक अच्छा, सरल ट्यूटोरियल भी है ।
id
एक करने के लिए BOOL
। किसी भी मामूली एआरसी संगत भिन्नता की बहुत सराहना की जाएगी।
BOOL
। NO
त्रुटि के मामले में वापसी और वापसी मूल्य के लिए जाँच करने के बजाय, बस जाँच करें error
। अगर nil
आगे बढ़ें, तो != nil
संभलें।
**error
शून्य नहीं है। अन्यथा कार्यक्रम एक त्रुटि फेंक देगा जो पूरी तरह से अमित्र है और यह स्पष्ट नहीं करता है कि क्या हो रहा है।
मैं अपने सबसे हालिया कार्यान्वयन के आधार पर कुछ और सुझाव जोड़ना चाहूंगा। मैंने Apple के कुछ कोड को देखा है और मुझे लगता है कि मेरा कोड उसी तरह से व्यवहार करता है।
ऊपर दिए गए पोस्ट पहले ही बता देते हैं कि NSError वस्तुओं को कैसे बनाया जाता है और उन्हें कैसे वापस किया जाता है, इसलिए मैं उस हिस्से से परेशान नहीं होऊंगा। मैं सिर्फ आपके ऐप में त्रुटियों (कोड, संदेश) को एकीकृत करने का एक अच्छा तरीका सुझाने की कोशिश करूंगा।
मैं 1 हेडर बनाने की सलाह देता हूं जो आपके डोमेन (यानी ऐप, लाइब्रेरी, आदि ..) की सभी त्रुटियों का अवलोकन होगा। मेरा वर्तमान हेडर इस तरह दिखता है:
FSError.h
FOUNDATION_EXPORT NSString *const FSMyAppErrorDomain;
enum {
FSUserNotLoggedInError = 1000,
FSUserLogoutFailedError,
FSProfileParsingFailedError,
FSProfileBadLoginError,
FSFNIDParsingFailedError,
};
FSError.m
#import "FSError.h"
NSString *const FSMyAppErrorDomain = @"com.felis.myapp";
अब त्रुटियों के लिए उपरोक्त मूल्यों का उपयोग करते समय, Apple आपके ऐप के लिए कुछ बुनियादी मानक त्रुटि संदेश बनाएगा। निम्नलिखित की तरह एक त्रुटि बनाई जा सकती है:
+ (FSProfileInfo *)profileInfoWithData:(NSData *)data error:(NSError **)error
{
FSProfileInfo *profileInfo = [[FSProfileInfo alloc] init];
if (profileInfo)
{
/* ... lots of parsing code here ... */
if (profileInfo.username == nil)
{
*error = [NSError errorWithDomain:FSMyAppErrorDomain code:FSProfileParsingFailedError userInfo:nil];
return nil;
}
}
return profileInfo;
}
error.localizedDescription
उपरोक्त कोड के लिए मानक Apple-जनित त्रुटि संदेश ( ) निम्नलिखित की तरह दिखाई देगा:
Error Domain=com.felis.myapp Code=1002 "The operation couldn’t be completed. (com.felis.myapp error 1002.)"
ऊपर एक डेवलपर के लिए पहले से ही काफी मददगार है, क्योंकि संदेश उस डोमेन को प्रदर्शित करता है जहां त्रुटि हुई थी और संबंधित त्रुटि कोड। अंतिम उपयोगकर्ताओं के पास कोई त्रुटि नहीं होगी कि त्रुटि कोड 1002
का क्या अर्थ है, इसलिए अब हमें प्रत्येक कोड के लिए कुछ अच्छे संदेशों को लागू करने की आवश्यकता है।
त्रुटि संदेशों के लिए हमें स्थानीयकरण को ध्यान में रखना होगा (भले ही हम स्थानीय संदेशों को तुरंत लागू न करें)। मैंने अपनी वर्तमान परियोजना में निम्नलिखित दृष्टिकोण का उपयोग किया है:
1) एक strings
फ़ाइल बनाएं जिसमें त्रुटियां होंगी। स्ट्रिंग्स फ़ाइलें आसानी से स्थानीय हैं। फ़ाइल निम्नलिखित की तरह दिख सकती है:
FSError.strings
"1000" = "User not logged in.";
"1001" = "Logout failed.";
"1002" = "Parser failed.";
"1003" = "Incorrect username or password.";
"1004" = "Failed to parse FNID."
2) स्थानीय त्रुटि संदेशों में पूर्णांक कोड बदलने के लिए मैक्रोज़ जोड़ें। मैंने अपनी स्थिरांक + मैक्रोज़.एच फ़ाइल में 2 मैक्रोज़ का उपयोग किया है। मैं हमेशा इस फ़ाइल को सुविधा के लिए उपसर्ग शीर्षक ( MyApp-Prefix.pch
) में शामिल करता हूँ ।
स्थिरांक + Macros.h
// error handling ...
#define FS_ERROR_KEY(code) [NSString stringWithFormat:@"%d", code]
#define FS_ERROR_LOCALIZED_DESCRIPTION(code) NSLocalizedStringFromTable(FS_ERROR_KEY(code), @"FSError", nil)
3) अब एक त्रुटि कोड के आधार पर उपयोगकर्ता के अनुकूल त्रुटि संदेश दिखाना आसान है। एक उदाहरण:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
message:FS_ERROR_LOCALIZED_DESCRIPTION(error.code)
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
Constants+Macros.h
और इस फाइल को प्रीफिक्स हेडर ( .pch
फाइल) में इम्पोर्ट करता है, इसलिए यह हर जगह उपलब्ध है। यदि आपका मतलब है कि आप केवल 2 मैक्रोज़ में से 1 का उपयोग कर रहे हैं, तो यह काम कर सकता है। शायद से रूपांतरण int
करने के लिए NSString
हालांकि मैं इस परीक्षण नहीं किया, वास्तव में आवश्यक नहीं है।
.strings
फ़ाइल) में होना चाहिए , क्योंकि यही वह जगह है जहाँ से Apple का मैक्रो दिखेगा। NSLocalizedStringFromTable
यहाँ उपयोग करने के बारे में पढ़ें : developer.apple.com/library/mac/documentation/cocoa/conceptual/…
FS_ERROR_LOCALIZED_DESCRIPTION
एक फ़ाइल नामक स्थान पर स्थानीय स्ट्रिंग की जाँच करता है FSError.strings
। यदि आप .strings
यह आपके लिए विदेशी हैं, तो आप फ़ाइलों पर Apple के स्थानीयकरण गाइड की जांच करना चाहते हैं।
महान जवाब एलेक्स। एक संभावित समस्या है NULL dereference। NSError ऑब्जेक्ट बनाने और वापस करने पर Apple का संदर्भ
...
[details setValue:@"ran out of money" forKey:NSLocalizedDescriptionKey];
if (error != NULL) {
// populate the error object with the details
*error = [NSError errorWithDomain:@"world" code:200 userInfo:details];
}
// we couldn't feed the world's children...return nil..sniffle...sniffle
return nil;
...
कृपया निम्नलिखित ट्यूटोरियल देखें
मुझे आशा है कि यह आपके लिए उपयोगी होगा, लेकिन इससे पहले आपको NSError के प्रलेखन को पढ़ना होगा
यह बहुत ही रोचक लिंक है जो मैंने हाल ही में एररहैंडलिंग पाया
मैं एलेक्स और jlmendezbonini के शानदार जवाब को संक्षेप में बताने की कोशिश करूंगा, एक ऐसा संशोधन जो सब कुछ ARC को संगत बना देगा (अब तक ARC शिकायत नहीं करेगा क्योंकि आपको वापस लौट जाना चाहिए id
, जिसका अर्थ है "कोई भी वस्तु", लेकिन BOOL
एक वस्तु नहीं है प्रकार)।
- (BOOL) endWorldHunger:(id)largeAmountsOfMonies error:(NSError**)error {
// begin feeding the world's children...
// it's all going well until....
if (ohNoImOutOfMonies) {
// sad, we can't solve world hunger, but we can let people know what went wrong!
// init dictionary to be used to populate error object
NSMutableDictionary* details = [NSMutableDictionary dictionary];
[details setValue:@"ran out of money" forKey:NSLocalizedDescriptionKey];
// populate the error object with the details
if (error != NULL) {
// populate the error object with the details
*error = [NSError errorWithDomain:@"world" code:200 userInfo:details];
}
// we couldn't feed the world's children...return nil..sniffle...sniffle
return NO;
}
// wohoo! We fed the world's children. The world is now in lots of debt. But who cares?
return YES;
}
अब हमारे विधि कॉल के वापसी मूल्य के लिए जाँच करने के बजाय, हम जाँचते हैं कि क्या error
अभी भी है nil
। अगर यह हमारे पास समस्या नहीं है।
// initialize NSError object
NSError* error = nil;
// try to feed the world
BOOL success = [self endWorldHunger:smallAmountsOfMonies error:&error];
if (!success) {
// inspect error
NSLog(@"%@", [error localizedDescription]);
}
// otherwise the world has been fed. Wow, your code must rock.
एक अन्य डिज़ाइन पैटर्न जो मैंने देखा है इसमें ब्लॉक का उपयोग करना शामिल है, जो विशेष रूप से उपयोगी है जब एक विधि को अतुल्यकालिक रूप से चलाया जा रहा है।
मान लें कि हमारे पास निम्नलिखित त्रुटि कोड हैं:
typedef NS_ENUM(NSInteger, MyErrorCodes) {
MyErrorCodesEmptyString = 500,
MyErrorCodesInvalidURL,
MyErrorCodesUnableToReachHost,
};
आप अपनी पद्धति को परिभाषित करेंगे जो एक त्रुटि को बढ़ा सकती है जैसे:
- (void)getContentsOfURL:(NSString *)path success:(void(^)(NSString *html))success failure:(void(^)(NSError *error))failure {
if (path.length == 0) {
if (failure) {
failure([NSError errorWithDomain:@"com.example" code:MyErrorCodesEmptyString userInfo:nil]);
}
return;
}
NSString *htmlContents = @"";
// Exercise for the reader: get the contents at that URL or raise another error.
if (success) {
success(htmlContents);
}
}
और फिर जब आप इसे कॉल करते हैं, तो आपको NSError ऑब्जेक्ट घोषित करने के बारे में चिंता करने की आवश्यकता नहीं है (कोड पूरा करना आपके लिए होगा), या रिटर्निंग मान की जांच करना। आप केवल दो ब्लॉकों की आपूर्ति कर सकते हैं: एक जो अपवाद होने पर कॉल किया जाएगा, और एक जिसे कॉल किया जाता है जब वह सफल होता है:
[self getContentsOfURL:@"http://google.com" success:^(NSString *html) {
NSLog(@"Contents: %@", html);
} failure:^(NSError *error) {
NSLog(@"Failed to get contents: %@", error);
if (error.code == MyErrorCodesEmptyString) { // make sure to check the domain too
NSLog(@"You must provide a non-empty string");
}
}];
extension NSError {
static func defaultError() -> NSError {
return NSError(domain: "com.app.error.domain", code: 0, userInfo: [NSLocalizedDescriptionKey: "Something went wrong."])
}
}
NSError.defaultError()
जब भी मैं मान्य त्रुटि ऑब्जेक्ट नहीं है मैं उपयोग कर सकते हैं ।
let error = NSError.defaultError()
print(error.localizedDescription) //Something went wrong.