iphone - البيانات الأساسية فون خطأ لم يتم حلها أثناء الحفظ





objective-c ios core-data (6)


أعني أن النموذج الخاص بك فشل في التحقق ، والذي قد يحدث لعدد من الأسباب: خاصية غير مستخدمة في النموذج الخاص بك ، القيمة المفقودة التي تم وضع علامة عليها كما هو مطلوب. للحصول على فهم أفضل لما حدث بالضبط ، ضع نقطة توقف في مكان تكون فيه مستعدًا لحفظ الكائن الخاص بك ، واتصل بأحد متغيرات الأسلوب validateFor... ، مثل:

po [myObject validateForInsert]

معلومات أكثر تفصيلاً حول المشكلة في وصف الخطأ. يعني التحقق الناجح أنك لن تحصل على أي مخرجات.

أتلقى رسالة خطأ غريبة من البيانات الأساسية عند محاولة الحفظ ولكن المشكلة أن الخطأ لا يمكن إعادة إنتاجه (يظهر في أوقات مختلفة عند القيام بمهام مختلفة)

رسالة الخطأ:

Unresolved error Domain=NSCocoaErrorDomain Code=1560 UserInfo=0x14f5480 "Operation could not be completed. (Cocoa error 1560.)", {
NSDetailedErrors = (
Error Domain=NSCocoaErrorDomain Code=1570 UserInfo=0x5406d70 "Operation could not be completed. (Cocoa error 1570.)",
Error Domain=NSCocoaErrorDomain Code=1570 UserInfo=0x14f9be0 "Operation could not be completed. (Cocoa error 1570.)"
);
}

والطريقة التي تولد الخطأ هي:

- (IBAction)saveAction:(id)sender {
    NSError *error;
    if (![[self managedObjectContext] save:&error]) {
        // Handle error
        NSLog(@"Unresolved error %@, %@, %@", error, [error userInfo],[error localizedDescription]);
        exit(-1);  // Fail
    }
}

أي فكرة لسبب هذه الرسالة؟ إعطاء ذلك يظهر في أوقات عشوائية




أنا أرمي هذا كإجابة ، على الرغم من أنه حقا أكثر من تجميل لمقتطف تشارلز. يمكن أن يكون الإخراج المستقيم من NSLog فوضى في القراءة والتفسير ، لذلك أرغب في رمي بعض المساحة البيضاء واستدعاء قيمة بعض مفاتيح 'userInfo' الهامة.

