아이폰 코어 데이터 "프로덕션" 오류 처리
Apple에서 제공한 예제 코드에서 핵심 데이터 오류를 처리하는 방법에 대한 참조를 보았습니다.I.e:
NSError *error = nil;
if (![context save:&error]) {
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
*/
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
하지만 그것을 어떻게 구현해야 하는지에 대한 어떤 예도 없습니다.
위의 방법을 설명하는 실제 "생산" 코드를 가지고 있는 사람(또는 제게 방향을 알려줄 수 있는 사람)이 있습니까?
이것은 제가 아이폰에서 검증 오류를 처리하고 표시하기 위해 고안한 일반적인 방법 중 하나입니다.하지만 마커스의 말이 옳습니다.메시지를 좀 더 사용하기 쉽게 조정할 수 있습니다.그러나 이를 통해 어떤 필드가 검증되지 않았는지, 그 이유를 확인할 수 있습니다.
- (void)displayValidationError:(NSError *)anError {
if (anError && [[anError domain] isEqualToString:@"NSCocoaErrorDomain"]) {
NSArray *errors = nil;
// multiple errors?
if ([anError code] == NSValidationMultipleErrorsError) {
errors = [[anError userInfo] objectForKey:NSDetailedErrorsKey];
} else {
errors = [NSArray arrayWithObject:anError];
}
if (errors && [errors count] > 0) {
NSString *messages = @"Reason(s):\n";
for (NSError * error in errors) {
NSString *entityName = [[[[error userInfo] objectForKey:@"NSValidationErrorObject"] entity] name];
NSString *attributeName = [[error userInfo] objectForKey:@"NSValidationErrorKey"];
NSString *msg;
switch ([error code]) {
case NSManagedObjectValidationError:
msg = @"Generic validation error.";
break;
case NSValidationMissingMandatoryPropertyError:
msg = [NSString stringWithFormat:@"The attribute '%@' mustn't be empty.", attributeName];
break;
case NSValidationRelationshipLacksMinimumCountError:
msg = [NSString stringWithFormat:@"The relationship '%@' doesn't have enough entries.", attributeName];
break;
case NSValidationRelationshipExceedsMaximumCountError:
msg = [NSString stringWithFormat:@"The relationship '%@' has too many entries.", attributeName];
break;
case NSValidationRelationshipDeniedDeleteError:
msg = [NSString stringWithFormat:@"To delete, the relationship '%@' must be empty.", attributeName];
break;
case NSValidationNumberTooLargeError:
msg = [NSString stringWithFormat:@"The number of the attribute '%@' is too large.", attributeName];
break;
case NSValidationNumberTooSmallError:
msg = [NSString stringWithFormat:@"The number of the attribute '%@' is too small.", attributeName];
break;
case NSValidationDateTooLateError:
msg = [NSString stringWithFormat:@"The date of the attribute '%@' is too late.", attributeName];
break;
case NSValidationDateTooSoonError:
msg = [NSString stringWithFormat:@"The date of the attribute '%@' is too soon.", attributeName];
break;
case NSValidationInvalidDateError:
msg = [NSString stringWithFormat:@"The date of the attribute '%@' is invalid.", attributeName];
break;
case NSValidationStringTooLongError:
msg = [NSString stringWithFormat:@"The text of the attribute '%@' is too long.", attributeName];
break;
case NSValidationStringTooShortError:
msg = [NSString stringWithFormat:@"The text of the attribute '%@' is too short.", attributeName];
break;
case NSValidationStringPatternMatchingError:
msg = [NSString stringWithFormat:@"The text of the attribute '%@' doesn't match the required pattern.", attributeName];
break;
default:
msg = [NSString stringWithFormat:@"Unknown error (code %i).", [error code]];
break;
}
messages = [messages stringByAppendingFormat:@"%@%@%@\n", (entityName?:@""),(entityName?@": ":@""),msg];
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Validation Error"
message:messages
delegate:nil
cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
[alert show];
[alert release];
}
}
}
즐거운 시간 되세요.
당신의 응용 프로그램과 오류가 발생하는 위치에 따라 100% 다르기 때문에 아무도 당신에게 생산 코드를 보여주지 않을 것입니다.
개인적으로, 저는 이 오류가 개발 과정에서 99.9% 발생할 것이며, 이 오류를 수정할 때 생산 과정에서 발생할 가능성이 매우 낮기 때문에 이 오류를 확인할 수 있습니다.
사용자에게 경고를 표시한 후 복구할 수 없는 오류가 발생했으며 응용 프로그램이 종료될 것임을 알립니다.또한 개발자에게 문의하여 이 작업을 추적할 수 있도록 요청하는 게시판을 삽입할 수도 있습니다.
그런 다음 앱이 "크래시"되고 나중에 문제를 추적하는 데 사용할 수 있는 스택 추적을 생성하기 때문에 중단()을 그곳에 둡니다.
저는 여기 있는 아무도 오류를 처리해야 할 방식으로 처리하지 않는다는 것이 놀랍습니다.설명서를 보면 알 수 있습니다.
여기서 오류가 발생하는 일반적인 이유는 다음과 같습니다. * 장치의 공간이 부족합니다.장치가 잠겨 있을 때 사용 권한 또는 데이터 보호 때문에 영구 저장소에 액세스할 수 없습니다.스토어를 현재 모델 버전으로 마이그레이션할 수 없습니다.상위 디렉터리가 없거나 만들 수 없거나 쓸 수 없습니다.
따라서 코어 데이터 스택을 설정할 때 오류가 발견되면 UIWindow의 rootViewController를 스왑하여 사용자에게 장치가 가득 찼거나 보안 설정이 너무 높아서 이 앱이 작동하지 않을 수 있음을 명확하게 알려주는 UI를 표시합니다.또한 코어 데이터 스택을 다시 시도하기 전에 문제를 해결할 수 있도록 '다시 시도' 버튼을 제공합니다.
예를 들어, 사용자는 저장 공간을 확보하고, 내 앱으로 돌아가서 Try again 버튼을 누를 수 있습니다.
단언?정말?방에 개발자가 너무 많습니다!
온라인 튜토리얼 중에서 이러한 이유로 저장 작업이 실패할 수 있는 방법에 대해 언급하지 않은 튜토리얼이 많다는 점도 놀랍습니다.따라서 앱 저장 저장으로 인해 장치가 꽉 찼기 때문에 앱의 모든 저장 이벤트가 실패할 수 있습니다.
저는 이 공통 저장 기능이 훨씬 더 나은 해결책이라는 것을 알았습니다.
- (BOOL)saveContext {
NSError *error;
if (![self.managedObjectContext save:&error]) {
DDLogError(@"[%@::%@] Whoops, couldn't save managed object context due to errors. Rolling back. Error: %@\n\n", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error);
[self.managedObjectContext rollback];
return NO;
}
return YES;
}
저장이 실패할 때마다 NSManagedObjectContext가 롤백되므로 마지막 저장 이후 컨텍스트에서 수행된 모든 변경 내용이 재설정됩니다.따라서 위의 저장 기능을 사용하여 항상 변경 사항을 유지하는 것은 데이터를 쉽게 손실할 수 있으므로 가능한 한 빨리 정기적으로 주의해야 합니다.
데이터를 삽입할 경우 다른 변경 사항을 적용할 수 있는 느슨한 변형일 수 있습니다.
- (BOOL)saveContext {
NSError *error;
if (![self.managedObjectContext save:&error]) {
DDLogError(@"[%@::%@] Whoops, couldn't save. Removing erroneous object from context. Error: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), object.objectId, error);
[self.managedObjectContext deleteObject:object];
return NO;
}
return YES;
}
참고: 여기서 기록하는 데 CocoaLumberjack을 사용합니다.
이를 개선하는 방법에 대한 어떠한 의견도 환영합니다!
BR 크리스
저는 유용할 수 있는 @Johannes Fahrenkrug의 유용한 답변을 스위프트 버전으로 만들었습니다.
public func displayValidationError(anError:NSError?) -> String {
if anError != nil && anError!.domain.compare("NSCocoaErrorDomain") == .OrderedSame {
var messages:String = "Reason(s):\n"
var errors = [AnyObject]()
if (anError!.code == NSValidationMultipleErrorsError) {
errors = anError!.userInfo[NSDetailedErrorsKey] as! [AnyObject]
} else {
errors = [AnyObject]()
errors.append(anError!)
}
if (errors.count > 0) {
for error in errors {
if (error as? NSError)!.userInfo.keys.contains("conflictList") {
messages = messages.stringByAppendingString("Generic merge conflict. see details : \(error)")
}
else
{
let entityName = "\(((error as? NSError)!.userInfo["NSValidationErrorObject"] as! NSManagedObject).entity.name)"
let attributeName = "\((error as? NSError)!.userInfo["NSValidationErrorKey"])"
var msg = ""
switch (error.code) {
case NSManagedObjectValidationError:
msg = "Generic validation error.";
break;
case NSValidationMissingMandatoryPropertyError:
msg = String(format:"The attribute '%@' mustn't be empty.", attributeName)
break;
case NSValidationRelationshipLacksMinimumCountError:
msg = String(format:"The relationship '%@' doesn't have enough entries.", attributeName)
break;
case NSValidationRelationshipExceedsMaximumCountError:
msg = String(format:"The relationship '%@' has too many entries.", attributeName)
break;
case NSValidationRelationshipDeniedDeleteError:
msg = String(format:"To delete, the relationship '%@' must be empty.", attributeName)
break;
case NSValidationNumberTooLargeError:
msg = String(format:"The number of the attribute '%@' is too large.", attributeName)
break;
case NSValidationNumberTooSmallError:
msg = String(format:"The number of the attribute '%@' is too small.", attributeName)
break;
case NSValidationDateTooLateError:
msg = String(format:"The date of the attribute '%@' is too late.", attributeName)
break;
case NSValidationDateTooSoonError:
msg = String(format:"The date of the attribute '%@' is too soon.", attributeName)
break;
case NSValidationInvalidDateError:
msg = String(format:"The date of the attribute '%@' is invalid.", attributeName)
break;
case NSValidationStringTooLongError:
msg = String(format:"The text of the attribute '%@' is too long.", attributeName)
break;
case NSValidationStringTooShortError:
msg = String(format:"The text of the attribute '%@' is too short.", attributeName)
break;
case NSValidationStringPatternMatchingError:
msg = String(format:"The text of the attribute '%@' doesn't match the required pattern.", attributeName)
break;
default:
msg = String(format:"Unknown error (code %i).", error.code) as String
break;
}
messages = messages.stringByAppendingString("\(entityName).\(attributeName):\(msg)\n")
}
}
}
return messages
}
return "no error"
}`
언급URL : https://stackoverflow.com/questions/2262704/iphone-core-data-production-error-handling
'programing' 카테고리의 다른 글
다중 XMLHttpRequest를 사용하는 방법은 무엇입니까? (0) | 2023.08.18 |
---|---|
파서 오류: '_Default'는 클래스 'System'을 확장하지 않으므로 여기서 허용되지 않습니다.웹.UI.페이지' & 마스터형식 선언 (0) | 2023.08.18 |
PowerShell 경로에서 달러 기호 이스케이프가 작동하지 않음 (0) | 2023.08.18 |
PIL 이미지를 바이트 배열로 변환하시겠습니까? (0) | 2023.08.18 |
탭을 사용하여 텍스트 영역 들여쓰기 (0) | 2023.08.18 |