NSError: inCaseLog + inCasePresent

This commit is contained in:
relikd
2019-09-19 11:54:33 +02:00
parent 32f999b248
commit 9dbd761fe0
9 changed files with 44 additions and 25 deletions

View File

@@ -30,6 +30,7 @@
#import "StoreCoordinator.h" #import "StoreCoordinator.h"
#import "SettingsFeeds+DragDrop.h" #import "SettingsFeeds+DragDrop.h"
#import "NSURL+Ext.h" #import "NSURL+Ext.h"
#import "NSError+Ext.h"
@interface AppHook() @interface AppHook()
@property (strong) NSWindowController *prefWindow; @property (strong) NSWindowController *prefWindow;
@@ -119,10 +120,8 @@
if (_persistentContainer == nil) { if (_persistentContainer == nil) {
_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"DBv1"]; _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"DBv1"];
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) { [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
if (error != nil) { if ([error inCaseLog:"Couldn't read NSPersistentContainer"])
NSLog(@"Couldn't read NSPersistentContainer: %@, %@", error, error.userInfo);
abort(); abort();
}
}]; }];
} }
} }
@@ -133,7 +132,7 @@
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
NSManagedObjectContext *context = self.persistentContainer.viewContext; NSManagedObjectContext *context = self.persistentContainer.viewContext;
if (![context commitEditing]) { if (![context commitEditing]) {
NSLog(@"%@:%@ unable to commit editing to terminate", [self class], NSStringFromSelector(_cmd)); NSLogCaller(@"unable to commit editing to terminate");
return NSTerminateCancel; return NSTerminateCancel;
} }
if (!context.hasChanges) { if (!context.hasChanges) {

View File

@@ -21,6 +21,7 @@
// SOFTWARE. // SOFTWARE.
#import "NSFetchRequest+Ext.h" #import "NSFetchRequest+Ext.h"
#import "NSError+Ext.h"
@implementation NSFetchRequest (Ext) @implementation NSFetchRequest (Ext)
@@ -28,7 +29,7 @@
- (NSArray*)fetchAllRows:(NSManagedObjectContext*)moc { - (NSArray*)fetchAllRows:(NSManagedObjectContext*)moc {
NSError *err; NSError *err;
NSArray *fetchResults = [moc executeFetchRequest:self error:&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 //NSLog(@"%@ ==> %@", self, fetchResults); // debugging
return fetchResults; return fetchResults;
} }

View File

@@ -26,6 +26,7 @@
#import "FaviconDownload.h" #import "FaviconDownload.h"
#import "Feed+Ext.h" #import "Feed+Ext.h"
#import "NSURL+Ext.h" #import "NSURL+Ext.h"
#import "NSError+Ext.h"
#import "NSFetchRequest+Ext.h" #import "NSFetchRequest+Ext.h"
@implementation StoreCoordinator @implementation StoreCoordinator
@@ -52,18 +53,13 @@
@param flag If @c YES save any parent context as well (recursive). @param flag If @c YES save any parent context as well (recursive).
*/ */
+ (void)saveContext:(NSManagedObjectContext*)context andParent:(BOOL)flag { + (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])
if (![context commitEditing]) { NSLogCaller(@"unable to commit editing before saving");
NSLog(@"%@:%@ unable to commit editing before saving", [self class], NSStringFromSelector(_cmd));
}
NSError *error = nil; NSError *error = nil;
if (context.hasChanges && ![context save:&error]) { if (context.hasChanges && ![context save:&error])
// Customize this code block to include application-specific recovery steps. [error inCasePresent:NSApp];
[NSApp presentError:error]; if (flag && context.parentContext)
}
if (flag && context.parentContext) {
[self saveContext:context.parentContext andParent:flag]; [self saveContext:context.parentContext andParent:flag];
}
} }
@@ -284,7 +280,7 @@
bdr.resultType = NSBatchDeleteResultTypeCount; bdr.resultType = NSBatchDeleteResultTypeCount;
NSError *err; NSError *err;
NSBatchDeleteResult *res = [moc executeRequest:bdr error:&err]; NSBatchDeleteResult *res = [moc executeRequest:bdr error:&err];
if (err) NSLog(@"%@", err); [err inCaseLog:"Couldn't delete batch"];
return [res.result unsignedIntegerValue]; return [res.result unsignedIntegerValue];
} }

View File

