আইফোন কোর ডেটা "উত্পাদন" ত্রুটি পরিচালনা


85

আপনি কীভাবে কোর ডেটার ত্রুটিগুলি পরিচালনা করবেন সে সম্পর্কে অ্যাপল রেফারেন্সের সরবরাহিত উদাহরণ কোডটি দেখেছি। অর্থাৎ:

NSError *error = nil;
if (![context save:&error]) {
/*
 Replace this implementation with code to handle the error appropriately.

 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
 */
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}

তবে আপনাকে কীভাবে এটি বাস্তবায়ন করা উচিত তার কোনও উদাহরণ নেই ।

কারও কাছে কি (বা আমাকে দিক নির্দেশ করতে পারে) কিছু প্রকৃত "উত্পাদন" কোড রয়েছে যা উপরের পদ্ধতিটি চিত্রিত করে?

অগ্রিম ধন্যবাদ, ম্যাট


8
+1 এটি একটি দুর্দান্ত প্রশ্ন।
ডেভ দেলং

উত্তর:


33

কেউ আপনাকে প্রোডাকশন কোডটি দেখায় না কারণ এটি আপনার অ্যাপ্লিকেশন এবং যেখানে ত্রুটি ঘটে সেখানে 100% নির্ভর করে।

ব্যক্তিগতভাবে, আমি সেখানে একটি দৃsert় বিবৃতি রেখেছি কারণ 99% এর মধ্যে এই ত্রুটিটি বিকাশে ঘটতে চলেছে এবং আপনি যখন এটি স্থির করেন এটির সম্ভাবনা খুব কম আপনি উত্পাদনতে দেখতে পাবেন।

জোর দেওয়ার পরে আমি ব্যবহারকারীর কাছে একটি সতর্কতা উপস্থাপন করব, তাদের একটি অপরিবর্তনযোগ্য ত্রুটি ঘটেছে এবং অ্যাপ্লিকেশনটি প্রস্থান হতে চলেছে তা তাদের জানান। আপনি বিকাশকারীদের সাথে যোগাযোগ করতে বলার জন্য সেখানে একটি ঝাপসা লাগাতে পারেন যাতে আপনি আশা করি এটি সম্পন্ন করা ট্র্যাক করতে পারেন।

তারপরে আমি এ্যাবস্ট () সেখানে রেখে দেব কারণ এটি অ্যাপটিকে "ক্র্যাশ করবে" এবং একটি স্ট্যাক ট্রেস তৈরি করবে যা আপনি আশাবাদী ইস্যুটি সন্ধান করতে পরে ব্যবহার করতে পারেন।


মার্কাস - যদি আপনি স্থানীয় স্ক্লাইট ডাটাবেস বা এক্সএমএল ফাইলের সাথে কথা বলছেন তবে জমিদারিগুলি ঠিক আছে, আপনার অবিরাম স্টোরটি ক্লাউড ভিত্তিক থাকলে আপনার আরও শক্তিশালী ত্রুটি পরিচালনার ব্যবস্থা দরকার।
dar512

4
যদি আপনার আইওএস কোর ডেটার ধ্রুবক স্টোরটি ক্লাউড ভিত্তিক হয় তবে আপনার আরও বড় সমস্যা রয়েছে।
মার্কাস এস জারা

4
আমি অ্যাপলের সাথে বেশ কয়েকটি বিষয়ে একমত নই। এটি একটি শিক্ষণ পরিস্থিতি (অ্যাপল) এবং খাদে (আমি) মধ্যে পার্থক্য। একাডেমিক পরিস্থিতি থেকে, হ্যাঁ আপনার অ্যাবর্সস সরানো উচিত। বাস্তবে, তারা এমন পরিস্থিতি ধরতে কার্যকর যেগুলি আপনি কখনও কল্পনাও করতে পারেননি। অ্যাপল ডকুমেন্টেশন লেখকরা ভান করতে চান যে প্রতিটি পরিস্থিতি দায়বদ্ধ। এর মধ্যে 99.999%। আপনি সত্যিকারের অপ্রত্যাশিত জন্য কি করবেন? আমি ক্রাশ করে একটি লগ তৈরি করি যাতে কী ঘটেছিল তা জানতে পারি। এটাই হল গর্ভপাত।
মার্কাস এস জারা

4
@ সিছুফ, এর কোনওটিই কোনও কোর ডেটা -save:কলকে প্রভাবিত করে না । আপনার কোডটি এই পর্যায়ে পৌঁছানোর আগে এই সমস্ত শর্তগুলি ঘটে।
মার্কাস এস জারা

