2009-08-16 37 views
164

Tôi nhận được một thông báo lỗi lạ từ dữ liệu cốt lõi khi cố gắng tiết kiệm nhưng vấn đề rằng lỗi là không tái sản xuất (nó xuất hiện vào những thời điểm khác nhau khi thực hiện nhiệm vụ khác nhau)iphone Core Data Chưa giải quyết lỗi khi lưu

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 pháp mà tạo ra lỗi này 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 nào về lý do của thông báo này? cho rằng nó xuất hiện vào các thời điểm ngẫu nhiên

+0

Điều này có thể giúp bạn: "Dữ liệu lõi iPhone" Sản xuất "Xử lý lỗi" http://stackoverflow.com/questions/2262704/iphone-core-data-production-error-handling/3510918#3510918 –

Trả lời

286

Điều đó có nghĩa là có một thuộc tính bắt buộc đã được chỉ định không. Hoặc 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.

Nếu bạn gặp phải các lỗi khác 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 của bạn 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 triển khai mô hình cũ.

Edit:

Tôi gần như quên đây là tất cả các mã lỗi mà Core Data spits ra: Core Data Constants Reference tôi đã gặp rắc rối với điều này trước và tôi nhận ra rằng tôi bỏ chọn đúng hộp tùy chọn. Khó khăn như vậy tìm ra vấn đề. Chúc may mắn.

+1

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

+0

Tôi không thể đạt được nguyên nhân gốc rễ nhưng tôi đã cố gắng giải quyết vấn đề bằng cách thực hiện tất cả các thuộc tính tùy chọn. –

+0

Bạn đã thử mã của Charles, nó sẽ cho bạn biết trường nào là vấn đề. –

232

Tôi đã vật lộn với điều này trong một thời gian ngắn. Vấn đề thực sự ở đây là việc gỡ lỗi bạn đã không cho bạn thấy vấn đề là gì. Lý do là vì CoreData sẽ đặt một mảng các đối tượng NSError trong đối tượng NSError "cấp cao nhất" nó trả về nếu có nhiều 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 1570). Có vẻ như CoreData có một số khóa mà nó sử dụng để lưu trữ thông tin trong lỗi nó trả về nếu có vấn đề sẽ cung cấp cho bạn thông tin hữu ích hơn (chẳng hạn như thực thể xảy ra lỗi, mối quan hệ/thuộc tính bị thiếu, v.v ...). Các phím bạn sử dụng để kiểm tra từ điển userInfo có thể được tìm thấy trong the reference docs here.

Đây là khối mã tôi sử dụng để có được đầu ra hợp lý từ các lỗi trở lại trong một tiết kiệm:

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 cho bạn biết các lĩnh vực mà là ở thiếu, mà làm cho sửa chữa các vấn đề dễ dàng hơn để giải quyết.

+0

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

+0

Cảm ơn bạn, tôi đã đăng ký đoạn mã của bạn cho Xcode của tôi ... :) – barley

21

Tôi đang ném 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 chỉnh sửa 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à giải thích, vì vậy tôi muốn ném vào một số 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 đã sử dụng. ('_sharedManagedObjectContext' là một #define cho '[[[UIApplication sharedApplication] đại biểu] 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; 
} 

này cho phép tôi để xem giá trị cho 'NSValidationErrorKey', mà khi tôi gặp phải vấn đề từ OP, chỉ trực tiếp đến các thực thể Core Data không bắt buộc mà tôi đã quên đặt trước khi cố lưu.

+0

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

+0

Gọn gàng. 'message' không được sử dụng btw. – pojo

0

Sự cố đã xảy ra với tôi, khi tôi lưu bản ghi thứ hai vào CoreData. Tất cả các trường không bắt buộc (mối quan hệ) đã được lấp đầy mà không có nil là tốt, nhưng trong đầu ra lỗi tôi nhận thấy, rằng một trong các trường trong đối tượng đã lưu đầu tiên đã trở thành không. Lạ một chút? Nhưng lý do là khá tầm thường - một mối quan hệ mà vô hiệu hóa đối tượng đầu tiên, khi tôi đặt nó trong lần thứ hai.

Vì vậy, chương trình này 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 Chánh từ One to One để Nhiều One 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, lỗi 1570 xuất hiện. Chỉ cần thay đổi tất cả các thuộc tính tạm thời của tôi thành tùy chọn. Nil-check logic 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 sử dụng trong mô hình của bạn, thiếu giá trị được đánh dấu là bắt buộc. Để có được một sự hiểu biết tốt hơn về những gì chính xác đã xảy ra, đặt một breakpoint ở một nơi mà bạn đã sẵn sàng để cứu đối tượng của bạn, và gọi một trong những validateFor... biến phương pháp, như:

po [myObject validateForInsert]

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

Các vấn đề liên quan