@@ -28,6 +28,7 @@
#import "Constants.h" #import "Constants.h"
#import "NSDate+Ext.h" #import "NSDate+Ext.h"
#import "NSView+Ext.h" #import "NSView+Ext.h"
#import "NSError+Ext.h"
#pragma mark - Helper #pragma mark - Helper
@@ -98,9 +99,7 @@ static NSInteger RadioGroupSelection(NSView *view) {
RSXMLData *xml = [[RSXMLData alloc] initWithData:data url:url]; RSXMLData *xml = [[RSXMLData alloc] initWithData:data url:url];
RSOPMLParser *parser = [RSOPMLParser parserWithXMLData:xml]; RSOPMLParser *parser = [RSOPMLParser parserWithXMLData:xml];
[parser parseAsync:^(RSOPMLItem * _Nullable doc, NSError * _Nullable error) { [parser parseAsync:^(RSOPMLItem * _Nullable doc, NSError * _Nullable error) {
if (error) { if (![error inCasePresent:NSApp]) {
[NSApp presentError:error];
} else {
for (RSOPMLItem *itm in doc.children) { for (RSOPMLItem *itm in doc.children) {
block(itm); block(itm);
} }
@@ -250,7 +249,7 @@ static NSInteger RadioGroupSelection(NSView *view) {
NSData *xml = [doc XMLDataWithOptions:NSXMLNodePreserveAttributeOrder | NSXMLNodePrettyPrint]; NSData *xml = [doc XMLDataWithOptions:NSXMLNodePreserveAttributeOrder | NSXMLNodePrettyPrint];
[xml writeToURL:url options:NSDataWritingAtomic error:&error]; [xml writeToURL:url options:NSDataWritingAtomic error:&error];
} }
if (error) [NSApp presentError:error]; [error inCasePresent:NSApp];
return error; return error;
} }

View File

@@ -70,7 +70,7 @@
</dict> </dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>13404</string> <string>13435</string>
<key>LSApplicationCategoryType</key> <key>LSApplicationCategoryType</key>
<string>public.app-category.news</string> <string>public.app-category.news</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>

View File

@@ -22,9 +22,15 @@
@import Cocoa; @import Cocoa;
/// Log error message and prepend calling class and calling method.
#define NSLogCaller(desc) { NSLog(@"%@:%@ %@", [self class], NSStringFromSelector(_cmd), desc); }
@interface NSError (Ext) @interface NSError (Ext)
// Generators // Generators
+ (instancetype)statusCode:(NSInteger)code reason:(nullable NSString*)reason; + (instancetype)statusCode:(NSInteger)code reason:(nullable NSString*)reason;
+ (instancetype)canceledByUser; + (instancetype)canceledByUser;
+ (instancetype)feedURLNotFound:(NSURL*)url; + (instancetype)feedURLNotFound:(NSURL*)url;
// User notification
- (BOOL)inCaseLog:(nullable const char*)title;
- (BOOL)inCasePresent:(NSApplication*)app;
@end @end

View File

@@ -126,4 +126,21 @@ static const char* CodeDescription(NSInteger code) {
return RSXMLMakeErrorWrongParser(RSXMLErrorExpectingFeed, RSXMLErrorExpectingHTML, url); 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 @end

View File

@@ -22,6 +22,7 @@
#import "NSURL+Ext.h" #import "NSURL+Ext.h"
#import "UserPrefs.h" // appName in +faviconsCacheURL #import "UserPrefs.h" // appName in +faviconsCacheURL
#import "NSError+Ext.h"
@implementation NSURL (Ext) @implementation NSURL (Ext)
@@ -50,9 +51,8 @@
- (BOOL)mkdir { - (BOOL)mkdir {
if ([self existsAndIsDir:YES]) return NO; if ([self existsAndIsDir:YES]) return NO;
NSError *err; NSError *err;
BOOL b = [[NSFileManager defaultManager] createDirectoryAtURL:self withIntermediateDirectories:YES attributes:nil error:&err]; [[NSFileManager defaultManager] createDirectoryAtURL:self withIntermediateDirectories:YES attributes:nil error:&err];
if (err) [NSApp presentError:err]; return ![err inCasePresent:NSApp];
return b;
} }
/// Delete file or folder at URL. If item does not exist, this method does nothing. /// Delete file or folder at URL. If item does not exist, this method does nothing.

View File

@@ -27,6 +27,7 @@
#import "FeedGroup+Ext.h" #import "FeedGroup+Ext.h"
#import "UpdateScheduler.h" #import "UpdateScheduler.h"
#import "SettingsFeedsView.h" #import "SettingsFeedsView.h"
#import "NSError+Ext.h"
@interface SettingsFeeds () @interface SettingsFeeds ()
@property (strong) SettingsFeedsView *view; // override super @property (strong) SettingsFeedsView *view; // override super
@@ -100,7 +101,7 @@
NSError *error; NSError *error;
[self.dataStore fetchWithRequest:nil merge:NO error:&error]; [self.dataStore fetchWithRequest:nil merge:NO error:&error];
if (error) [NSApp presentError:error]; [error inCasePresent:NSApp];
} }
/** /**