4
এটি একটি প্রত্যাশিত ত্রুটি যা সংরক্ষণের আগে ধরা ও সংশোধন করা যায়। ডেটাটি বৈধ কিনা আপনি সঠিক তথ্য জিজ্ঞাসা করতে পারেন এবং এটি সংশোধন করতে পারেন। প্লাস আপনি পরীক্ষার সময় পরীক্ষা করতে পারেন যে সমস্ত বৈধ ক্ষেত্র উপস্থিত রয়েছে তা নিশ্চিত করার জন্য। এটি একটি বিকাশকারী স্তরের ত্রুটি যা -save:ডাকা যাওয়ার আগে হ্যান্ডেল করা যায় ।
মার্কাস এস জারা

32

এটি একটি জেনেরিক পদ্ধতি যা আমি আইফোনে বৈধতা ত্রুটিগুলি পরিচালনা এবং প্রদর্শন করতে এসেছি। তবে মার্কাস সঠিক: আপনি সম্ভবত ব্যবহারকারীদের আরও বেশি বন্ধুত্বপূর্ণ হওয়ার জন্য বার্তাগুলি টুইট করতে চান। তবে কমপক্ষে এটি আপনাকে কোন ক্ষেত্রটি বৈধতা দেয়নি এবং কেন তা দেখার জন্য একটি সূচনা পয়েন্ট দেয়।

- (void)displayValidationError:(NSError *)anError {
    if (anError && [[anError domain] isEqualToString:@"NSCocoaErrorDomain"]) {
        NSArray *errors = nil;

        // multiple errors?
        if ([anError code] == NSValidationMultipleErrorsError) {
            errors = [[anError userInfo] objectForKey:NSDetailedErrorsKey];
        } else {
            errors = [NSArray arrayWithObject:anError];
        }

        if (errors && [errors count] > 0) {
            NSString *messages = @"Reason(s):\n";

            for (NSError * error in errors) {
                NSString *entityName = [[[[error userInfo] objectForKey:@"NSValidationErrorObject"] entity] name];
                NSString *attributeName = [[error userInfo] objectForKey:@"NSValidationErrorKey"];
                NSString *msg;
                switch ([error code]) {
                    case NSManagedObjectValidationError:
                        msg = @"Generic validation error.";
                        break;
                    case NSValidationMissingMandatoryPropertyError:
                        msg = [NSString stringWithFormat:@"The attribute '%@' mustn't be empty.", attributeName];
                        break;
                    case NSValidationRelationshipLacksMinimumCountError:  
                        msg = [NSString stringWithFormat:@"The relationship '%@' doesn't have enough entries.", attributeName];
                        break;
                    case NSValidationRelationshipExceedsMaximumCountError:
                        msg = [NSString stringWithFormat:@"The relationship '%@' has too many entries.", attributeName];
                        break;
                    case NSValidationRelationshipDeniedDeleteError:
                        msg = [NSString stringWithFormat:@"To delete, the relationship '%@' must be empty.", attributeName];
                        break;
                    case NSValidationNumberTooLargeError:                 
                        msg = [NSString stringWithFormat:@"The number of the attribute '%@' is too large.", attributeName];
                        break;
                    case NSValidationNumberTooSmallError:                 
                        msg = [NSString stringWithFormat:@"The number of the attribute '%@' is too small.", attributeName];
                        break;
                    case NSValidationDateTooLateError:                    
                        msg = [NSString stringWithFormat:@"The date of the attribute '%@' is too late.", attributeName];
                        break;
                    case NSValidationDateTooSoonError:                    
                        msg = [NSString stringWithFormat:@"The date of the attribute '%@' is too soon.", attributeName];
                        break;
                    case NSValidationInvalidDateError:                    
                        msg = [NSString stringWithFormat:@"The date of the attribute '%@' is invalid.", attributeName];
                        break;
                    case NSValidationStringTooLongError:      
                        msg = [NSString stringWithFormat:@"The text of the attribute '%@' is too long.", attributeName];
                        break;
                    case NSValidationStringTooShortError:                 
                        msg = [NSString stringWithFormat:@"The text of the attribute '%@' is too short.", attributeName];
                        break;
                    case NSValidationStringPatternMatchingError:          
                        msg = [NSString stringWithFormat:@"The text of the attribute '%@' doesn't match the required pattern.", attributeName];
                        break;
                    default:
                        msg = [NSString stringWithFormat:@"Unknown error (code %i).", [error code]];
                        break;
                }

                messages = [messages stringByAppendingFormat:@"%@%@%@\n", (entityName?:@""),(entityName?@": ":@""),msg];
            }
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Validation Error" 
                                                            message:messages
                                                           delegate:nil 
                                                  cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
            [alert show];
            [alert release];
        }
    }
}

