NSError: inCaseLog + inCasePresent
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user