iphone Core Data chưa được giải quyết trong khi lưu


169

Tôi nhận được một thông báo lỗi lạ từ dữ liệu cốt lõi khi cố lưu nhưng vấn đề là lỗi không thể lặp lại được (nó xuất hiện vào những thời điểm khác nhau khi thực hiện các tác vụ khác nhau)

thông báo lỗi:

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.)"
);
}

và phương thức tạo ra lỗi là:

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

Bất kỳ ý tưởng cho lý do của tin nhắn này? cho rằng nó xuất hiện vào những thời điểm ngẫu nhiên


Điều này có thể giúp bạn: "Xử lý lỗi dữ liệu iPhone Core dữ liệu xử lý lỗi" stackoverflow.com/questions/2262704/ từ
Julian Fahrenkrug

Câu trả lời:


296

Nó có nghĩa là có một tài sản bắt buộc đã được chỉ định không. Trong * .xcodatamodel của bạn, hãy chọn hộp "tùy chọn" hoặc khi bạn đang lưu vào ManagedObjectContext, hãy đảm bảo rằng các thuộc tính của bạn được điền vào.

Nếu bạn gặp thêm lỗi sau khi thay đổi mã cho phù hợp với hai yêu cầu, hãy thử làm sạch bản dựng và xóa ứng dụng khỏi thiết bị iPhone Simulator / iPhone của bạn. Thay đổi mô hình của bạn có thể xung đột với việc thực hiện mô hình cũ.

Biên tập:

Tôi gần như đã quên ở đây tất cả các mã lỗi mà Core Data phát sinh: Tham chiếu hằng số dữ liệu lõi Tôi đã gặp sự cố với điều này trước đây và tôi nhận ra rằng tôi đã bỏ chọn hộp tùy chọn chính xác. Khó khăn như vậy để tìm ra vấn đề. Chúc may mắn.


2
Điều này đã giải quyết nó cho tôi. Cũng lưu ý rằng ít nhất theo kinh nghiệm của tôi mặc dù nó không được lưu vào tệp sqlite, nhưng những thay đổi đã đi vào bối cảnh. Vì vậy, hành vi có thể thất thường khi điều này xảy ra.
nickthedude

Tôi không thể hiểu nguyên nhân gốc rễ nhưng tôi đã làm cho vấn đề biến mất bằng cách làm cho tất cả các thuộc tính là tùy chọn.
Michael Osofsky

Bạn đã thử mã của Charles chưa, nó sẽ cho bạn biết lĩnh vực nào là vấn đề.
David Wong

233

Tôi đã vật lộn với điều này một chút trong bản thân mình. Vấn đề thực sự ở đây là việc gỡ lỗi mà bạn gặp phải không cho bạn biết vấn đề là gì. Lý do cho điều này là do CoreData sẽ đặt một mảng các đối tượng NSError vào đối tượng NSError "cấp cao nhất" mà nó trả về nếu có nhiều hơn một vấn đề (Đây là lý do tại sao bạn thấy lỗi 1560, cho biết nhiều vấn đề và một mảng lỗi 1570s). Dường như CoreData có một số khóa mà nó sử dụng để xử lý thông tin trong lỗi mà nó trả về nếu có vấn đề sẽ cung cấp cho bạn nhiều thông tin hữu ích hơn (chẳng hạn như lỗi thực thể xảy ra, mối quan hệ / thuộc tính bị thiếu, v.v. ). Các khóa bạn sử dụng để kiểm tra từ điển userInfo có thể được tìm thấy trong các tài liệu tham khảo ở đây .

Đây là khối mã tôi sử dụng để nhận đầu ra hợp lý từ lỗi được trả về trong quá trình lưu:

    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]);
        }
    }

Nó sẽ tạo ra kết quả đầu ra cho bạn biết các trường bị thiếu, điều này giúp khắc phục sự cố dễ dàng hơn để giải quyết.


Cảm ơn rất nhiều cho mã này. Nó làm cho việc theo dõi vấn đề CoreData thực sự đơn giản hơn nhiều.
MiKL

21

Tôi sẽ đưa ra câu trả lời này như một câu trả lời, mặc dù nó thực sự là một sự tô điểm cho đoạn trích của Charles. Đầu ra thẳng từ NSLog có thể là một mớ hỗn độn để đọc và diễn giải, vì vậy tôi muốn ném vào một khoảng trắng và gọi ra giá trị của một số khóa 'userInfo' quan trọng.

Đây là phiên bản của phương pháp tôi đang sử dụng. ('_ SharedManagedObjectContext' là một #define cho '[[[UIApplication sharedApplication] ủy nhiệm] 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;
}

Điều này cho phép tôi thấy giá trị của 'NSValidationErrorKey', khi tôi gặp phải sự cố từ OP, đã chỉ trực tiếp đến các thực thể Dữ liệu lõi không tùy chọn mà tôi đã quên đặt trước khi thử lưu.


Cũng rất hữu ích. Đặc biệt khi bạn nhận được chuỗi mô tả thực thể dữ liệu lõi \ n \ n \ n này.
Lukasz

Khéo léo. 'tin nhắn' không được sử dụng btw.
pojo

0

Vấn đề khiến tôi cảm động, khi tôi lưu bản ghi thứ hai vào CoreData. Tất cả các trường không phải là tùy chọn (mối quan hệ) cũng được điền mà không có con số nào, nhưng trong đầu ra lỗi tôi nhận thấy, một trong các trường trong đối tượng được lưu đầu tiên đã trở thành con số không. Lạ một chút? Nhưng lý do khá tầm thường - mối quan hệ một đối một sẽ vô hiệu hóa đối tượng thứ nhất, khi tôi đặt nó vào lần thứ hai.

Vì vậy, kế hoạch là:

"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)

Thay đổi mối quan hệ trong Cha mẹ từ Một thành Một thành Nhiều thành Một đã giải quyết nhiệm vụ này.


0

Tôi có thuộc tính tạm thời của loại int không phải là tùy chọn. Rõ ràng, khi nó được đặt thành 0, 1570 xuất hiện lỗi. Chỉ cần thay đổi tất cả các thuộc tính thoáng qua của tôi để tùy chọn. Logic Nil-check có thể được thực hiện trong mã nếu cần thiết.


0

Tôi có nghĩa là mô hình của bạn không thể xác thực, điều này có thể xảy ra vì một số lý do: tài sản không được sử dụng trong mô hình của bạn, thiếu giá trị được đánh dấu là bắt buộc. Để hiểu rõ hơn về chính xác những gì đã sai, hãy đặt một điểm dừng ở nơi bạn đã sẵn sàng để lưu đối tượng của mình và gọi một trong các validateFor...biến thể của phương thức, như:

po [myObject validateForInsert]

Thông tin chi tiết hơn về vấn đề là trong mô tả lỗi. Xác nhận thành công có nghĩa là bạn sẽ không nhận được đầu ra.


0

Nó đã giúp đỡ tôi. Kiểm tra cái này quá.

Chọn hộp tùy chọn trong các đối tượng * .xcodatamodel của bạn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.