উপভোগ করুন।


4
অবশ্যই এই কোডটিতে কোনও ভুল দেখতে পাচ্ছে না। শক্ত লাগছে। ব্যক্তিগতভাবে আমি দৃ Data়তার সাথে কোর ডেটার ত্রুটিগুলি পরিচালনা করতে পছন্দ করি। আমি এখনও এটির একটি উত্পাদন করতে দেখেছি তাই আমি সর্বদা তাদের সম্ভাব্য উত্পাদন ত্রুটির চেয়ে উন্নয়নের ত্রুটি হিসাবে বিবেচনা করেছি। যদিও এটি অবশ্যই সুরক্ষার আরেকটি স্তর :)
মার্কাস এস জাররা

4
মার্কস, জোর দেওয়া সম্পর্কে: বৈধতার ক্ষেত্রে ডিআরওয়াই কোড রাখার বিষয়ে আপনার মতামত কী? আমার মতে মডেলটিতে (যেখানে এটি অন্তর্ভুক্ত) কেবলমাত্র একবার আপনার বৈধতার মানদণ্ডকে সংজ্ঞায়িত করা খুব আকাঙ্ক্ষিত: এই ক্ষেত্রটি খালি থাকতে পারে না, সেই ক্ষেত্রটি কমপক্ষে 5 টি দীর্ঘ দীর্ঘ হতে হবে এবং সেই ক্ষেত্রটি এই রেজেক্সটির সাথে মেলে । যে উচিত সব তথ্য ব্যবহারকারীকে একটি যথাযথ বার্তা প্রদর্শন করা প্রয়োজন হবে। এমওসি সংরক্ষণের আগে কোডগুলিতে আবার সেই চেকগুলি করা কোনওভাবেই আমার সাথে ভাল করে বসে না। আপনি কি মনে করেন?
জোহানেস ফারেনক্রুগ

4
এই মন্তব্যটি আমার উত্তরে না থাকায় কখনও দেখেনি। এমনকি আপনি যখন মডেলটিতে বৈধতা রেখেছেন তখনও আপনাকে এখনও অবজেক্টটি বৈধতা দিয়ে গেছে কিনা তা পরীক্ষা করে দেখতে হবে এবং এটি ব্যবহারকারীকে উপস্থাপন করতে হবে। মাঠ পর্যায়ে (এই পাসওয়ার্ডটি খারাপ) ইত্যাদি বা সেভ পয়েন্টে থাকা নকশার উপর নির্ভর করে। ডিজাইনারের পছন্দ। আমি অ্যাপটির সেই অংশটি জেনেরিক করব না।
মার্কাস এস জাররা

4
@ MarcusS.Zarra আমি অনুমান আপনি এটা পেয়েছিলাম কারণ আমি না সঠিকভাবে @ -mention আপনি :) আমি মনে করি আমরা সম্পূর্ণ একমত: আমি validation- চাই তথ্য মডেল হতে, কিন্তু সিদ্ধান্ত কখন ট্রিগার বৈধতা এবং কীভাবে বৈধতার ফলাফলটি পরিচালনা এবং উপস্থাপন করা যায় তা জেনেরিক হওয়া উচিত নয় এবং অ্যাপ্লিকেশন কোডের যথাযথ জায়গায় পরিচালনা করা উচিত।
জোহানেস ফারেনক্রুগ

কোডটি দুর্দান্ত দেখাচ্ছে। আমার একমাত্র প্রশ্ন হ'ল সতর্কতা দেখানোর পরে বা বিশ্লেষণটি লগ করার পরে, আমি কি কোরি ডেটা প্রসঙ্গে রোলব্যাক করব বা অ্যাপটি বাতিল করতে হবে? অন্যথায়, আমি অনুমান করি যে আপনি যখন সংরক্ষণ করার চেষ্টা করবেন তখন সংরক্ষণ না করা পরিবর্তনগুলি একই সমস্যার কারণ হতে থাকবে।
জেক

6

আমি আশ্চর্য হয়েছি যে কেউ এখানে আসলে ত্রুটিটি পরিচালনা করার জন্য বোঝায় না। আপনি যদি ডকুমেন্টেশনটি দেখুন, আপনি দেখতে পাবেন।

এখানে ত্রুটির জন্য সাধারণ কারণগুলির মধ্যে রয়েছে: * ডিভাইসটির স্থান খুব বেশি। * ডিভাইস লক হয়ে গেলে অনুমতি বা ডেটা সুরক্ষার কারণে অবিরাম স্টোরটি অ্যাক্সেসযোগ্য হয় না। * বর্তমান মডেল সংস্করণে স্টোরটি স্থানান্তরিত করা যায়নি। * মূল ডিরেক্টরি উপস্থিত নেই, তৈরি করা যায় না, বা লেখার অনুমতি দেয় না।

