iphone Core Data Unresolved error error ขณะบันทึก


169

ฉันได้รับข้อความแสดงข้อผิดพลาดแปลก ๆ จากข้อมูลหลักเมื่อพยายามบันทึก แต่ปัญหาที่ข้อผิดพลาดนั้นไม่สามารถทำซ้ำได้ (ปรากฏในเวลาต่างกันเมื่อทำงานต่างกัน)

ข้อความแสดงข้อผิดพลาด:

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
    }
}

ความคิดใด ๆ สำหรับเหตุผลของข้อความนี้? ให้มันปรากฏขึ้นในเวลาสุ่ม


สิ่งนี้อาจช่วยคุณได้: การจัดการข้อผิดพลาด "iPhone Core Data“ การผลิต” ข้อผิดพลาด" stackoverflow.com/questions/2262704/ …
Johannes Fahrenkrug

คำตอบ:


296

มันหมายความว่ามีคุณสมบัติที่จำเป็นได้รับมอบหมายเป็นศูนย์ ไม่ว่าจะใน * .xcodatamodel ของคุณให้ทำเครื่องหมายในช่อง "ตัวเลือก" หรือเมื่อคุณบันทึกลงใน managedObjectContext ให้แน่ใจว่าคุณสมบัติของคุณเต็มแล้ว

หากคุณได้รับข้อผิดพลาดเพิ่มเติมหลังจากเปลี่ยนรหัสเพื่อให้เหมาะกับข้อกำหนดสองข้อลองทำความสะอาดโครงสร้างของคุณและลบแอปพลิเคชันออกจากอุปกรณ์ iPhone Simulator / iPhone ของคุณ การเปลี่ยนแปลงรูปแบบของคุณอาจขัดแย้งกับการใช้รูปแบบเก่า

แก้ไข:

ฉันเกือบลืมรหัสข้อผิดพลาดทั้งหมดที่ Core Data คายออกมา: การอ้างอิงค่าคงที่ของคอร์ข้อมูล ฉันมีปัญหากับสิ่งนี้มาก่อน ปัญหาดังกล่าวเป็นการค้นหาปัญหา โชคดี.


2
วิธีนี้แก้ไขได้สำหรับฉัน โปรดทราบด้วยอย่างน้อยในประสบการณ์ของฉันแม้ว่าจะไม่ได้บันทึกลงในไฟล์ sqlite การเปลี่ยนแปลงก็นำไปสู่บริบท ดังนั้นพฤติกรรมอาจไม่แน่นอนเมื่อเกิดเหตุการณ์เช่นนี้
nickthedude

ฉันไม่เข้าใจสาเหตุที่แท้จริง แต่ฉันจัดการเพื่อทำให้ปัญหาหายไปโดยทำให้คุณสมบัติทั้งหมดเป็นตัวเลือก
Michael Osofsky

คุณลองใช้รหัสของชาร์ลส์แล้วมันจะบอกคุณว่าฟิลด์ใดเป็นปัญหา
David Wong

233

ฉันดิ้นรนกับสิ่งนี้สักพัก ปัญหาจริงที่นี่คือการแก้ไขข้อบกพร่องที่คุณไม่ได้แสดงให้คุณเห็นว่าปัญหาคืออะไร เหตุผลนี้เป็นเพราะ CoreData จะใส่อาร์เรย์ของวัตถุ NSError ในวัตถุ NSError "ระดับสูงสุด" ที่ส่งคืนหากมีปัญหามากกว่าหนึ่งปัญหา (นี่คือสาเหตุที่คุณเห็นข้อผิดพลาด 1560 ซึ่งบ่งชี้ถึงปัญหาหลายข้อและอาร์เรย์ข้อผิดพลาด ยุค 1570) ปรากฏว่า 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 ง่ายขึ้นมาก
MiKL

21

ฉันโยนคำตอบนี้ลงไปถึงแม้ว่ามันจะเป็นตัวอย่างของชาร์ลส์มากกว่า เอาท์พุทตรงจาก NSLog อาจเป็นระเบียบในการอ่านและตีความดังนั้นฉันชอบที่จะโยนในพื้นที่สีขาวและเรียกค่าคีย์ 'userInfo' ที่สำคัญบางอย่าง

นี่คือวิธีการที่ฉันใช้อยู่ ('_sharedManagedObjectContext' คือ #define สำหรับ '[[[UIApplication sharedApplication] ผู้รับมอบสิทธิ์] 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' ซึ่งเมื่อฉันพบปัญหาจาก OP ชี้ไปที่เอนทิตี Core Data ที่ไม่ใช่ตัวเลือกที่ฉันลืมตั้งค่าก่อนที่จะบันทึก


ยังมีประโยชน์มาก พิเศษเมื่อคุณได้รับสตริงคำอธิบายเอนทิตีข้อมูลหลัก raw \ n \ n \ n
Lukasz

เรียบร้อย ข้อความ 'ไม่ได้ใช้ btw
pojo

0

ปัญหาแตะต้องฉันเมื่อฉันบันทึกรายการที่สองใน 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)

การเปลี่ยนความสัมพันธ์ในพาเรนต์จากหนึ่งเป็นหนึ่งเป็นมากเป็นหนึ่งแก้ไขงานนี้


0

ฉันมีคุณสมบัติชั่วคราวของประเภท int ที่ไม่ใช่ทางเลือก เห็นได้ชัดว่าเมื่อตั้งค่าเป็น 0 ข้อผิดพลาด 1570 จะปรากฏขึ้น เพิ่งเปลี่ยนคุณสมบัติชั่วคราวทั้งหมดของฉันเป็นตัวเลือก ตรรกะการตรวจสอบ Nil สามารถนำมาใช้ในรหัสหากจำเป็น


0

ฉันหมายความว่าแบบจำลองของคุณไม่สามารถตรวจสอบความถูกต้องซึ่งอาจเกิดขึ้นได้จากหลายสาเหตุ: คุณสมบัติที่ไม่ได้ใช้ในแบบจำลองของคุณมูลค่าที่ขาดหายไปซึ่งระบุว่าจำเป็น หากต้องการทำความเข้าใจกับสิ่งที่ผิดพลาดให้วางเบรกพอยต์ในที่ที่คุณพร้อมที่จะบันทึกวัตถุของคุณและเรียกหนึ่งในvalidateFor...วิธีการที่หลากหลายเช่น:

po [myObject validateForInsert]

ข้อมูลรายละเอียดเพิ่มเติมเกี่ยวกับปัญหาอยู่ในคำอธิบายข้อผิดพลาด การตรวจสอบที่ประสบความสำเร็จหมายความว่าคุณจะไม่ได้รับผลลัพธ์


0

มันช่วยฉัน ตรวจสอบอันนี้ด้วย

ทำเครื่องหมายในช่องตัวเลือกในวัตถุ * .xcodatamodel ของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.