وإليك نسخة من الطريقة التي أستخدمها. ('_sharedManagedObjectContext' هو #define لـ '[[[UIApplication sharedApplication] delegate] managedObjectContext]'.)

- (BOOL)saveData {
    NSError *error;
    if (![_sharedManagedObjectContext save:&error]) {
        // If Cocoa generated the error...
        if ([[error domain] isEqualToString:@"NSCocoaErrorDomain"]) {
            // ...check whether there's an NSDetailedErrors array            
            NSDictionary *userInfo = [error userInfo];
            if ([userInfo valueForKey:@"NSDetailedErrors"] != nil) {
                // ...and loop through the array, if so.
                NSArray *errors = [userInfo valueForKey:@"NSDetailedErrors"];
                for (NSError *anError in errors) {

                    NSDictionary *subUserInfo = [anError userInfo];
                    subUserInfo = [anError userInfo];
                    // Granted, this indents the NSValidation keys rather a lot
                    // ...but it's a small loss to keep the code more readable.
                    NSLog(@"Core Data Save Error\n\n \
                      NSValidationErrorKey\n%@\n\n \
                      NSValidationErrorPredicate\n%@\n\n \
                      NSValidationErrorObject\n%@\n\n \
                      NSLocalizedDescription\n%@", 
                      [subUserInfo valueForKey:@"NSValidationErrorKey"], 
                      [subUserInfo valueForKey:@"NSValidationErrorPredicate"], 
                      [subUserInfo valueForKey:@"NSValidationErrorObject"], 
                      [subUserInfo valueForKey:@"NSLocalizedDescription"]);
                }
            }
            // If there was no NSDetailedErrors array, print values directly
            // from the top-level userInfo object. (Hint: all of these keys
            // will have null values when you've got multiple errors sitting
            // behind the NSDetailedErrors key.
            else {
                    NSLog(@"Core Data Save Error\n\n \
                      NSValidationErrorKey\n%@\n\n \
                      NSValidationErrorPredicate\n%@\n\n \
                      NSValidationErrorObject\n%@\n\n \
                      NSLocalizedDescription\n%@", 
                      [userInfo valueForKey:@"NSValidationErrorKey"], 
                      [userInfo valueForKey:@"NSValidationErrorPredicate"], 
                      [userInfo valueForKey:@"NSValidationErrorObject"], 
                      [userInfo valueForKey:@"NSLocalizedDescription"]);

            }
        } 
        // Handle mine--or 3rd party-generated--errors
        else {
            NSLog(@"Custom Error: %@", [error localizedDescription]);
        }
        return NO;
    }
    return YES;
}

هذا يسمح لي بمشاهدة قيمة "NSValidationErrorKey" ، والتي ، عندما واجهت المشكلة من البروتوكول الاختياري ، توجه مباشرة إلى كيانات البيانات الأساسية غير الاختيارية التي نسيت وضعها قبل محاولة الحفظ.




هذا يعني أنه تم تعيين خاصية إلزامية. إما في * .xcodatamodel تحقق من المربع "اختياري" أو عندما تقوم بالحفظ إلى managedObjectContext تأكد من ملء الخصائص الخاصة بك.

إذا كنت تحصل على أخطاء أخرى بعد تغيير شفرتك لتلائم المتطلبين ، فجرّب تنظيف البنية وحذف التطبيق من جهاز iPhone Simulator / iPhone. قد يتعارض تغيير نموذجك مع تنفيذ الطراز القديم.

تصحيح:

لقد نسيت تقريبا هنا جميع رموز الخطأ التي تبثها Core Data: Core Constants Reference لقد واجهت مشكلة مع هذا من قبل وأدركت أنني غير محددة في المربع الاختياري الصحيح. مثل مشكلة في معرفة المشكلة. حظا طيبا وفقك الله.




أنا ناضلت مع هذا لفترة قصيرة بنفسي. تكمن المشكلة الحقيقية هنا في أن التصحيح الذي تحصل عليه لا يُظهر لك المشكلة. والسبب في ذلك هو أن CoreData سيضع مصفوفة من كائنات NSError في كائن NSError "المستوى الأعلى" ويعيدها إذا كان هناك أكثر من مشكلة واحدة (هذا هو السبب في أنك ترى الخطأ 1560 ، والذي يشير إلى العديد من المشكلات ، ومجموعة من الأخطاء 1570s). يبدو أن CoreData يحتوي على عدد قليل من المفاتيح التي يستخدمها لتخفيض المعلومات في الخطأ الذي يتم إرجاعه إذا كانت هناك مشكلة ستعطيك معلومات أكثر فائدة (مثل الكيان الذي حدث فيه الخطأ ، والعلاقة / السمة التي كانت مفقودة ، إلخ. ). يمكن العثور على المفاتيح التي تستخدمها لفحص قاموس userInfo في المستندات المرجعية هنا .

هذه هي كتلة الكود الذي أستخدمه للحصول على ناتج معقول من الخطأ الذي تم إرجاعه أثناء الحفظ:

    NSError* error;
    if(![[survey managedObjectContext] save:&error]) {
        NSLog(@"Failed to save to data store: %@", [error localizedDescription]);
        NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
        if(detailedErrors != nil && [detailedErrors count] > 0) {
            for(NSError* detailedError in detailedErrors) {
                NSLog(@"  DetailedError: %@", [detailedError userInfo]);
            }
        }
        else {
            NSLog(@"  %@", [error userInfo]);
        }
    }

سينتج إخراج يخبرك الحقول المفقودة ، مما يجعل من السهل معالجة المشكلة بشكل كبير.




تلمسني المشكلة ، عندما أقوم بحفظ السجل الثاني إلى CoreData. تمت تعبئة جميع الحقول غير الاختيارية (العلاقة) دون الصفر كذلك ، ولكن في الإخراج الخطأ الذي سألاحظه ، أصبح أحد الحقول في أول كائن تم حفظه لا شيء. غريب قليلا؟ لكن السبب تافه للغاية - علاقة واحدة تلغي الكائن الأول ، عندما أضعه في الثاني.

إذن ، المخطط هو:

"Parent" with relationship "child" One to One
Create Child 1, set parent. Save - OK
Create Child 2, set parent. Save - Error, Child 1.Parent == nil
(behind the scene child 2 did nullify child 1 parent)

تغيير العلاقة في الوالد من واحد إلى واحد إلى العديد إلى واحد حل هذه المهمة.




أنا استخدم siphon ، جرب هذا:

os-mac  
ide-X






iphone objective-c ios core-data