সুতরাং আমি যদি মূল ডেটা স্ট্যাক সেট আপ করার সময় কোনও ত্রুটি খুঁজে পাই তবে আমি ইউআইওয়াইন্ডো এর রুটভিউ কনট্রোলারকে অদলবদল করে এবং ইউআই দেখায় যা ব্যবহারকারীকে স্পষ্টভাবে জানিয়ে দেয় যে তাদের ডিভাইস পূর্ণ হতে পারে, বা এই অ্যাপ্লিকেশনটির কাজ করার জন্য তাদের সুরক্ষা সেটিংস খুব বেশি। আমি তাদের একটি 'আবার চেষ্টা করুন' বোতামটিও দিয়েছি, যাতে তারা মূল ডেটা স্ট্যাক পুনরায় চেষ্টা করার আগে সমস্যাটি সমাধানের চেষ্টা করতে পারে।

উদাহরণস্বরূপ ব্যবহারকারী কিছু সঞ্চয় স্থান ফাঁকা করতে পারে, আমার অ্যাপ্লিকেশনটিতে ফিরে আসতে পারেন এবং আবার চেষ্টা করুন বোতামটি টিপুন।

জোর দিয়েছি? সত্যি? ঘরে অনেক বেশি বিকাশকারী!

আমি অনলাইনে টিউটোরিয়ালগুলির সংখ্যা দেখেও অবাক হয়েছি যে এই কারণে কীভাবে একটি সংরক্ষণের অপারেশন ব্যর্থ হতে পারে তা উল্লেখ করে না। সুতরাং আপনাকে নিশ্চিত করতে হবে যে আপনার অ্যাপ্লিকেশনটিতে যে কোনও সংরক্ষণ ইভেন্ট ব্যর্থ হতে পারে কারণ এই মিনিটটি ডিভাইসটি আপনার অ্যাপ্লিকেশন সাশ্রয় সাশ্রয়ী সঞ্চয় দিয়ে পূর্ণ হয়ে গেছে।


এই প্রশ্নটি কোর ডেটা স্ট্যাকের সঞ্চয় সম্পর্কে, এটি কোর ডেটা স্ট্যাক সেটআপ করার বিষয়ে নয়। তবে আমি সম্মত হই যে এর শিরোনাম বিভ্রান্তিকর হতে পারে এবং সম্ভবত এটি পরিবর্তন করা উচিত।
ভ্যালাকোচো

আমি @ ভ্যালাকোখোয়কে দ্বিমত করছি উত্পাদনের সংরক্ষণের ত্রুটিগুলি কীভাবে পরিচালনা করতে হয় সে সম্পর্কে পোস্টটি পরিষ্কার is আরেকবার দেখুন।

@ রদ্দনশ যা আমি যা বলেছিলাম… ডব্লিউটিএইচ! :) আপনার উত্তরটি দেখুন।
ভ্যালেকোচো

আপনি পাগল ভাই

আপনি প্রাসঙ্গিক সংরক্ষণের সময় ঘটে যাওয়া ত্রুটিগুলি সম্পর্কিত প্রশ্নে ধ্রুবক স্টোরটি ইনস্ট্যান্ট করার সময় ঘটতে পারে এমন ত্রুটিগুলির জন্য ডকুমেন্টেশনের অংশটি আটকান, এবং আমি কি পাগল? ঠিক আছে ...
valeCocoa

5

আমি এই সাধারণ সংরক্ষণ কার্যটি আরও ভাল সমাধান পেয়েছি:

- (BOOL)saveContext {
    NSError *error;
    if (![self.managedObjectContext save:&error]) {
        DDLogError(@"[%@::%@] Whoops, couldn't save managed object context due to errors. Rolling back. Error: %@\n\n", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error);
        [self.managedObjectContext rollback];
        return NO;
    }
    return YES;
}

যখনই কোনও সংরক্ষণ ব্যর্থ হয় এটি আপনার NSManagedObjectContext রোলব্যাক করবে অর্থাত্ এটি সর্বশেষ সংরক্ষণের পরে প্রসঙ্গে করা সমস্ত পরিবর্তনগুলি পুনরায় সেট করবে । সুতরাং উপরের সেভ ফাংশনটি যত তাড়াতাড়ি এবং নিয়মিত সম্ভব ব্যবহারের পরিবর্তে সর্বদা পরিবর্তনগুলি অবিরত রাখতে আপনাকে সাবধানতার সাথে নজর রাখতে হবে যেহেতু আপনি অন্যথায় সহজেই ডেটা হারাতে পারেন।

