NSError: inCaseLog + inCasePresent
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
#import "StoreCoordinator.h"
|
||||
#import "SettingsFeeds+DragDrop.h"
|
||||
#import "NSURL+Ext.h"
|
||||
#import "NSError+Ext.h"
|
||||
|
||||
@interface AppHook()
|
||||
@property (strong) NSWindowController *prefWindow;
|
||||
@@ -119,10 +120,8 @@
|
||||
if (_persistentContainer == nil) {
|
||||
_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"DBv1"];
|
||||
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
|
||||
if (error != nil) {
|
||||
NSLog(@"Couldn't read NSPersistentContainer: %@, %@", error, error.userInfo);
|
||||
if ([error inCaseLog:"Couldn't read NSPersistentContainer"])
|
||||
abort();
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
@@ -133,7 +132,7 @@
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
|
||||
NSManagedObjectContext *context = self.persistentContainer.viewContext;
|
||||
if (![context commitEditing]) {
|
||||
NSLog(@"%@:%@ unable to commit editing to terminate", [self class], NSStringFromSelector(_cmd));
|
||||
NSLogCaller(@"unable to commit editing to terminate");
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
if (!context.hasChanges) {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#import "NSFetchRequest+Ext.h"
|
||||
#import "NSError+Ext.h"
|
||||
|
||||
@implementation NSFetchRequest (Ext)
|
||||
|
||||
@@ -28,7 +29,7 @@
|
||||
- (NSArray*)fetchAllRows:(NSManagedObjectContext*)moc {
|
||||
NSError *err;
|
||||
NSArray *fetchResults = [moc executeFetchRequest:self error:&err];
|
||||
if (err) NSLog(@"ERROR: Fetch request failed: %@", err);
|
||||
[err inCaseLog:"Fetch request failed"];
|
||||
//NSLog(@"%@ ==> %@", self, fetchResults); // debugging
|
||||
return fetchResults;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#import "FaviconDownload.h"
|
||||
#import "Feed+Ext.h"
|
||||
#import "NSURL+Ext.h"
|
||||
#import "NSError+Ext.h"
|
||||
#import "NSFetchRequest+Ext.h"
|
||||
|
||||
@implementation StoreCoordinator
|
||||
@@ -52,19 +53,14 @@
|
||||
@param flag If @c YES save any parent context as well (recursive).
|
||||
*/
|
||||
+ (void)saveContext:(NSManagedObjectContext*)context andParent:(BOOL)flag {
|
||||
// Performs the save action for the application, which is to send the save: message to the application's managed object context. Any encountered errors are presented to the user.
|
||||
if (![context commitEditing]) {
|
||||
NSLog(@"%@:%@ unable to commit editing before saving", [self class], NSStringFromSelector(_cmd));
|
||||
}
|
||||
if (![context commitEditing])
|
||||
NSLogCaller(@"unable to commit editing before saving");
|
||||
NSError *error = nil;
|
||||
if (context.hasChanges && ![context save:&error]) {
|
||||
// Customize this code block to include application-specific recovery steps.
|
||||
[NSApp presentError:error];
|
||||
}
|
||||
if (flag && context.parentContext) {
|
||||
if (context.hasChanges && ![context save:&error])
|
||||
[error inCasePresent:NSApp];
|
||||
if (flag && context.parentContext)
|
||||
[self saveContext:context.parentContext andParent:flag];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Options
|
||||
@@ -284,7 +280,7 @@
|
||||
bdr.resultType = NSBatchDeleteResultTypeCount;
|
||||
NSError *err;
|
||||
NSBatchDeleteResult *res = [moc executeRequest:bdr error:&err];
|
||||
if (err) NSLog(@"%@", err);
|
||||
[err inCaseLog:"Couldn't delete batch"];
|
||||
return [res.result unsignedIntegerValue];
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#import "Constants.h"
|
||||
#import "NSDate+Ext.h"
|
||||
#import "NSView+Ext.h"
|
||||
#import "NSError+Ext.h"
|
||||
|
||||
#pragma mark - Helper
|
||||
|
||||
@@ -98,9 +99,7 @@ static NSInteger RadioGroupSelection(NSView *view) {
|
||||
RSXMLData *xml = [[RSXMLData alloc] initWithData:data url:url];
|
||||
RSOPMLParser *parser = [RSOPMLParser parserWithXMLData:xml];
|
||||
[parser parseAsync:^(RSOPMLItem * _Nullable doc, NSError * _Nullable error) {
|
||||
if (error) {
|
||||
[NSApp presentError:error];
|
||||
} else {
|
||||
if (![error inCasePresent:NSApp]) {
|
||||
for (RSOPMLItem *itm in doc.children) {
|
||||
block(itm);
|
||||
}
|
||||
@@ -250,7 +249,7 @@ static NSInteger RadioGroupSelection(NSView *view) {
|
||||
NSData *xml = [doc XMLDataWithOptions:NSXMLNodePreserveAttributeOrder | NSXMLNodePrettyPrint];
|
||||
[xml writeToURL:url options:NSDataWritingAtomic error:&error];
|
||||
}
|
||||
if (error) [NSApp presentError:error];
|
||||
[error inCasePresent:NSApp];
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>13404</string>
|
||||
<string>13435</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.news</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
@@ -22,9 +22,15 @@
|
||||
|
||||
@import Cocoa;
|
||||
|
||||
/// Log error message and prepend calling class and calling method.
|
||||
#define NSLogCaller(desc) { NSLog(@"%@:%@ %@", [self class], NSStringFromSelector(_cmd), desc); }
|
||||
|
||||
@interface NSError (Ext)
|
||||
// Generators
|
||||
+ (instancetype)statusCode:(NSInteger)code reason:(nullable NSString*)reason;
|
||||
+ (instancetype)canceledByUser;
|
||||
+ (instancetype)feedURLNotFound:(NSURL*)url;
|
||||
// User notification
|
||||
- (BOOL)inCaseLog:(nullable const char*)title;
|
||||
- (BOOL)inCasePresent:(NSApplication*)app;
|
||||
@end
|
||||
|
||||
@@ -126,4 +126,21 @@ static const char* CodeDescription(NSInteger code) {
|
||||
return RSXMLMakeErrorWrongParser(RSXMLErrorExpectingFeed, RSXMLErrorExpectingHTML, url);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// | MARK: - User notification
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
/// Will only execute and return @c YES if @c error @c != @c nil . Log error message to console.
|
||||
- (BOOL)inCaseLog:(nullable const char*)title {
|
||||
if (title) printf("ERROR %s: %s, %s\n", title, self.description.UTF8String, self.userInfo.description.UTF8String);
|
||||
else printf("%s, %s\n", self.description.UTF8String, self.userInfo.description.UTF8String);
|
||||
return YES;
|
||||
}
|
||||
|
||||
/// Will only execute and return @c YES if @c error @c != @c nil . Present application modal error message.
|
||||
- (BOOL)inCasePresent:(NSApplication*)app {
|
||||
[app presentError:self];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#import "NSURL+Ext.h"
|
||||
#import "UserPrefs.h" // appName in +faviconsCacheURL
|
||||
#import "NSError+Ext.h"
|
||||
|
||||
@implementation NSURL (Ext)
|
||||
|
||||
@@ -50,9 +51,8 @@
|
||||
- (BOOL)mkdir {
|
||||
if ([self existsAndIsDir:YES]) return NO;
|
||||
NSError *err;
|
||||
BOOL b = [[NSFileManager defaultManager] createDirectoryAtURL:self withIntermediateDirectories:YES attributes:nil error:&err];
|
||||
if (err) [NSApp presentError:err];
|
||||
return b;
|
||||
[[NSFileManager defaultManager] createDirectoryAtURL:self withIntermediateDirectories:YES attributes:nil error:&err];
|
||||
return ![err inCasePresent:NSApp];
|
||||
}
|
||||
|
||||
/// Delete file or folder at URL. If item does not exist, this method does nothing.
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#import "FeedGroup+Ext.h"
|
||||
#import "UpdateScheduler.h"
|
||||
#import "SettingsFeedsView.h"
|
||||
#import "NSError+Ext.h"
|
||||
|
||||
@interface SettingsFeeds ()
|
||||
@property (strong) SettingsFeedsView *view; // override super
|
||||
@@ -100,7 +101,7 @@
|
||||
|
||||
NSError *error;
|
||||
[self.dataStore fetchWithRequest:nil merge:NO error:&error];
|
||||
if (error) [NSApp presentError:error];
|
||||
[error inCasePresent:NSApp];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user