iphone Core Data Kesalahan yang belum terselesaikan saat menyimpan

169

Saya mendapatkan pesan kesalahan aneh dari data inti saat mencoba menyimpan tetapi masalah bahwa kesalahan tidak dapat direproduksi (muncul pada waktu yang berbeda saat melakukan tugas yang berbeda)

pesan kesalahan:

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

dan metode yang menghasilkan kesalahan adalah:

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

ada ide untuk alasan pesan ini? memberikan bahwa itu muncul secara acak

Ahmed Kotb
sumber
Ini mungkin membantu Anda: "Penanganan Kesalahan Data" Data Inti iPhone " stackoverflow.com/questions/2262704/…
Johannes Fahrenkrug

Jawaban:

296

Artinya ada properti wajib yang telah ditetapkan nihil. Baik di * .xcodatamodel Anda, centang kotak "opsional" atau ketika Anda menyimpan ke managedObjectContext pastikan bahwa properti Anda sudah diisi.

Jika Anda mendapatkan kesalahan lebih lanjut setelah mengubah kode Anda agar sesuai dengan dua persyaratan, coba bersihkan build Anda dan hapus aplikasi dari perangkat iPhone Simulator / iPhone Anda. Perubahan model Anda dapat bertentangan dengan implementasi model lama.

Edit:

Saya hampir lupa di sini semua kode kesalahan yang dikeluarkan Core Data : Core Data Constants Reference Saya pernah mengalami masalah dengan ini sebelumnya dan saya menyadari bahwa saya tidak mencentang kotak opsional yang benar. Kesulitan seperti mencari tahu masalahnya. Semoga berhasil.

David Wong
sumber
2
Ini menyelesaikannya untuk saya. Juga perhatikan bahwa setidaknya dalam pengalaman saya meskipun tidak disimpan ke file sqlite, perubahannya memang masuk ke dalam konteks. Jadi perilakunya mungkin tidak menentu ketika ini terjadi.
nickthedude
Saya tidak dapat memahami penyebab dasarnya, tetapi saya berhasil mengatasi masalah dengan menjadikan semua properti opsional.
Michael Osofsky
Apakah Anda mencoba kode Charles, itu akan memberi tahu Anda bidang mana yang menjadi masalah.
David Wong
233

Saya berjuang dengan ini untuk sementara waktu. Masalah sebenarnya di sini adalah bahwa debugging yang Anda miliki tidak menunjukkan kepada Anda apa masalahnya. Alasan untuk ini adalah karena CoreData akan meletakkan array objek NSError di objek NSError "level atas" yang dikembalikan jika ada lebih dari satu masalah (Inilah sebabnya mengapa Anda melihat kesalahan 1560, yang menunjukkan banyak masalah, dan berbagai kesalahan 1570-an). Tampaknya CoreData memiliki beberapa kunci yang digunakannya untuk menyimpan informasi dalam kesalahan yang ia kembalikan jika ada masalah yang akan memberi Anda informasi yang lebih berguna (Seperti entitas tempat kesalahan terjadi, hubungan / atribut yang hilang, dll. ). Kunci yang Anda gunakan untuk memeriksa kamus userInfo dapat ditemukan di dokumen rujukan di sini .

Ini adalah blok kode yang saya gunakan untuk mendapatkan hasil yang masuk akal dari kesalahan yang dikembalikan selama penyimpanan:

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

Ini akan menghasilkan output yang memberitahu Anda bidang yang hilang, yang membuat memperbaiki masalah secara signifikan lebih mudah untuk ditangani.

Charles
sumber
Terima kasih banyak untuk kode ini. Itu membuat pelacakan masalah CoreData memang jauh lebih sederhana.
MiKL
21

Saya memberikan ini sebagai jawaban, meskipun itu benar-benar lebih dari potongan Charles. Keluaran langsung dari NSLog bisa menjadi berantakan untuk dibaca dan ditafsirkan, jadi saya suka melempar spasi putih dan memanggil nilai beberapa kunci 'userInfo' yang penting.

Inilah versi metode yang saya gunakan. ('_sharedManagedObjectContext' adalah #define untuk '[[[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;
}

Ini memungkinkan saya untuk melihat nilai untuk 'NSValidationErrorKey', yang, ketika saya menemukan masalah dari OP, menunjuk langsung ke entitas Data Core non-opsional yang saya lupa atur sebelum mencoba menyimpan.

clozach
sumber
Juga sangat bermanfaat. Khususnya ketika Anda mendapatkan string uraian entitas data inti ini \ n \ n \ n.
Lukasz
Rapi. 'pesan' tidak digunakan btw.
pojo
0

Masalahnya menyentuh saya, ketika saya menyimpan catatan kedua ke CoreData. Semua bidang tidak opsional (hubungan) diisi tanpa nihil juga, tetapi dalam output kesalahan saya perhatikan, bahwa salah satu bidang di objek yang disimpan pertama telah menjadi nol. Aneh sedikit? Tapi alasannya cukup sepele - hubungan satu ke satu yang membatalkan objek pertama, ketika saya mengaturnya di yang kedua.

Jadi, skemanya adalah:

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

Mengubah hubungan di Induk dari Satu ke Satu ke Banyak ke Satu menyelesaikan tugas ini.

HotJard
sumber
0

Saya memiliki properti sementara tipe int yang bukan opsional. Jelas, ketika diatur ke 0, 1570 kesalahan muncul. Baru saja mengubah semua properti sementara saya menjadi opsional. Logika nil-check dapat diimplementasikan dalam kode jika perlu.

Anton Plebanovich
sumber
0

Maksud saya, model Anda gagal divalidasi, yang dapat terjadi karena sejumlah alasan: properti yang tidak digunakan dalam model Anda, nilai yang hilang yang ditandai sebagaimana diperlukan. Untuk mendapatkan pemahaman yang lebih baik tentang kesalahan sebenarnya, letakkan breakpoint di tempat Anda siap untuk menyimpan objek Anda, dan panggil salah satu validateFor...varian metode, seperti:

po [myObject validateForInsert]

Informasi lebih rinci tentang masalah ini ada dalam deskripsi kesalahan. Validasi yang berhasil berarti Anda tidak akan mendapatkan hasil.

kkodev
sumber
0

Itu membantu saya. Periksa yang ini juga.

Centang kotak opsional di objek * .xcodatamodel Anda

ssowri1
sumber