ডেটা tingোকানোর জন্য এটি হতে পারে একটি আলগা বৈকল্পিক যা অন্য পরিবর্তনগুলিকে লাইভ করতে দেয়:

- (BOOL)saveContext {
    NSError *error;
    if (![self.managedObjectContext save:&error]) {
        DDLogError(@"[%@::%@] Whoops, couldn't save. Removing erroneous object from context. Error: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), object.objectId, error);
        [self.managedObjectContext deleteObject:object];
        return NO;
    }
    return YES;
}

দ্রষ্টব্য: আমি এখানে লগ করার জন্য কোকো লাম্বারজ্যাক ব্যবহার করছি।

কীভাবে এটিকে উন্নত করা যায় সে সম্পর্কে কোনও মন্তব্য আরও স্বাগত!

বিআর ক্রিস


: যখন আমি এই অর্জনের জন্য রোলব্যাক ব্যবহারের চেষ্টা আমি অদ্ভুত আচরণের পেয়ে করছি stackoverflow.com/questions/34426719/...
malhal

আমি পরিবর্তে এখন পূর্বাবস্থা ব্যবহার করছি
ম্যালহাল

2

আমি @ জোহানেসফেরেনক্রুগের দরকারী উত্তরের একটি সুইফ্ট সংস্করণ তৈরি করেছি যা দরকারী হতে পারে:

public func displayValidationError(anError:NSError?) -> String {
    if anError != nil && anError!.domain.compare("NSCocoaErrorDomain") == .OrderedSame {
        var messages:String = "Reason(s):\n"
        var errors = [AnyObject]()
        if (anError!.code == NSValidationMultipleErrorsError) {
            errors = anError!.userInfo[NSDetailedErrorsKey] as! [AnyObject]
        } else {
            errors = [AnyObject]()
            errors.append(anError!)
        }
        if (errors.count > 0) {
            for error in errors {
                if (error as? NSError)!.userInfo.keys.contains("conflictList") {
                    messages =  messages.stringByAppendingString("Generic merge conflict. see details : \(error)")
                }
                else
                {
                    let entityName = "\(((error as? NSError)!.userInfo["NSValidationErrorObject"] as! NSManagedObject).entity.name)"
                    let attributeName = "\((error as? NSError)!.userInfo["NSValidationErrorKey"])"
                    var msg = ""
                    switch (error.code) {
                    case NSManagedObjectValidationError:
                        msg = "Generic validation error.";
                        break;
                    case NSValidationMissingMandatoryPropertyError:
                        msg = String(format:"The attribute '%@' mustn't be empty.", attributeName)
                        break;
                    case NSValidationRelationshipLacksMinimumCountError:
                        msg = String(format:"The relationship '%@' doesn't have enough entries.", attributeName)
                        break;
                    case NSValidationRelationshipExceedsMaximumCountError:
                        msg = String(format:"The relationship '%@' has too many entries.", attributeName)
                        break;
                    case NSValidationRelationshipDeniedDeleteError:
                        msg = String(format:"To delete, the relationship '%@' must be empty.", attributeName)
                        break;
                    case NSValidationNumberTooLargeError:
                        msg = String(format:"The number of the attribute '%@' is too large.", attributeName)
                        break;
                    case NSValidationNumberTooSmallError:
                        msg = String(format:"The number of the attribute '%@' is too small.", attributeName)
                        break;
                    case NSValidationDateTooLateError:
                        msg = String(format:"The date of the attribute '%@' is too late.", attributeName)
                        break;
                    case NSValidationDateTooSoonError:
                        msg = String(format:"The date of the attribute '%@' is too soon.", attributeName)
                        break;
                    case NSValidationInvalidDateError:
                        msg = String(format:"The date of the attribute '%@' is invalid.", attributeName)
                        break;
                    case NSValidationStringTooLongError:
                        msg = String(format:"The text of the attribute '%@' is too long.", attributeName)
                        break;
                    case NSValidationStringTooShortError:
                        msg = String(format:"The text of the attribute '%@' is too short.", attributeName)
                        break;
                    case NSValidationStringPatternMatchingError:
                        msg = String(format:"The text of the attribute '%@' doesn't match the required pattern.", attributeName)
                        break;
                    default:
                        msg = String(format:"Unknown error (code %i).", error.code) as String
                        break;
                    }

                    messages = messages.stringByAppendingString("\(entityName).\(attributeName):\(msg)\n")
                }
            }
        }
        return messages
    }
    return "no error"
}`
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.