diff --git a/Core Data Editor/Core Data Editor.xcodeproj/project.pbxproj b/Core Data Editor/Core Data Editor.xcodeproj/project.pbxproj index 68e3262..95c835e 100644 --- a/Core Data Editor/Core Data Editor.xcodeproj/project.pbxproj +++ b/Core Data Editor/Core Data Editor.xcodeproj/project.pbxproj @@ -64,6 +64,7 @@ AB3B07C91775FCE2000855B0 /* CDEBoolValueTableCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = AB3B07C81775FCE2000855B0 /* CDEBoolValueTableCellView.m */; }; AB3B07CB1775FCF2000855B0 /* CDEBoolValueTableCellView.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB3B07CA1775FCF2000855B0 /* CDEBoolValueTableCellView.xib */; }; AB3B07CE17760E23000855B0 /* NSTableCellView+JKNibLoading.m in Sources */ = {isa = PBXBuildFile; fileRef = AB3B07CD17760E23000855B0 /* NSTableCellView+JKNibLoading.m */; }; + AB4068FA1DE1C5DE001F83E9 /* FilteringArray.m in Sources */ = {isa = PBXBuildFile; fileRef = AB4068F91DE1C5DE001F83E9 /* FilteringArray.m */; }; AB531222179953B300529EF7 /* NSTableColumn+CDERequestDataCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = AB531221179953B300529EF7 /* NSTableColumn+CDERequestDataCoordinator.m */; }; AB5583A5176751AE005C002C /* icon.iconset in Resources */ = {isa = PBXBuildFile; fileRef = AB5583A4176751AE005C002C /* icon.iconset */; }; AB59DA401DDF42AA00A19963 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AB59DA3F1DDF42AA00A19963 /* Main.storyboard */; }; @@ -99,7 +100,6 @@ ABBEA7ED1765CB730024A9D2 /* CDEDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = ABBEA7EC1765CB730024A9D2 /* CDEDocument.m */; }; ABBEA7F01765CB730024A9D2 /* CDEDocument.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABBEA7EE1765CB730024A9D2 /* CDEDocument.xib */; }; ABBEA7F31765CB730024A9D2 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABBEA7F11765CB730024A9D2 /* MainMenu.xib */; }; - ABBEA7F61765CB730024A9D2 /* CDEDocument.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = ABBEA7F41765CB730024A9D2 /* CDEDocument.xcdatamodeld */; }; ABBEA8241765D5AC0024A9D2 /* CDEPathActionLabelController.m in Sources */ = {isa = PBXBuildFile; fileRef = ABBEA7FE1765D5AA0024A9D2 /* CDEPathActionLabelController.m */; }; ABBEA8251765D5AC0024A9D2 /* CDENewConfigurationSummaryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ABBEA8001765D5AA0024A9D2 /* CDENewConfigurationSummaryViewController.m */; }; ABBEA8261765D5AC0024A9D2 /* CDENewConfigurationSummaryViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABBEA8011765D5AA0024A9D2 /* CDENewConfigurationSummaryViewController.xib */; }; @@ -121,7 +121,6 @@ ABBEA8951765F3320024A9D2 /* NSBundle+CDEApplicationAnalyzer.m in Sources */ = {isa = PBXBuildFile; fileRef = ABBEA8941765F3320024A9D2 /* NSBundle+CDEApplicationAnalyzer.m */; }; ABBEA8A01765FC230024A9D2 /* NSURL+CDEApplicationAnalyzer.m in Sources */ = {isa = PBXBuildFile; fileRef = ABBEA89F1765FC230024A9D2 /* NSURL+CDEApplicationAnalyzer.m */; }; ABBEA8A4176602B60024A9D2 /* NSString+CDEPersistentStore.m in Sources */ = {isa = PBXBuildFile; fileRef = ABBEA8A3176602B60024A9D2 /* NSString+CDEPersistentStore.m */; }; - ABBEA8B517660AB30024A9D2 /* _CDEConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = ABBEA8B217660AB30024A9D2 /* _CDEConfiguration.m */; }; ABBEA8B617660AB30024A9D2 /* CDEConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = ABBEA8B417660AB30024A9D2 /* CDEConfiguration.m */; }; ABBEA8BB1766153A0024A9D2 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = ABBEA8B91766153A0024A9D2 /* Localizable.strings */; }; ABBEA8D41766212A0024A9D2 /* NSPasteboard-CDEAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = ABBEA8D31766212A0024A9D2 /* NSPasteboard-CDEAdditions.m */; }; @@ -318,6 +317,8 @@ AB3B07CA1775FCF2000855B0 /* CDEBoolValueTableCellView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CDEBoolValueTableCellView.xib; sourceTree = ""; }; AB3B07CC17760E22000855B0 /* NSTableCellView+JKNibLoading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSTableCellView+JKNibLoading.h"; sourceTree = ""; }; AB3B07CD17760E23000855B0 /* NSTableCellView+JKNibLoading.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSTableCellView+JKNibLoading.m"; sourceTree = ""; }; + AB4068F81DE1C5DE001F83E9 /* FilteringArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilteringArray.h; sourceTree = ""; }; + AB4068F91DE1C5DE001F83E9 /* FilteringArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FilteringArray.m; sourceTree = ""; }; AB531220179953B300529EF7 /* NSTableColumn+CDERequestDataCoordinator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSTableColumn+CDERequestDataCoordinator.h"; sourceTree = ""; }; AB531221179953B300529EF7 /* NSTableColumn+CDERequestDataCoordinator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSTableColumn+CDERequestDataCoordinator.m"; sourceTree = ""; }; AB5583A4176751AE005C002C /* icon.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; path = icon.iconset; sourceTree = ""; }; @@ -378,7 +379,6 @@ ABBEA7EC1765CB730024A9D2 /* CDEDocument.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CDEDocument.m; sourceTree = ""; }; ABBEA7EF1765CB730024A9D2 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CDEDocument.xib; sourceTree = ""; }; ABBEA7F21765CB730024A9D2 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; - ABBEA7F51765CB730024A9D2 /* CDEDocument.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = CDEDocument.xcdatamodel; sourceTree = ""; }; ABBEA7FD1765D5AA0024A9D2 /* CDEPathActionLabelController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDEPathActionLabelController.h; sourceTree = ""; }; ABBEA7FE1765D5AA0024A9D2 /* CDEPathActionLabelController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDEPathActionLabelController.m; sourceTree = ""; }; ABBEA7FF1765D5AA0024A9D2 /* CDENewConfigurationSummaryViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDENewConfigurationSummaryViewController.h; sourceTree = ""; }; @@ -421,8 +421,6 @@ ABBEA89F1765FC230024A9D2 /* NSURL+CDEApplicationAnalyzer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURL+CDEApplicationAnalyzer.m"; sourceTree = ""; }; ABBEA8A2176602B60024A9D2 /* NSString+CDEPersistentStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+CDEPersistentStore.h"; sourceTree = ""; }; ABBEA8A3176602B60024A9D2 /* NSString+CDEPersistentStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+CDEPersistentStore.m"; sourceTree = ""; }; - ABBEA8B117660AB30024A9D2 /* _CDEConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _CDEConfiguration.h; sourceTree = ""; }; - ABBEA8B217660AB30024A9D2 /* _CDEConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _CDEConfiguration.m; sourceTree = ""; }; ABBEA8B317660AB30024A9D2 /* CDEConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDEConfiguration.h; sourceTree = ""; }; ABBEA8B417660AB30024A9D2 /* CDEConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDEConfiguration.m; sourceTree = ""; }; ABBEA8BA1766153A0024A9D2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; @@ -840,6 +838,8 @@ children = ( AB15E73F177B690B00FA113E /* CDEEntityRequestDataCoordinator.h */, AB15E740177B690B00FA113E /* CDEEntityRequestDataCoordinator.m */, + AB4068F81DE1C5DE001F83E9 /* FilteringArray.h */, + AB4068F91DE1C5DE001F83E9 /* FilteringArray.m */, ); name = "Entity Coordinator"; sourceTree = ""; @@ -1223,7 +1223,6 @@ ABBEA7EE1765CB730024A9D2 /* CDEDocument.xib */, ABBEA7F11765CB730024A9D2 /* MainMenu.xib */, AB59DA3F1DDF42AA00A19963 /* Main.storyboard */, - ABBEA7F41765CB730024A9D2 /* CDEDocument.xcdatamodeld */, ABBEA7E01765CB730024A9D2 /* Supporting Files */, ); path = "Core Data Editor"; @@ -1439,20 +1438,10 @@ AB23E43C17A6C1F5001C19A7 /* Autosave Information */, ABBEA8B317660AB30024A9D2 /* CDEConfiguration.h */, ABBEA8B417660AB30024A9D2 /* CDEConfiguration.m */, - ABBEA8B717660FC00024A9D2 /* Machine */, ); name = Model; sourceTree = ""; }; - ABBEA8B717660FC00024A9D2 /* Machine */ = { - isa = PBXGroup; - children = ( - ABBEA8B117660AB30024A9D2 /* _CDEConfiguration.h */, - ABBEA8B217660AB30024A9D2 /* _CDEConfiguration.m */, - ); - name = Machine; - sourceTree = ""; - }; ABBEA8B817660FD40024A9D2 /* Shared */ = { isa = PBXGroup; children = ( @@ -2166,7 +2155,6 @@ ABBEA7E61765CB730024A9D2 /* main.m in Sources */, ABDA4235181BFF2C0054A226 /* CDEMenuWindowItemBadgeView.m in Sources */, ABBEA7ED1765CB730024A9D2 /* CDEDocument.m in Sources */, - ABBEA7F61765CB730024A9D2 /* CDEDocument.xcdatamodeld in Sources */, ABDA4282181C068F0054A226 /* CDEManagedObjectsTableViewController.m in Sources */, ABBEA8241765D5AC0024A9D2 /* CDEPathActionLabelController.m in Sources */, ABBEA8251765D5AC0024A9D2 /* CDENewConfigurationSummaryViewController.m in Sources */, @@ -2187,7 +2175,6 @@ ABBEA8951765F3320024A9D2 /* NSBundle+CDEApplicationAnalyzer.m in Sources */, ABBEA8A01765FC230024A9D2 /* NSURL+CDEApplicationAnalyzer.m in Sources */, ABBEA8A4176602B60024A9D2 /* NSString+CDEPersistentStore.m in Sources */, - ABBEA8B517660AB30024A9D2 /* _CDEConfiguration.m in Sources */, ABBEA8B617660AB30024A9D2 /* CDEConfiguration.m in Sources */, ABBEA8D41766212A0024A9D2 /* NSPasteboard-CDEAdditions.m in Sources */, AB22AC7A17664480004890AC /* NSBundle+CDEModelFinder.m in Sources */, @@ -2301,6 +2288,7 @@ ABB225D717B92B230024FE4F /* CDEProjectBrowserWindowController.m in Sources */, ABB225DC17B939E60024FE4F /* CDEProjectBrowserItem.m in Sources */, ABB225DF17B940CE0024FE4F /* CDEProjectBrowserItemTableCellView.m in Sources */, + AB4068FA1DE1C5DE001F83E9 /* FilteringArray.m in Sources */, AB36447E17BA47D4004ADAAC /* CDESetupWindowController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2480,19 +2468,6 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ - -/* Begin XCVersionGroup section */ - ABBEA7F41765CB730024A9D2 /* CDEDocument.xcdatamodeld */ = { - isa = XCVersionGroup; - children = ( - ABBEA7F51765CB730024A9D2 /* CDEDocument.xcdatamodel */, - ); - currentVersion = ABBEA7F51765CB730024A9D2 /* CDEDocument.xcdatamodel */; - path = CDEDocument.xcdatamodeld; - sourceTree = ""; - versionGroupType = wrapper.xcdatamodel; - }; -/* End XCVersionGroup section */ }; rootObject = ABBEA7CE1765CB730024A9D2 /* Project object */; } diff --git a/Core Data Editor/Core Data Editor/CDEApplicationDelegate.m b/Core Data Editor/Core Data Editor/CDEApplicationDelegate.m index 5f1b052..1b92a49 100644 --- a/Core Data Editor/Core Data Editor/CDEApplicationDelegate.m +++ b/Core Data Editor/Core Data Editor/CDEApplicationDelegate.m @@ -51,65 +51,20 @@ - (IBAction)showProjectBrowser:(id)sender { if(self.projectBrowserWindowController == nil) { self.projectBrowserWindowController = [CDEProjectBrowserWindowController new]; } - [self.projectBrowserWindowController showWithProjectDirectoryURL:self.iPhoneSimulatorDirectory]; -} - -#pragma mark - Helper -#pragma mark - Helper / Security Scoped Resources -- (BOOL)startAccessingCoreDataEditorSecurityScopedResources { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - BOOL iPhoneSimulatorSuccess = YES; - - if(defaults.simulatorDirectory_cde != nil) { - self.iPhoneSimulatorDirectory = defaults.simulatorDirectory_cde; - iPhoneSimulatorSuccess = [self.iPhoneSimulatorDirectory startAccessingSecurityScopedResource]; - } - - BOOL buildProductsDirectorySuccess = YES; - - if(defaults.buildProductsDirectory_cde != nil) { - self.derivedDataDirectory = defaults.buildProductsDirectory_cde; - buildProductsDirectorySuccess = [self.derivedDataDirectory startAccessingSecurityScopedResource]; - if(buildProductsDirectorySuccess == NO) { - // we have bookmark data but we cannot start accessing it! - NSAlert *alert = [NSAlert new]; - alert.messageText = @"Failed to access Derived Data Directory"; - [alert addButtonWithTitle:@"Set Directory…"]; - [alert addButtonWithTitle:@"Cancel"]; - alert.informativeText = @"You have set a Xcode derived data directory in the preferences but Core Data Editor failed to access the contents of the directory. If you want to continue to use this feature you should set a new directory now."; - NSUInteger returnCode = [alert runModal]; - if(returnCode == NSAlertFirstButtonReturn) { - assert(false); -// [self.preferencesWindowController showAutomaticProjectCreationPreferencesWithCompletionHandler:nil]; - } - } - } - - return (iPhoneSimulatorSuccess && buildProductsDirectorySuccess); + [self.projectBrowserWindowController showWithProjectDirectoryURL:defaults.simulatorDirectory_cde]; } #pragma mark NSApplicationDelegate - (void)applicationWillFinishLaunching:(NSNotification *)notification { - - // Start accessing security scoped resources here because this delegate method is called - // before applicationDidFinishLaunching: and before application:openFile: - // Since we need access to the resources in both cases... - [self startAccessingCoreDataEditorSecurityScopedResources]; - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [defaults setObject:@"HELLO" forKey:@"AAAAAAAAAAAAAA"]; [[NSNotificationCenter defaultCenter] addObserverForName:CDEUserDefaultsNotifications.didChangeSimulatorDirectory object:defaults queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { - [self.iPhoneSimulatorDirectory stopAccessingSecurityScopedResource]; self.iPhoneSimulatorDirectory = defaults.simulatorDirectory_cde; - [self.iPhoneSimulatorDirectory startAccessingSecurityScopedResource]; [self.projectBrowserWindowController updateProjectDirectoryURL:self.iPhoneSimulatorDirectory]; }]; [[NSNotificationCenter defaultCenter] addObserverForName:CDEUserDefaultsNotifications.didChangeBuildProductsDirectory object:defaults queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { - [self.derivedDataDirectory stopAccessingSecurityScopedResource]; self.derivedDataDirectory = defaults.buildProductsDirectory_cde; - [self.derivedDataDirectory startAccessingSecurityScopedResource]; }]; } - (void)applicationDidFinishLaunching:(NSNotification *)notification { @@ -125,10 +80,6 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { } self.aboutWindowController = [[CDEAboutWindowController alloc] initWithWindowNibName:@"CDEAboutWindowController"]; - // Create prefs if needed -// if(self.preferencesWindowController == nil) { -// self.preferencesWindowController = [CDEPreferencesWindowController new]; -// } } - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag @@ -146,10 +97,6 @@ - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender { } - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { - // Need to create prefs? -// if(self.preferencesWindowController == nil) { -// self.preferencesWindowController = [CDEPreferencesWindowController new]; -// } if([filename.pathExtension isEqualToString:@"coredataeditor5"]) { [[NSDocumentController sharedDocumentController] openDocumentWithContentsOfURL:[NSURL fileURLWithPath:filename] display:YES completionHandler:^(NSDocument * _Nullable document, BOOL documentWasAlreadyOpen, NSError * _Nullable error) { @@ -169,8 +116,6 @@ - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filenam if(buildProductsDirectory == nil) { NSLog(@"no build products directory."); assert(false); -#pragma mark warn bla -// [self.preferencesWindowController showAutomaticProjectCreationPreferencesAndDisplayInfoSheetWithCompletionHandler:nil]; return YES; } @@ -211,17 +156,9 @@ - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filenam // We have found something! NSLog(@"%@ is compatible with %@", storeURL.lastPathComponent, modelURL); CDEDocument *document = [[NSDocumentController sharedDocumentController] openUntitledDocumentAndDisplay:NO error:NULL]; - CDEConfiguration *c = [document createConfiguration]; - error = nil; - BOOL set = [c setBookmarkDataWithApplicationBundleURL:nil storeURL:storeURL modelURL:modelURL error:&error]; - if(!set) { - NSLog(@"error: %@", error); - } + CDEConfiguration *configuration = [document createConfiguration]; + [configuration setApplicationBundleURL:nil storeURL:storeURL modelURL:modelURL]; error = nil; - BOOL setup = [document setupAndStartAccessingConfigurationRelatedURLsAndGetError:&error]; - if(!setup) { - NSLog(@"error: %@", error); - } [document makeWindowControllers]; [document showWindows]; return YES; diff --git a/Core Data Editor/Core Data Editor/CDEConfiguration.h b/Core Data Editor/Core Data Editor/CDEConfiguration.h index f4e2026..3e40f05 100644 --- a/Core Data Editor/Core Data Editor/CDEConfiguration.h +++ b/Core Data Editor/Core Data Editor/CDEConfiguration.h @@ -1,15 +1,20 @@ -#import "_CDEConfiguration.h" +@interface CDEConfiguration : NSObject -@interface CDEConfiguration : _CDEConfiguration - -#pragma mark - Getting the only Configuration object -+ (CDEConfiguration *)fetchedConfigurationInManagedObjectContext:(NSManagedObjectContext *)managedObjectContext error:(NSError **)error; -+ (BOOL)configurationExistsInManagedObjectContext:(NSManagedObjectContext *)managedObjectContext error:(NSError **)error; +#pragma mark - Properties +@property (nullable, readonly) NSURL *storeURL, *modelURL, *applicationBundleURL; +@property (nullable, copy) NSString *applicationBundlePath; +@property (nullable, strong) NSDictionary *autosaveInformationByEntityName; +@property (nullable, copy) NSNumber *isMacApplication; +@property (nullable, copy) NSString *modelPath; +@property (nullable, copy) NSString *storePath; #pragma mark - Properties @property (nonatomic, readonly, getter = isValid) BOOL isValid; -#pragma mark - Setting Bookmark Data in Batch -- (BOOL)setBookmarkDataWithApplicationBundleURL:(NSURL *)applicationBundleURL storeURL:(NSURL *)storeURL modelURL:(NSURL *)modelURL error:(NSError **)error; +#pragma mark - Setting URLs +- (void)setApplicationBundleURL:(nullable NSURL *)applicationBundleURL storeURL:(nullable NSURL *)storeURL modelURL:(nullable NSURL *)modelURL; + +- (NSData * _Nonnull )data; +- (nullable instancetype)initWithData:(NSData * _Nullable )data; @end diff --git a/Core Data Editor/Core Data Editor/CDEConfiguration.m b/Core Data Editor/Core Data Editor/CDEConfiguration.m index 57650a9..cb3ce5c 100644 --- a/Core Data Editor/Core Data Editor/CDEConfiguration.m +++ b/Core Data Editor/Core Data Editor/CDEConfiguration.m @@ -6,86 +6,76 @@ @interface CDEConfiguration () @implementation CDEConfiguration -#pragma mark - Properties -#pragma mark - Getting the only Configuration object -+ (CDEConfiguration *)fetchedConfigurationInManagedObjectContext:(NSManagedObjectContext *)managedObjectContext error:(NSError **)error { - NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[self entityName]]; - NSArray *fetchedConfigurations = [managedObjectContext executeFetchRequest:fetchRequest error:error]; - CDEConfiguration *configuration = [fetchedConfigurations lastObject]; - return configuration; + +- ( NSData * _Nonnull)data { + NSMutableDictionary *dict = [NSMutableDictionary new]; + if(self.applicationBundlePath != nil) { + dict[@"applicationBundlePath"] = self.applicationBundlePath; + } + if(self.autosaveInformationByEntityName != nil) { + dict[@"autosaveInformationByEntityName"] = self.autosaveInformationByEntityName; + } + if(self.isMacApplication != nil) { + dict[@"isMacApplication"] = self.isMacApplication; + } + if(self.modelPath != nil) { + dict[@"modelPath"] = self.modelPath; + } + if(self.storePath != nil) { + dict[@"storePath"] = self.storePath; + } + NSData *result = [NSKeyedArchiver archivedDataWithRootObject:dict]; + return result; } -+ (BOOL)configurationExistsInManagedObjectContext:(NSManagedObjectContext *)managedObjectContext error:(NSError **)error { - NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[self entityName]]; - NSUInteger count = [managedObjectContext countForFetchRequest:fetchRequest error:error]; +- (instancetype)initWithData:(NSData *_Nullable)data { + self = [super init]; + NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithData:data]; + self.applicationBundlePath = dict[@"applicationBundlePath"]; + self.autosaveInformationByEntityName = dict[@"autosaveInformationByEntityName"]; + self.isMacApplication = dict[@"isMacApplication"]; + self.modelPath = dict[@"modelPath"]; + self.storePath = dict[@"storePath"]; + return self; +} +#pragma mark - Properties +- (NSURL*)applicationBundleURL { + return [NSURL fileURLWithPath:self.applicationBundlePath]; +} - if(count == NSNotFound) { - return NO; - } - - return (count == 1); +- (NSURL*)storeURL { + return [NSURL fileURLWithPath:self.storePath]; +} +- (void)setStoreURL:(NSURL *)storeURL { + self.storePath = storeURL.path; +} +- (NSURL *)modelURL { + return [NSURL fileURLWithPath:self.modelPath]; +} +- (void)setModelURL:(NSURL *)modelURL { + self.modelPath = modelURL.path; } +#pragma mark - Getting the only Configuration object + (NSSet *)keyPathsForValuesAffectingIsValid { - return [NSSet setWithArray:@[CDEConfigurationAttributes.modelBookmarkData, CDEConfigurationAttributes.storeBookmarkData]]; + return [NSSet setWithArray:@[@"modelPath", @"storePath"]]; } - (BOOL)isValid { - if(self.modelBookmarkData == nil || self.storeBookmarkData == nil) { - return NO; - } - return YES; + if(self.modelPath == nil || self.storePath == nil) { + return NO; + } + return YES; } #pragma mark - Setting Bookmark Data in Batch -- (BOOL)setBookmarkDataWithApplicationBundleURL:(NSURL *)applicationBundleURL storeURL:(NSURL *)storeURL modelURL:(NSURL *)modelURL error:(NSError **)error { - NSParameterAssert(storeURL); - NSParameterAssert(modelURL); - - // Application Bundle URL is optional - - NSError *bookmarkError = nil; - NSData *storeData = [storeURL bookmarkDataAndGetError_cde:&bookmarkError]; - - if(storeData == nil) { - NSLog(@"Error: %@", bookmarkError); - if(error != NULL) { - *error = bookmarkError; - } - return NO; - } - - self.storeBookmarkData = storeData; - - bookmarkError = nil; - NSData *modelData = [modelURL bookmarkDataAndGetError_cde:&bookmarkError]; - - if(modelData == nil) { - NSLog(@"Error: %@", bookmarkError); - if(error != NULL) { - *error = bookmarkError; - } - return NO; - } - - self.modelBookmarkData = modelData; - - if(applicationBundleURL != nil) { - bookmarkError = nil; - NSData *applicationData = [applicationBundleURL bookmarkDataAndGetError_cde:&bookmarkError]; - - if(applicationData == nil) { - NSLog(@"Error: %@", bookmarkError); - if(error != NULL) { - *error = bookmarkError; - } - return NO; - } - self.applicationBundleBookmarkData = applicationData; - } - - return YES; +- (void)setApplicationBundleURL:(NSURL *)applicationBundleURL storeURL:(NSURL *)storeURL modelURL:(NSURL *)modelURL { + NSParameterAssert(storeURL); + NSParameterAssert(modelURL); + self.applicationBundlePath = applicationBundleURL.path; + self.storePath = storeURL.path; + self.modelPath = modelURL.path; } @end diff --git a/Core Data Editor/Core Data Editor/CDEDateAttributeView.xib b/Core Data Editor/Core Data Editor/CDEDateAttributeView.xib index aae75a4..3f14ef9 100644 --- a/Core Data Editor/Core Data Editor/CDEDateAttributeView.xib +++ b/Core Data Editor/Core Data Editor/CDEDateAttributeView.xib @@ -1,6 +1,7 @@ + @@ -9,13 +10,12 @@ - - + diff --git a/Core Data Editor/Core Data Editor/CDEDateAttributeViewController.m b/Core Data Editor/Core Data Editor/CDEDateAttributeViewController.m index 3219a15..c6c48dd 100644 --- a/Core Data Editor/Core Data Editor/CDEDateAttributeViewController.m +++ b/Core Data Editor/Core Data Editor/CDEDateAttributeViewController.m @@ -4,7 +4,7 @@ @interface CDEDateAttributeViewController () #pragma mark Properties -@property (nonatomic, retain) CDEDatePickerWindow *datePickerWindow; +@property (strong) CDEDatePickerWindow *datePickerWindow; @end diff --git a/Core Data Editor/Core Data Editor/CDEDocument.h b/Core Data Editor/Core Data Editor/CDEDocument.h index 061ed30..7f0cbc2 100644 --- a/Core Data Editor/Core Data Editor/CDEDocument.h +++ b/Core Data Editor/Core Data Editor/CDEDocument.h @@ -2,10 +2,9 @@ // see: file:///Users/cmk/Projects/Products/CoreDataEditor @class CDEConfiguration; -@interface CDEDocument : NSPersistentDocument +@interface CDEDocument : NSDocument #pragma mark - Should only be used by the App Delegate - (CDEConfiguration *)createConfiguration; -- (BOOL)setupAndStartAccessingConfigurationRelatedURLsAndGetError:(NSError **)error; @end diff --git a/Core Data Editor/Core Data Editor/CDEDocument.m b/Core Data Editor/Core Data Editor/CDEDocument.m index ede890e..0d1ab91 100644 --- a/Core Data Editor/Core Data Editor/CDEDocument.m +++ b/Core Data Editor/Core Data Editor/CDEDocument.m @@ -14,14 +14,14 @@ @interface CDEDocument () #pragma mark - Properties -@property (nonatomic, strong) CDEConfiguration *configuration; -@property (nonatomic, strong) CDEConfigurationWizzard *configurationWizzard; -@property (nonatomic, strong) CDEEditorViewController *editorViewController; -@property (nonatomic, weak) IBOutlet NSView *containerView; +@property (strong) CDEConfiguration *configuration; +@property (strong) CDEConfigurationWizzard *configurationWizzard; +@property (strong) CDEEditorViewController *editorViewController; +@property (weak) IBOutlet NSView *containerView; -@property (nonatomic, copy) NSURL *storeURL; -@property (nonatomic, copy) NSURL *modelURL; -@property (nonatomic, copy) NSURL *applicationBundleURL; +@property (readonly) NSURL *storeURL; +@property (readonly) NSURL *modelURL; +@property (readonly) NSURL *applicationBundleURL; #pragma mark - Actions - (IBAction)showConfiguration:(id)sender; @@ -32,345 +32,250 @@ @implementation CDEDocument #pragma mark - NSObject + (void)initialize { - if(self == [CDEDocument class]) { - [CDEManagedObjectIDToStringValueTransformer registerDefaultManagedObjectIDToStringValueTransformer]; - } + if(self == [CDEDocument class]) { + [CDEManagedObjectIDToStringValueTransformer registerDefaultManagedObjectIDToStringValueTransformer]; + } } +- (NSURL *)storeURL { return self.configuration.storeURL; } + +- (NSURL *)modelURL { return self.configuration.modelURL; } +- (NSURL *)applicationBundleURL { return self.configuration.applicationBundleURL; } + - (NSWindow*)_documentWindow { - NSParameterAssert(self.windowControllers.count == 1); - - if([[self windowControllers] count] == 1) { - return [[self windowControllers][0] window]; - } - return nil; + NSParameterAssert(self.windowControllers.count == 1); + + if([[self windowControllers] count] == 1) { + return [[self windowControllers][0] window]; + } + return nil; } #pragma mark - Actions - (IBAction)showConfiguration:(id)sender { - [self.configurationWizzard window]; - __typeof__(self) __weak weakSelf = self; - [self.configurationWizzard beginSheetModalForWindow:[self _documentWindow] - applicationBundleURL:self.applicationBundleURL - storeURL:self.storeURL - modelURL:self.modelURL completionHandler:^(BOOL success, NSURL *applicationBundleURL, NSURL *storeURL, NSURL *modelURL) { - if(success == NO) { - return; - } - - NSError *error = nil; - BOOL bookmarkDataSet = [self.configuration setBookmarkDataWithApplicationBundleURL:applicationBundleURL storeURL:storeURL modelURL:modelURL error:&error]; - if(bookmarkDataSet == NO) { - [NSApp presentError:error]; - return; - } - - // Resolve - NSError *resolveError = nil; - BOOL resolved = [self setupAndStartAccessingConfigurationRelatedURLsAndGetError:&resolveError]; - if(resolved == NO) { - [NSApp presentError:resolveError]; - return; - } - - [weakSelf.editorViewController setConfiguration:self.configuration modelURL:self.modelURL storeURL:self.storeURL needsReload:YES error:NULL]; - }]; + [self.configurationWizzard window]; + __typeof__(self) __weak weakSelf = self; + [self.configurationWizzard beginSheetModalForWindow:[self _documentWindow] + applicationBundleURL:self.applicationBundleURL + storeURL:self.storeURL + modelURL:self.modelURL completionHandler:^(BOOL success, NSURL *applicationBundleURL, NSURL *storeURL, NSURL *modelURL) { + if(success == NO) { + return; + } + + [self.configuration setApplicationBundleURL:applicationBundleURL storeURL:storeURL modelURL:modelURL]; + + [weakSelf.editorViewController setConfiguration:self.configuration modelURL:self.modelURL storeURL:self.storeURL needsReload:YES error:NULL]; + }]; +} + +- (IBAction)refresh:(id)sender { + [self.editorViewController setConfiguration:self.configuration modelURL:self.modelURL storeURL:self.storeURL needsReload:YES error:NULL]; } #pragma mark - NSDocument - (instancetype)init { - self = [super init]; - if (self) { - self.configurationWizzard = [CDEConfigurationWizzard new]; - self.editorViewController = [CDEEditorViewController new]; - } - return self; + self = [super init]; + if (self) { + self.configurationWizzard = [CDEConfigurationWizzard new]; + self.editorViewController = [CDEEditorViewController new]; + } + return self; } - (NSString *)windowNibName { - return @"CDEDocument"; + return @"CDEDocument"; } + (BOOL)preservesVersions { - return NO; + return NO; } - (void)dealloc { - self.editorViewController = nil; + self.editorViewController = nil; } - (BOOL)validateUserInterfaceItem:(id )item { - // Validate the Entity menu - if([item action] == @selector(deleteSelectedObjcts:)) { - return self.editorViewController.canDeleteSelectedManagedObjects; - } - if([item action] == @selector(insertObject:)) { - return self.editorViewController.canInsertManagedObject; - } - if([item action] == @selector(copySelectedObjectsAsCSV:)) { - return self.editorViewController.canCreateCSVRepresentationWithSelectedObjects; - } - - // Let super do its work - return [super validateUserInterfaceItem:item]; + // Validate the Entity menu + if([item action] == @selector(deleteSelectedObjcts:)) { + return self.editorViewController.canDeleteSelectedManagedObjects; + } + if([item action] == @selector(insertObject:)) { + return self.editorViewController.canInsertManagedObject; + } + if([item action] == @selector(copySelectedObjectsAsCSV:)) { + return self.editorViewController.canCreateCSVRepresentationWithSelectedObjects; + } + + // Let super do its work + return [super validateUserInterfaceItem:item]; } - (BOOL)validateToolbarItem:(NSToolbarItem *)item { - if([item.itemIdentifier isEqualToString:@"CDECode"]) { - return (self.configuration.storeBookmarkData != nil && self.configuration.modelBookmarkData != nil); - } - if([item.itemIdentifier isEqualToString:@"CDECSV"]) { - return (self.configuration.storeBookmarkData != nil && self.configuration.modelBookmarkData != nil); - } - return YES; + if([item.itemIdentifier isEqualToString:@"CDECode"]) { + return (self.configuration.storePath != nil && self.configuration.modelPath != nil); + } + if([item.itemIdentifier isEqualToString:@"CDECSV"]) { + return (self.configuration.storePath != nil && self.configuration.modelPath != nil); + } + return YES; } -- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName forSaveOperation:(NSSaveOperationType)saveOperation originalContentsURL:(NSURL *)absoluteOriginalContentsURL error:(NSError **)error { - NSError *saveError = nil; - [self.editorViewController save:&saveError]; - BOOL result = [super writeToURL:absoluteURL ofType:typeName forSaveOperation:saveOperation originalContentsURL:absoluteOriginalContentsURL error:error]; - if(saveError != nil) { - [NSApp presentError:saveError]; - } - return result; +-(BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError * _Nullable __autoreleasing *)outError { + CDEConfiguration *c = [[CDEConfiguration alloc] initWithData: data]; + self.configuration = c; + return YES; +} + +-(NSData *)dataOfType:(NSString *)typeName error:(NSError * _Nullable __autoreleasing *)outError { + NSError *saveError = nil; + [self.editorViewController save:&saveError]; + if(saveError != nil) { + [NSApp presentError:saveError]; + } + + return self.configuration.data; } - (CDEConfiguration *)createConfiguration { - [[[self managedObjectContext] undoManager] disableUndoRegistration]; - CDEConfiguration *configuration = [CDEConfiguration insertInManagedObjectContext:self.managedObjectContext]; - self.configuration = configuration; - - [[[self managedObjectContext] undoManager] enableUndoRegistration]; - [[self managedObjectContext] processPendingChanges]; - [[[self managedObjectContext] undoManager] removeAllActions]; - [self updateChangeCount:NSChangeCleared]; - return configuration; + CDEConfiguration *configuration = [CDEConfiguration new]; + self.configuration = configuration; + + [self updateChangeCount:NSChangeCleared]; + return configuration; } - (void)_createConfiguration { - [[[self managedObjectContext] undoManager] disableUndoRegistration]; - CDEConfiguration *configuration = [CDEConfiguration insertInManagedObjectContext:self.managedObjectContext]; - self.configuration = configuration; - - [[[self managedObjectContext] undoManager] enableUndoRegistration]; - [[self managedObjectContext] processPendingChanges]; - [[[self managedObjectContext] undoManager] removeAllActions]; - [self updateChangeCount:NSChangeCleared]; + CDEConfiguration *configuration = [CDEConfiguration new]; + self.configuration = configuration; + + [self updateChangeCount:NSChangeCleared]; } - (void)createConfigurationAndShowWizzard { - [self _createConfiguration]; - __typeof__(self) __weak weakSelf = self; - [self.configurationWizzard beginSheetModalForWindow:[self _documentWindow] completionHandler:^(BOOL success, NSURL *applicationBundleURL, NSURL *storeURL, NSURL *modelURL) { - if(success == NO) { - return; - } - - NSError *error = nil; - BOOL bookmarkDataSet = [self.configuration setBookmarkDataWithApplicationBundleURL:applicationBundleURL storeURL:storeURL modelURL:modelURL error:&error]; - if(bookmarkDataSet == NO) { - [NSApp presentError:error]; - return; - } - - // Resolve - NSError *resolveError = nil; - BOOL resolved = [self setupAndStartAccessingConfigurationRelatedURLsAndGetError:&resolveError]; - if(resolved == NO) { - [NSApp presentError:resolveError]; - return; - } - - [weakSelf.editorViewController setConfiguration:self.configuration modelURL:self.modelURL storeURL:self.storeURL needsReload:YES error:NULL]; - }]; - -} - -- (BOOL)setupAndStartAccessingConfigurationRelatedURLsAndGetError:(NSError **)error { - NSParameterAssert(self.configuration); - - NSError *resolveError = nil; - self.modelURL = [NSURL URLByResolvingBookmarkData:self.configuration.modelBookmarkData - error_cde:&resolveError]; - - if(self.modelURL == nil) { - NSLog(@"Error resolving model URL: %@", resolveError); - if(error != NULL) { - *error = resolveError; - } - - return NO; - } - if([self.modelURL startAccessingSecurityScopedResource] == NO) { - NSLog(@"Error accessing model URL (%@).", self.modelURL); - - return NO; - } - - resolveError = nil; - self.storeURL = [NSURL URLByResolvingBookmarkData:self.configuration.storeBookmarkData - error_cde:&resolveError]; - if(self.storeURL == nil) { - NSLog(@"Error resolving store URL: %@", resolveError); - if(error != NULL) { - *error = resolveError; - } - return NO; - } - - if([self.storeURL startAccessingSecurityScopedResource] == NO) { - NSLog(@"Error accessing store URL (%@).", self.storeURL); - return NO; + [self _createConfiguration]; + __typeof__(self) __weak weakSelf = self; + [self.configurationWizzard beginSheetModalForWindow:[self _documentWindow] completionHandler:^(BOOL success, NSURL *applicationBundleURL, NSURL *storeURL, NSURL *modelURL) { + if(success == NO) { + return; } - return YES; + [self.configuration setApplicationBundleURL:applicationBundleURL storeURL:storeURL modelURL:modelURL]; + [weakSelf.editorViewController setConfiguration:self.configuration modelURL:self.modelURL storeURL:self.storeURL needsReload:YES error:NULL]; + }]; + } - (void)windowControllerDidLoadNib:(NSWindowController *)windowController { - [super windowControllerDidLoadNib:windowController]; + [super windowControllerDidLoadNib:windowController]; [self _documentWindow].titleVisibility = NSWindowTitleHidden; - self.editorViewController.view.frame = self.containerView.bounds; - [self.containerView addSubview:self.editorViewController.view]; - - self.configuration = [CDEConfiguration fetchedConfigurationInManagedObjectContext:self.managedObjectContext error:NULL]; + self.editorViewController.view.frame = self.containerView.bounds; + [self.containerView addSubview:self.editorViewController.view]; + + if(self.configuration == nil) { + [self createConfigurationAndShowWizzard]; + } + else { + // - store and model incompatible + // - model invalid + NSMutableOrderedSet *errorMessages = [NSMutableOrderedSet orderedSet]; + NSFileManager *fs = [NSFileManager defaultManager]; + if([fs fileExistsAtPath:self.modelURL.path] == NO) { + [errorMessages addObject:@"• Model could not be found."]; + + } + if([fs fileExistsAtPath:self.storeURL.path] == NO) { + [errorMessages addObject:@"• Store could not be found."]; + } - if(self.configuration == nil) { - [self createConfigurationAndShowWizzard]; + // If there aren't any error messages we can check for compatibility + NSManagedObjectModel *model = nil; + @try { + model = [[NSManagedObjectModel alloc] initWithContentsOfURL:self.modelURL]; + if(model == nil) { + [errorMessages addObject:@"• Model could not be loaded."]; + } } - else { - // Resolve - // Possible errors: - // - modelURL: - // A: could not be resolved: file does not exist (NSCocoaErrorDomain, Code: NSFileNoSuchFileError) - // B: could not be resolved: other error - // C: start accessing failed - // - storeURL could not be resolved: - // A: could not be resolved: file does not exist (NSCocoaErrorDomain, Code: NSFileNoSuchFileError) - // B: could not be resolved: other error - // C: start accessing failed - // - store and model incompatible - // - model invalid - NSMutableOrderedSet *errorMessages = [NSMutableOrderedSet orderedSet]; - NSError *resolveError = nil; - self.modelURL = [NSURL URLByResolvingBookmarkData:self.configuration.modelBookmarkData options:NSURLBookmarkResolutionWithoutUI relativeToURL:nil bookmarkDataIsStale:NULL error:&resolveError]; - if(self.modelURL == nil) { - if([[resolveError domain] isEqualToString:NSCocoaErrorDomain] && resolveError.code == NSFileNoSuchFileError) { - [errorMessages addObject:@"• Model could not be found."]; - } else { - [errorMessages addObject:[@"• " stringByAppendingString:resolveError.localizedDescription]]; - } - NSLog(@"error: %@", resolveError); - } else { - if([self.modelURL startAccessingSecurityScopedResource] == NO) { - NSLog(@"failed to access model"); - [errorMessages addObject:@"• Model could not be accessed."]; - } - } - - resolveError = nil; - self.storeURL = [NSURL URLByResolvingBookmarkData:self.configuration.storeBookmarkData options:NSURLBookmarkResolutionWithoutUI relativeToURL:nil bookmarkDataIsStale:NULL error:&resolveError]; - if(self.storeURL == nil) { - if([[resolveError domain] isEqualToString:NSCocoaErrorDomain] && resolveError.code == NSFileNoSuchFileError) { - [errorMessages addObject:@"• Store could not be found."]; - } else { - [errorMessages addObject:[@"• " stringByAppendingString:resolveError.localizedDescription]]; - } - - NSLog(@"error: %@", resolveError); - } else { - if([self.storeURL startAccessingSecurityScopedResource] == NO) { - [errorMessages addObject:@"• Store could not be accessed."]; - NSLog(@"failed to access store"); - } - } - // If there aren't any error messages we can check for compatibility - NSManagedObjectModel *model = nil; - @try { - model = [[NSManagedObjectModel alloc] initWithContentsOfURL:self.modelURL]; - if(model == nil) { - [errorMessages addObject:@"• Model could not be loaded."]; - } - } - @catch (NSException *exception) { - [errorMessages addObject:@"• Model could not be loaded because an exception occured."]; - NSString *exceptionMessage = [NSString stringWithFormat:@"%@\nReason: %@\nUser Info: %@", [exception name], [exception reason], [exception userInfo]]; - NSLog(@"Exception raised:\n%@", exceptionMessage); - NSLog(@"Backtrace: %@", [exception callStackSymbols]); - } - if(model != nil) { - NSError *error = nil; - BOOL configurationSet = [self.editorViewController setConfiguration:self.configuration modelURL:self.modelURL storeURL:self.storeURL needsReload:YES error:&error]; - if(configurationSet == NO) { - [errorMessages addObject:@"• Configuration is invalid."]; - } - } + @catch (NSException *exception) { + [errorMessages addObject:@"• Model could not be loaded because an exception occured."]; + NSString *exceptionMessage = [NSString stringWithFormat:@"%@\nReason: %@\nUser Info: %@", [exception name], [exception reason], [exception userInfo]]; + NSLog(@"Exception raised:\n%@", exceptionMessage); + NSLog(@"Backtrace: %@", [exception callStackSymbols]); + } + if(model != nil) { + NSError *error = nil; + BOOL configurationSet = [self.editorViewController setConfiguration:self.configuration modelURL:self.modelURL storeURL:self.storeURL needsReload:YES error:&error]; + if(configurationSet == NO) { + [errorMessages addObject:@"• Configuration is invalid."]; + } + } + + BOOL configurationIsValid = (errorMessages.count == 0); + if(!configurationIsValid) { + NSString *message = nil; + if(errorMessages.count > 1) { + message = @"There were multiple problems with the current project configuration:\n\n"; + } else { + message = @"There is one problem with the current project configuration:\n\n"; + } + NSString *errorMessagesForDisplay = [errorMessages.array componentsJoinedByString:@"\n"]; + message = [message stringByAppendingString:errorMessagesForDisplay]; + message = [message stringByAppendingString:@"\n\nYou can configure the project now to resolve those problems. If you do so the project will be usable again."]; - BOOL configurationIsValid = (errorMessages.count == 0); - if(!configurationIsValid) { - NSString *message = nil; - if(errorMessages.count > 1) { - message = @"There were multiple problems with the current project configuration:\n\n"; - } else { - message = @"There is one problem with the current project configuration:\n\n"; - } - NSString *errorMessagesForDisplay = [errorMessages.array componentsJoinedByString:@"\n"]; - message = [message stringByAppendingString:errorMessagesForDisplay]; - message = [message stringByAppendingString:@"\n\nYou can configure the project now to resolve those problems. If you do so the project will be usable again."]; - - NSAlert *alert = [NSAlert new]; - alert.messageText = message; - alert.informativeText = @"Unable to open Project"; - [alert addButtonWithTitle:@"Configure"]; - [alert addButtonWithTitle:@"Cancel"]; - [alert beginSheetModalForWindow:[self _documentWindow] completionHandler:^(NSModalResponse returnCode) { - if(returnCode == NSAlertFirstButtonReturn) { // "Configure" was clicked - [self.configurationWizzard setEditing:YES]; - double delayInSeconds = 0.5; - dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); - dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ - [self showConfiguration:self]; - }); - } else { // "Cancel" was clicked - [self close]; - } - - }]; + NSAlert *alert = [NSAlert new]; + alert.messageText = message; + alert.informativeText = @"Unable to open Project"; + [alert addButtonWithTitle:@"Configure"]; + [alert addButtonWithTitle:@"Cancel"]; + [alert beginSheetModalForWindow:[self _documentWindow] completionHandler:^(NSModalResponse returnCode) { + if(returnCode == NSAlertFirstButtonReturn) { // "Configure" was clicked + [self.configurationWizzard setEditing:YES]; + double delayInSeconds = 0.5; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); + dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + [self showConfiguration:self]; + }); + } else { // "Cancel" was clicked + [self close]; } + + }]; } + } } - (void)close { - [self.editorViewController cleanup]; - [super close]; + [self.editorViewController cleanup]; + [super close]; } + (BOOL)autosavesInPlace { - return YES; + return YES; } #pragma mark - Query Control - (IBAction)takeQueryFromSender:(id)sender { - [self.editorViewController takeQueryFromSender:sender]; + [self.editorViewController takeQueryFromSender:sender]; } #pragma mark - Actions - (IBAction)deleteSelectedObjcts:(id)sender { - [self.editorViewController deleteSelectedObjcts:sender]; + [self.editorViewController deleteSelectedObjcts:sender]; } - (IBAction)insertObject:(id)sender { - [self.editorViewController insertObject:sender]; + [self.editorViewController insertObject:sender]; } - (IBAction)copySelectedObjectsAsCSV:(id)sender { - [self.editorViewController copySelectedObjectsAsCSV:sender]; + [self.editorViewController copySelectedObjectsAsCSV:sender]; } #pragma mark - Importing/Exporting - (IBAction)showImportCSVFileWindow:(id)sender { - [self.editorViewController showImportCSVFileWindow:sender]; + [self.editorViewController showImportCSVFileWindow:sender]; } @end diff --git a/Core Data Editor/Core Data Editor/CDEDocument.xcdatamodeld/.xccurrentversion b/Core Data Editor/Core Data Editor/CDEDocument.xcdatamodeld/.xccurrentversion deleted file mode 100644 index 0dd228a..0000000 --- a/Core Data Editor/Core Data Editor/CDEDocument.xcdatamodeld/.xccurrentversion +++ /dev/null @@ -1,8 +0,0 @@ - - - - - _XCCurrentVersionName - CDEDocument.xcdatamodel - - diff --git a/Core Data Editor/Core Data Editor/CDEDocument.xcdatamodeld/CDEDocument.xcdatamodel/contents b/Core Data Editor/Core Data Editor/CDEDocument.xcdatamodeld/CDEDocument.xcdatamodel/contents deleted file mode 100644 index be3b6c6..0000000 --- a/Core Data Editor/Core Data Editor/CDEDocument.xcdatamodeld/CDEDocument.xcdatamodel/contents +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Core Data Editor/Core Data Editor/CDEEditorViewController.m b/Core Data Editor/Core Data Editor/CDEEditorViewController.m index 43e2a08..34f6a81 100644 --- a/Core Data Editor/Core Data Editor/CDEEditorViewController.m +++ b/Core Data Editor/Core Data Editor/CDEEditorViewController.m @@ -141,13 +141,15 @@ - (void)loadView { } #pragma mark - Displaying a Configuration -- (BOOL)setConfiguration:(CDEConfiguration *)configuration modelURL:(NSURL *)modelURL storeURL:(NSURL *)storeURL needsReload:(BOOL)needsReload error:(NSError **)error { +- (BOOL)setConfiguration:(CDEConfiguration *)configuration + modelURL:(NSURL *)modelURL + storeURL:(NSURL *)storeURL + needsReload:(BOOL)needsReload + error:(NSError **)error { BOOL performReload = ((_configuration == nil) || (configuration == nil) || ([_configuration isEqual:configuration] == NO) || (needsReload)); - // Cleanup - self.configuration = configuration; self.autosaveInformation = [[CDEAutosaveInformation alloc] initWithDictionaryRepresentation:self.configuration.autosaveInformationByEntityName]; diff --git a/Core Data Editor/Core Data Editor/CDEEntityRequestDataCoordinator.m b/Core Data Editor/Core Data Editor/CDEEntityRequestDataCoordinator.m index 5ea4731..0c44fed 100644 --- a/Core Data Editor/Core Data Editor/CDEEntityRequestDataCoordinator.m +++ b/Core Data Editor/Core Data Editor/CDEEntityRequestDataCoordinator.m @@ -5,138 +5,145 @@ #import "CDEEntityAutosaveInformationItem.h" #import "CDEManagedObjectsViewController.h" #import "CDERequestDataCoordinator_Subclass.h" +#import "FilteringArray.h" @interface CDEEntityRequestDataCoordinator () #pragma mark - Properties -@property (nonatomic, strong) NSArrayController *arrayController; +@property (strong) FilteringArray *filteringArray; @end @implementation CDEEntityRequestDataCoordinator - (NSInteger)numberOfObjects { - return [[self.arrayController arrangedObjects] count]; + return self.filteringArray == nil ? 0 : self.filteringArray.count; } // Returning nil is okay - (id)objectValueForTableColumn:(NSTableColumn *)tableColumn atIndex:(NSUInteger)index { - NSManagedObject *object = [self.arrayController arrangedObjects][index]; - id objectValue = [object valueForKey:tableColumn.identifier]; - return objectValue; + NSManagedObject *object = [self managedObjectAtIndex: index]; + id objectValue = [object valueForKey:tableColumn.identifier]; + return objectValue; } - (NSManagedObject *)managedObjectAtIndex:(NSUInteger)index { - NSManagedObject *object = [self.arrayController arrangedObjects][index]; - return object; + NSManagedObject *object = [self.filteringArray objectAtIndex:index]; + return object; } - (NSUInteger)indexOfManagedObject:(NSManagedObject *)managedObject { - NSParameterAssert(managedObject); - return [[self.arrayController arrangedObjects] indexOfObject:managedObject]; + NSParameterAssert(managedObject); + return [self.filteringArray indexOfObject:managedObject]; } - (NSDictionary *)tableColumnsByIdentifier { - NSMutableDictionary *result = [NSMutableDictionary new]; - for(NSTableColumn *column in self.tableColumns) { - result[column.identifier] = column; - } - return result; + NSMutableDictionary *result = [NSMutableDictionary new]; + for(NSTableColumn *column in self.tableColumns) { + result[column.identifier] = column; + } + return result; +} + +- (void)dealloc +{ + NSLog(@""); } - (void)prepare { - // Adjust columns - CDEAutosaveInformation *autosaveInformation = self.managedObjectsViewController.autosaveInformation; - if(autosaveInformation != nil) { - // Get the information for the entity - NSString *entityName = self.request.entityDescription.name; - if(entityName != nil) { - CDEEntityAutosaveInformation *entityInformation = [autosaveInformation informationForEntityNamed:entityName]; - if(entityInformation != nil) { - NSDictionary *tableColumnsByIdentifier = [self tableColumnsByIdentifier]; - NSMutableOrderedSet *newColumns = [NSMutableOrderedSet orderedSetWithArray:self.tableColumns]; - NSUInteger designatedIndex = 0; - for(CDEEntityAutosaveInformationItem *item in entityInformation.items) { - NSTableColumn *column = tableColumnsByIdentifier[item.identifier]; - if(column != nil) { - NSUInteger currentIndex = [newColumns indexOfObject:column]; - if(currentIndex != NSNotFound && newColumns.count > designatedIndex) { - [newColumns moveObjectsAtIndexes:[NSIndexSet indexSetWithIndex:currentIndex] toIndex:designatedIndex]; - } - column.width = item.width; - } - designatedIndex++; - } - self.tableColumns = newColumns.array; + NSAssert(self.request.isEntityRequest, @""); + // Adjust columns + CDEAutosaveInformation *autosaveInformation = self.managedObjectsViewController.autosaveInformation; + if(autosaveInformation != nil) { + // Get the information for the entity + NSString *entityName = self.request.entityDescription.name; + if(entityName != nil) { + CDEEntityAutosaveInformation *entityInformation = [autosaveInformation informationForEntityNamed:entityName]; + if(entityInformation != nil) { + NSDictionary *tableColumnsByIdentifier = [self tableColumnsByIdentifier]; + NSMutableOrderedSet *newColumns = [NSMutableOrderedSet orderedSetWithArray:self.tableColumns]; + NSUInteger designatedIndex = 0; + for(CDEEntityAutosaveInformationItem *item in entityInformation.items) { + NSTableColumn *column = tableColumnsByIdentifier[item.identifier]; + if(column != nil) { + NSUInteger currentIndex = [newColumns indexOfObject:column]; + if(currentIndex != NSNotFound && newColumns.count > designatedIndex) { + [newColumns moveObjectsAtIndexes:[NSIndexSet indexSetWithIndex:currentIndex] toIndex:designatedIndex]; } + column.width = item.width; + } + designatedIndex++; } + self.tableColumns = newColumns.array; + } } - - // Array Controller - self.arrayController = [[NSArrayController alloc] initWithContent:nil]; - self.arrayController.entityName = self.request.entityDescription.name; - self.arrayController.managedObjectContext = self.request.managedObjectContext; - self.arrayController.selectsInsertedObjects = YES; - NSFetchRequest *fetchRequest = nil; - if(self.request.isFetchRequest) { - fetchRequest = self.request.fetchRequest; - } else { - fetchRequest = [NSFetchRequest fetchRequestWithEntityName:self.request.entityDescription.name]; - } - fetchRequest.entity = self.request.entityDescription; - - NSError *error = nil; - BOOL fetched = [self.arrayController fetchWithRequest:fetchRequest merge:NO error:&error]; - if(fetched == NO) { - NSLog(@"Error: %@", error); - return; - } - - [self.tableView bind:NSContentBinding toObject:self.arrayController withKeyPath:@"arrangedObjects" options:nil]; - [self.tableView bind:NSSelectionIndexesBinding toObject:self.arrayController withKeyPath:@"selectionIndexes" options:nil]; - [self.tableView bind:NSSortDescriptorsBinding toObject:self.arrayController withKeyPath:@"sortDescriptors" options:nil]; + } + + NSError *fetchError = nil; + NSString *entityName = self.request.entityDescription.name; + NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:entityName]; + NSArray *objects = [self.request.managedObjectContext executeFetchRequest:fetchRequest error:&fetchError]; + if(objects == nil) { + NSLog(@"error: %@", fetchError); + return; + } + self.filteringArray = [FilteringArray new]; + [self.filteringArray addObjectsFromArray:objects]; + [self.tableView reloadData]; } - (void)invalidate { - [self.tableView unbind:NSContentBinding]; - [self.tableView unbind:NSSelectionIndexesBinding]; - [self.tableView unbind:NSSortDescriptorsBinding]; - self.arrayController = nil; } - (NSManagedObject *)createAndAddManagedObject { - NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:self.request.entityDescription.name inManagedObjectContext:self.request.managedObjectContext]; - [self.arrayController addObject:object]; - return object; + NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:self.request.entityDescription.name inManagedObjectContext:self.request.managedObjectContext]; + [self addObject:object]; + return object; +} + +- (void)removeSelectedManagedObjects { + NSIndexSet *indexes = [self indexesOfSelectedManagedObjects]; + NSArray* objects = [self.filteringArray objectsAtIndexes:indexes]; + [self.filteringArray removeObjectsAtIndexes:indexes]; + for(NSManagedObject *object in objects) { + [self.request.managedObjectContext deleteObject:object]; + } + [self.tableView reloadData]; + } - (void)removeManagedObjectAtIndex:(NSUInteger)index { - [self.arrayController removeObjectAtArrangedObjectIndex:index]; + [self.filteringArray removeObjectAtIndex:index]; } - (NSView *)viewForTableColumn:(NSTableColumn *)tableColumn atIndex:(NSInteger)index { - return [super viewForTableColumn:tableColumn atIndex:index]; + return [super viewForTableColumn:tableColumn atIndex:index]; } - (void)didChangeFilterPredicate { - self.arrayController.filterPredicate = self.filterPredicate; - NSNotification *notification = [NSNotification notificationWithName:NSTableViewSelectionDidChangeNotification object:self.tableView userInfo:@{}]; - [self.tableView.delegate tableViewSelectionDidChange:notification]; + [self.filteringArray setFilterPredicate:self.filterPredicate]; + [self.tableView reloadData]; + NSNotification *notification = [NSNotification notificationWithName:NSTableViewSelectionDidChangeNotification object:self.tableView userInfo:@{}]; + [self.tableView.delegate tableViewSelectionDidChange:notification]; } - (BOOL)canPerformAdd { - return YES; + return YES; } - (BOOL)canPerformDelete { - // Delete only possible if there is a selection - return (self.tableView.selectedRow != -1); - return [[self.arrayController selectedObjects] count] > 0; + // Delete only possible if there is a selection + return (self.tableView.selectedRow != -1); } #pragma mark - Autosave - (void)updateAutosaveInformation:(CDEAutosaveInformation *)autosaveInformation { - // do nothing by default + // do nothing by default +} + +#pragma mark - Modifying the Fetched Objects +- (void)addObject:(NSManagedObject *)object { + [self.filteringArray addObject:object]; } @end diff --git a/Core Data Editor/Core Data Editor/CDEManagedObjectsViewController.m b/Core Data Editor/Core Data Editor/CDEManagedObjectsViewController.m index 1f72f48..25495b0 100644 --- a/Core Data Editor/Core Data Editor/CDEManagedObjectsViewController.m +++ b/Core Data Editor/Core Data Editor/CDEManagedObjectsViewController.m @@ -201,6 +201,7 @@ - (IBAction)add:(id)sender { [self updateAddAndRemoveButtons]; [self managedObjectsViewControllerDidChangeContents]; NSInteger row = [self.dataCoordinator indexOfManagedObject:addedObject]; + [self.tableView reloadData]; [self.tableView scrollRowToVisible:row]; } @@ -485,5 +486,4 @@ -(void)viewDidDisappear: (BOOL)animated { } - @end diff --git a/Core Data Editor/Core Data Editor/CDEProjectBrowserWindowController.m b/Core Data Editor/Core Data Editor/CDEProjectBrowserWindowController.m index 9d0c646..a70d46a 100644 --- a/Core Data Editor/Core Data Editor/CDEProjectBrowserWindowController.m +++ b/Core Data Editor/Core Data Editor/CDEProjectBrowserWindowController.m @@ -83,20 +83,14 @@ - (IBAction)createProject:(id)sender { return; } CDEDocument *document = [[NSDocumentController sharedDocumentController] openUntitledDocumentAndDisplay:NO error:NULL]; - CDEConfiguration *c = [document createConfiguration]; + CDEConfiguration *configuration = [document createConfiguration]; NSError *error = nil; NSURL *storeURL = [NSURL fileURLWithPath:item.storePath]; NSURL *modelURL = [NSURL fileURLWithPath:item.modelPath]; - BOOL set = [c setBookmarkDataWithApplicationBundleURL:nil storeURL:storeURL modelURL:modelURL error:&error]; - if(!set) { - NSLog(@"error: %@", error); - } + [configuration setApplicationBundleURL:nil storeURL:storeURL modelURL:modelURL]; + error = nil; - BOOL setup = [document setupAndStartAccessingConfigurationRelatedURLsAndGetError:&error]; - if(!setup) { - NSLog(@"error: %@", error); - } [document makeWindowControllers]; [document showWindows]; } diff --git a/Core Data Editor/Core Data Editor/CDESetupWindowController.m b/Core Data Editor/Core Data Editor/CDESetupWindowController.m index 1e4ea9d..3c0aed9 100644 --- a/Core Data Editor/Core Data Editor/CDESetupWindowController.m +++ b/Core Data Editor/Core Data Editor/CDESetupWindowController.m @@ -14,71 +14,75 @@ @interface CDESetupWindowController () @implementation CDESetupWindowController - (instancetype)init { - self = [super initWithWindowNibName:@"CDESetupWindowController" owner:self]; - if(self) { } - return self; + self = [super initWithWindowNibName:@"CDESetupWindowController" owner:self]; + if(self) { } + return self; } - (void)windowDidLoad { - [super windowDidLoad]; - - self.simulatorPathPopupButton.otherItemSelectedHandler = ^(CDEPathPickerPopUpButton *sender) { - [self showSimulatorDirectoryPicker:sender]; - }; - self.derivedDataPathPopupButton.otherItemSelectedHandler = ^(CDEPathPickerPopUpButton *sender) { - [self showDerivdedDataPicker:sender]; - }; + [super windowDidLoad]; + + self.simulatorPathPopupButton.otherItemSelectedHandler = ^(CDEPathPickerPopUpButton *sender) { + [self showSimulatorDirectoryPicker:sender]; + }; + self.derivedDataPathPopupButton.otherItemSelectedHandler = ^(CDEPathPickerPopUpButton *sender) { + [self showDerivdedDataPicker:sender]; + }; + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + self.simulatorPathPopupButton.URL = defaults.simulatorDirectory_cde; + self.derivedDataPathPopupButton.URL = defaults.buildProductsDirectory_cde; + } - (IBAction)showSimulatorDirectoryPicker:(id)sender { - NSOpenPanel *panel = [NSOpenPanel openPanel]; - [panel setCanChooseDirectories:YES]; - [panel setCanChooseFiles:NO]; - [panel setShowsHiddenFiles:YES]; - [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) { - if(result == NSFileHandlingPanelOKButton) { - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - defaults.simulatorDirectory_cde = panel.URL; - self.simulatorPathPopupButton.URL = defaults.simulatorDirectory_cde; - } - }]; + NSOpenPanel *panel = [NSOpenPanel openPanel]; + [panel setCanChooseDirectories:YES]; + [panel setCanChooseFiles:NO]; + [panel setShowsHiddenFiles:YES]; + [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) { + if(result == NSFileHandlingPanelOKButton) { + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + defaults.simulatorDirectory_cde = panel.URL; + self.simulatorPathPopupButton.URL = defaults.simulatorDirectory_cde; + } + }]; } - (IBAction)showDerivdedDataPicker:(id)sender { - NSOpenPanel *panel = [NSOpenPanel openPanel]; - [panel setCanChooseDirectories:YES]; - [panel setCanChooseFiles:NO]; - [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) { - if(result == NSFileHandlingPanelOKButton) { - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - defaults.buildProductsDirectory_cde = panel.URL; - self.derivedDataPathPopupButton.URL = defaults.buildProductsDirectory_cde; - } - }]; + NSOpenPanel *panel = [NSOpenPanel openPanel]; + [panel setCanChooseDirectories:YES]; + [panel setCanChooseFiles:NO]; + [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) { + if(result == NSFileHandlingPanelOKButton) { + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + defaults.buildProductsDirectory_cde = panel.URL; + self.derivedDataPathPopupButton.URL = defaults.buildProductsDirectory_cde; + } + }]; } #pragma mark - Actions - (IBAction)beginSetupProcess:(id)sender { - [self.tabView selectNextTabViewItem:sender]; + [self.tabView selectNextTabViewItem:sender]; } - (IBAction)showBuildProductsSetupTab:(id)sender { - [self.tabView selectNextTabViewItem:sender]; + [self.tabView selectNextTabViewItem:sender]; } - (IBAction)showSummary:(id)sender { - [self.tabView selectNextTabViewItem:sender]; - [[NSUserDefaults standardUserDefaults] setApplicationNeedsSetup_cde:NO]; + [self.tabView selectNextTabViewItem:sender]; + [[NSUserDefaults standardUserDefaults] setApplicationNeedsSetup_cde:NO]; } - (IBAction)openProjectBrowser:(id)sender { - [self.window orderOut:self]; - [(CDEApplicationDelegate *)[NSApp delegate] showProjectBrowser:sender]; + [self.window orderOut:self]; + [(CDEApplicationDelegate *)[NSApp delegate] showProjectBrowser:sender]; } - (IBAction)createNewProject:(id)sender { - [self.window orderOut:self]; - [[NSDocumentController sharedDocumentController] newDocument:self]; + [self.window orderOut:self]; + [[NSDocumentController sharedDocumentController] newDocument:self]; } @end diff --git a/Core Data Editor/Core Data Editor/FilteringArray.h b/Core Data Editor/Core Data Editor/FilteringArray.h new file mode 100644 index 0000000..b090442 --- /dev/null +++ b/Core Data Editor/Core Data Editor/FilteringArray.h @@ -0,0 +1,13 @@ +#import + +@interface FilteringArray: NSObject +- (void)setFilterPredicate:(NSPredicate *)predicate; +- (void)addObject:(ObjectType)anObject; +- (void)removeObjectAtIndex:(NSUInteger)index; +- (ObjectType)objectAtIndex:(NSUInteger)index; +- (void)addObjectsFromArray:(NSArray *)otherArray; +- (NSUInteger)indexOfObject:(ObjectType)anObject; +- (void)removeObjectsAtIndexes:(NSIndexSet *)indexes; +- (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes; +- (NSUInteger)count; +@end diff --git a/Core Data Editor/Core Data Editor/FilteringArray.m b/Core Data Editor/Core Data Editor/FilteringArray.m new file mode 100644 index 0000000..1a5d5c7 --- /dev/null +++ b/Core Data Editor/Core Data Editor/FilteringArray.m @@ -0,0 +1,80 @@ +#import "FilteringArray.h" + +@interface FilteringArray () + +@property (strong) NSMutableArray *_allObjects; +@property (strong) NSMutableArray *_filteredObjects; +@property (strong) NSPredicate *_predicate; + +@end + +@implementation FilteringArray + +- (instancetype)init { + self = [super init]; + self._allObjects = [NSMutableArray new]; + self._filteredObjects = [NSMutableArray new]; + return self; +} + +- (void)setFilterPredicate:(NSPredicate *)predicate { + self._predicate = predicate; + [self applyFilter]; +} + +- (void)applyFilter { + self._filteredObjects = self._allObjects; + + if(self._predicate == nil) { + return; + } + + [self._filteredObjects filterUsingPredicate:self._predicate]; +} + +- (void)addObject:(id)object { + [self._allObjects addObject: object]; + [self applyFilter]; +} +- (void)removeObjectAtIndex:(NSUInteger)index { + [self._allObjects removeObjectAtIndex:index]; + [self applyFilter]; +} +- (id)objectAtIndex:(NSUInteger)index { + if(self._predicate == nil) { + return [self._allObjects objectAtIndex:index]; + } + return [self._filteredObjects objectAtIndex:index]; +} +- (void)addObjectsFromArray:(NSArray *)otherArray { + [self._allObjects addObjectsFromArray:otherArray]; + [self applyFilter]; +} +- (NSUInteger)indexOfObject:(id)object { + if(self._predicate == nil) { + return [self._allObjects indexOfObject:object]; + } + return [self._filteredObjects indexOfObject:object]; + +} + +- (NSUInteger)count { + if(self._predicate == nil) { + return self._allObjects.count; + } + return self._filteredObjects.count; + +} +- (void)removeObjectsAtIndexes:(NSIndexSet *)indexes { + NSArray *objectsToRemove = [[self objects] objectsAtIndexes:indexes]; + [self._allObjects removeObjectsInArray:objectsToRemove]; + [self applyFilter]; +} + +- (NSMutableArray *)objects { + return self._predicate == nil ? self._allObjects : self._filteredObjects; +} +- (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes { + return [self.objects objectsAtIndexes:indexes]; +} +@end diff --git a/Core Data Editor/Core Data Editor/Main.storyboard b/Core Data Editor/Core Data Editor/Main.storyboard index f62a9c5..44bb64e 100644 --- a/Core Data Editor/Core Data Editor/Main.storyboard +++ b/Core Data Editor/Core Data Editor/Main.storyboard @@ -102,9 +102,10 @@ - + + - + diff --git a/Core Data Editor/Core Data Editor/NSURL+CDEAdditions.h b/Core Data Editor/Core Data Editor/NSURL+CDEAdditions.h index a8c9586..f3d7d3c 100644 --- a/Core Data Editor/Core Data Editor/NSURL+CDEAdditions.h +++ b/Core Data Editor/Core Data Editor/NSURL+CDEAdditions.h @@ -2,10 +2,6 @@ @interface NSURL (CDEAdditions) -#pragma mark - Bookmarks (Convenience) -+ (NSURL *)URLByResolvingBookmarkData:(NSData *)data error_cde:(NSError **)error; -- (NSData *)bookmarkDataAndGetError_cde:(NSError **)error; - #pragma mark - UTI - (NSString *)typeOfFileURLAndGetError_cde:(NSError **)error; - (BOOL)isCompiledManagedObjectModelFile_cde; @@ -21,4 +17,4 @@ @interface NSURL (CDESQLiteAdditions) - (BOOL)isSQLiteURL_cde; - (BOOL)isSQLiteStoreURL_cde; -@end \ No newline at end of file +@end diff --git a/Core Data Editor/Core Data Editor/NSURL+CDEAdditions.m b/Core Data Editor/Core Data Editor/NSURL+CDEAdditions.m index 9b364be..4597db4 100644 --- a/Core Data Editor/Core Data Editor/NSURL+CDEAdditions.m +++ b/Core Data Editor/Core Data Editor/NSURL+CDEAdditions.m @@ -3,33 +3,6 @@ @implementation NSURL (CDEAdditions) -#pragma mark - Bookmarks (Convenience) -+ (NSURL *)URLByResolvingBookmarkData:(NSData *)data error_cde:(NSError **)error { - NSParameterAssert(data); - - return [NSURL URLByResolvingBookmarkData:data - options:NSURLBookmarkResolutionWithoutUI - relativeToURL:nil - bookmarkDataIsStale:NULL - error:error]; -} - -- (NSData *)bookmarkDataAndGetError_cde:(NSError **)error { - NSError *localError = nil; - NSURL *pathOnlyURL = [NSURL fileURLWithPath:[self path]]; - NSData *result = [pathOnlyURL bookmarkDataWithOptions:NSURLBookmarkCreationSuitableForBookmarkFile - includingResourceValuesForKeys:nil - relativeToURL:nil - error:&localError]; - if(result == nil) { - if(error != NULL) { - *error = localError; - } - return nil; - } - return result; -} - #pragma mark - UTI - (NSString *)typeOfFileURLAndGetError_cde:(NSError **)error { NSWorkspace *workspace = [NSWorkspace sharedWorkspace]; diff --git a/Core Data Editor/Core Data Editor/NSUserDefaults+CDEAdditions.h b/Core Data Editor/Core Data Editor/NSUserDefaults+CDEAdditions.h index 65e5d75..2fbf2cc 100644 --- a/Core Data Editor/Core Data Editor/NSUserDefaults+CDEAdditions.h +++ b/Core Data Editor/Core Data Editor/NSUserDefaults+CDEAdditions.h @@ -1,23 +1,23 @@ #import extern const struct CDEUserDefaultsKeys { - __unsafe_unretained NSString *showsNameOfEntityInObjectIDColumn; - __unsafe_unretained NSString *numberOfDecimals; - __unsafe_unretained NSString *dateFormatterTimeStyle; - __unsafe_unretained NSString *dateFormatterDateStyle; - __unsafe_unretained NSString *showsNiceEntityAndPropertyNames; - __unsafe_unretained NSString *automaticallyResolvesValidationErrors; - __unsafe_unretained NSString *buildProductsDirectoryBookmarkData; - __unsafe_unretained NSString *simulatorDirectoryBookmarkData; - __unsafe_unretained NSString *applicationNeedsSetup; - __unsafe_unretained NSString *firstLaunchDate; - __unsafe_unretained NSString *openProjectBrowserOnLaunch; - + __unsafe_unretained NSString *showsNameOfEntityInObjectIDColumn; + __unsafe_unretained NSString *numberOfDecimals; + __unsafe_unretained NSString *dateFormatterTimeStyle; + __unsafe_unretained NSString *dateFormatterDateStyle; + __unsafe_unretained NSString *showsNiceEntityAndPropertyNames; + __unsafe_unretained NSString *automaticallyResolvesValidationErrors; + __unsafe_unretained NSString *buildProductsDirectory; + __unsafe_unretained NSString *simulatorDirectory; + __unsafe_unretained NSString *applicationNeedsSetup; + __unsafe_unretained NSString *firstLaunchDate; + __unsafe_unretained NSString *openProjectBrowserOnLaunch; + } CDEUserDefaultsKeys; extern const struct CDEUserDefaultsNotifications { - __unsafe_unretained NSString *didChangeSimulatorDirectory; - __unsafe_unretained NSString *didChangeBuildProductsDirectory; + __unsafe_unretained NSString *didChangeSimulatorDirectory; + __unsafe_unretained NSString *didChangeBuildProductsDirectory; } CDEUserDefaultsNotifications; @interface NSUserDefaults (CDEAdditions) @@ -27,40 +27,34 @@ extern const struct CDEUserDefaultsNotifications { #pragma mark - Properties @property (nonatomic, assign, getter = showsNameOfEntityInObjectIDColumn_cde, - setter = setShowsNameOfEntityInObjectIDColumn_cde:) BOOL showsNameOfEntityInObjectIDColumn; + setter = setShowsNameOfEntityInObjectIDColumn_cde:) BOOL showsNameOfEntityInObjectIDColumn; @property (nonatomic, assign, getter = opensProjectBrowserOnLaunch_cde, setter = setOpenProjectBrowserOnLaunch_cde:) BOOL opensProjectBrowserOnLaunch; @property (nonatomic, assign, getter = numberOfDecimals_cde, - setter = setNumberOfDecimals_cde:) NSInteger numberOfDecimals; + setter = setNumberOfDecimals_cde:) NSInteger numberOfDecimals; @property (nonatomic, assign, getter = dateFormatterTimeStyle_cde, - setter = setDateFormatterTimeStyle_cde:) NSDateFormatterStyle dateFormatterTimeStyle; + setter = setDateFormatterTimeStyle_cde:) NSDateFormatterStyle dateFormatterTimeStyle; @property (nonatomic, assign, getter = dateFormatterDateStyle_cde, - setter = setDateFormatterDateStyle_cde:) NSDateFormatterStyle dateFormatterDateStyle; + setter = setDateFormatterDateStyle_cde:) NSDateFormatterStyle dateFormatterDateStyle; @property (nonatomic, readonly) NSDateFormatter *dateFormatter_cde; @property (nonatomic, readonly) NSNumberFormatter *floatingPointNumberFormatter_cde; @property (nonatomic, assign, getter = showsNiceEntityAndPropertyNames_cde, - setter = setShowsNiceEntityAndPropertyNames_cde:) BOOL showsNiceEntityAndPropertyNames; + setter = setShowsNiceEntityAndPropertyNames_cde:) BOOL showsNiceEntityAndPropertyNames; @property (nonatomic, assign, getter = automaticallyResolvesValidationErrors_cde, - setter = setAutomaticallyResolvesValidationErrors_cde:) BOOL automaticallyResolvesValidationErrors_cde; - -@property (nonatomic, copy, getter = buildProductsDirectoryBookmarkData_cde, - setter = setBuildProductsDirectoryBookmarkData_cde:) NSData *buildProductsDirectoryBookmarkData_cde; + setter = setAutomaticallyResolvesValidationErrors_cde:) BOOL automaticallyResolvesValidationErrors_cde; @property (nonatomic, getter = buildProductsDirectory_cde, setter = setBuildProductsDirectory_cde:) NSURL *buildProductsDirectory_cde; -@property (nonatomic, copy, getter = simulatorDirectoryBookmarkData_cde, - setter = setSimulatorDirectoryBookmarkData_cde:) NSData *simulatorDirectoryBookmarkData_cde; - @property (nonatomic, getter = simulatorDirectory_cde, setter = setSimulatorDirectory_cde:) NSURL *simulatorDirectory_cde; @property (nonatomic, assign, getter = applicationNeedsSetup_cde, - setter = setApplicationNeedsSetup_cde:) BOOL applicationNeedsSetup; + setter = setApplicationNeedsSetup_cde:) BOOL applicationNeedsSetup; @end diff --git a/Core Data Editor/Core Data Editor/NSUserDefaults+CDEAdditions.m b/Core Data Editor/Core Data Editor/NSUserDefaults+CDEAdditions.m index 0e644ff..bd04f0d 100644 --- a/Core Data Editor/Core Data Editor/NSUserDefaults+CDEAdditions.m +++ b/Core Data Editor/Core Data Editor/NSUserDefaults+CDEAdditions.m @@ -8,8 +8,8 @@ .dateFormatterDateStyle = @"CDEUserDefaultsDateFormatterDateStyle", .showsNiceEntityAndPropertyNames = @"CDEUserDefaultsShowsNiceEntityAndPropertyNames", .automaticallyResolvesValidationErrors = @"CDEUserDefaultsAutomaticallyResolvesValidationErrors", - .buildProductsDirectoryBookmarkData = @"CDEUserDefaultsBuildProductsDirectoryBookmarkData", - .simulatorDirectoryBookmarkData = @"CDEUserDefaultsSimulatorDirectoryBookmarkData", + .buildProductsDirectory = @"CDEUserDefaultsBuildProductsDirectory", + .simulatorDirectory = @"CDEUserDefaultsSimulatorDirectory", .applicationNeedsSetup = @"CDEUserDefaultsApplicationNeedsSetup", .firstLaunchDate = @"CDEUserDefaultsFirstLaunchDate", .openProjectBrowserOnLaunch = @"CDEUserDefaultsOpenProjectBrowserOnLaunch", @@ -24,7 +24,12 @@ @implementation NSUserDefaults (CDEAdditions) #pragma mark - Register Defaults + (void)registerCoreDataEditorDefaults_cde { - NSDictionary *defaults = @{ CDEUserDefaultsKeys.showsNameOfEntityInObjectIDColumn : @NO, + + NSURL *buildProductsDirectory = [NSURL fileURLWithPath:[@"~/Library/Developer/Xcode/DerivedData/" stringByExpandingTildeInPath]]; + NSURL *simulatorDirectory = [NSURL fileURLWithPath:[@"~/Library/Developer/CoreSimulator/" stringByExpandingTildeInPath]]; + NSDictionary *defaults = @{ CDEUserDefaultsKeys.buildProductsDirectory : buildProductsDirectory, + CDEUserDefaultsKeys.simulatorDirectory : simulatorDirectory, + CDEUserDefaultsKeys.showsNameOfEntityInObjectIDColumn : @NO, CDEUserDefaultsKeys.numberOfDecimals : @2, CDEUserDefaultsKeys.dateFormatterDateStyle : @(NSDateFormatterShortStyle), CDEUserDefaultsKeys.dateFormatterTimeStyle : @(NSDateFormatterShortStyle), @@ -46,16 +51,15 @@ - (BOOL)showsNameOfEntityInObjectIDColumn_cde { - (void)setShowsNameOfEntityInObjectIDColumn_cde:(BOOL)showsNameOfEntityInObjectIDColumn { [self setBool:showsNameOfEntityInObjectIDColumn forKey:CDEUserDefaultsKeys.showsNameOfEntityInObjectIDColumn]; } -- (BOOL)opensProjectBrowserOnLaunch_cde -{ + +- (BOOL)opensProjectBrowserOnLaunch_cde { return [self boolForKey:CDEUserDefaultsKeys.openProjectBrowserOnLaunch]; } -- (void)setOpenProjectBrowserOnLaunch_cde:(BOOL)opensProjectBrowserOnLaunch -{ + +- (void)setOpenProjectBrowserOnLaunch_cde:(BOOL)opensProjectBrowserOnLaunch { [self setBool:opensProjectBrowserOnLaunch forKey:CDEUserDefaultsKeys.openProjectBrowserOnLaunch]; } - - (NSInteger)numberOfDecimals_cde { return [self integerForKey:CDEUserDefaultsKeys.numberOfDecimals]; } @@ -83,11 +87,9 @@ - (void)setDateFormatterTimeStyle_cde:(NSDateFormatterStyle)dateFormatterTimeSty - (NSDateFormatter *)dateFormatter_cde { NSDateFormatterStyle timeStyle = [self dateFormatterTimeStyle_cde]; NSDateFormatterStyle dateStyle = [self dateFormatterDateStyle_cde]; - NSDateFormatter *formatter = [NSDateFormatter new]; [formatter setDateStyle:dateStyle]; [formatter setTimeStyle:timeStyle]; - return formatter; } @@ -117,70 +119,22 @@ - (void)setAutomaticallyResolvesValidationErrors_cde:(BOOL)automaticallyResolves [self setBool:automaticallyResolvesValidationErrors_cde forKey:CDEUserDefaultsKeys.automaticallyResolvesValidationErrors]; } -- (NSData *)buildProductsDirectoryBookmarkData_cde { - return [self dataForKey:CDEUserDefaultsKeys.buildProductsDirectoryBookmarkData]; -} - -- (void)setBuildProductsDirectoryBookmarkData_cde:(NSData *)buildProductsDirectoryBookmarkData { - [self setObject:buildProductsDirectoryBookmarkData forKey:CDEUserDefaultsKeys.buildProductsDirectoryBookmarkData]; - [[NSNotificationCenter defaultCenter] postNotificationName:CDEUserDefaultsNotifications.didChangeBuildProductsDirectory object:self]; -} - - (NSURL *)buildProductsDirectory_cde { - NSData *bookmarkData = self.buildProductsDirectoryBookmarkData_cde; - if(bookmarkData == nil) { - return nil; - } - NSError *error = nil; - NSURL *URL = [NSURL URLByResolvingBookmarkData:bookmarkData error_cde:&error]; - if(URL == nil) { - NSLog(@"failed to resolve bookmark data for build directory: %@", error); - return nil; - } - return URL; + return [self URLForKey:CDEUserDefaultsKeys.buildProductsDirectory]; } - (void)setBuildProductsDirectory_cde:(NSURL *)URL { - NSError *error = nil; - NSData *bookmarkData = [URL bookmarkDataAndGetError_cde:&error]; - if(bookmarkData == nil) { - NSLog(@"Failed to create bookmark data for selected build products directory '%@': %@", URL, error); - } - self.buildProductsDirectoryBookmarkData_cde = bookmarkData; -} - - -- (NSData *)simulatorDirectoryBookmarkData_cde { - return [self dataForKey:CDEUserDefaultsKeys.simulatorDirectoryBookmarkData]; -} - -- (void)setSimulatorDirectoryBookmarkData_cde:(NSData *)simulatorDirectoryBookmarkData { - [self setObject:simulatorDirectoryBookmarkData forKey:CDEUserDefaultsKeys.simulatorDirectoryBookmarkData]; - [[NSNotificationCenter defaultCenter] postNotificationName:CDEUserDefaultsNotifications.didChangeSimulatorDirectory object:self]; + [self setURL:URL forKey:CDEUserDefaultsKeys.buildProductsDirectory]; + [[NSNotificationCenter defaultCenter] postNotificationName:CDEUserDefaultsNotifications.didChangeBuildProductsDirectory object:self]; } - (NSURL *)simulatorDirectory_cde { - NSData *bookmarkData = self.simulatorDirectoryBookmarkData_cde; - if(bookmarkData == nil) { - return nil; - } - NSError *error = nil; - NSURL *URL = [NSURL URLByResolvingBookmarkData:bookmarkData error_cde:&error]; - - if(URL == nil) { - NSLog(@"failed to resolve bookmark data for build directory: %@", error); - return nil; - } - return URL; + return [self URLForKey:CDEUserDefaultsKeys.simulatorDirectory]; } - (void)setSimulatorDirectory_cde:(NSURL *)URL { - NSError *error = nil; - NSData *bookmarkData = [URL bookmarkDataAndGetError_cde:&error]; - if(bookmarkData == nil) { - NSLog(@"Failed to create bookmark data for selected build products directory '%@': %@", URL, error); - } - self.simulatorDirectoryBookmarkData_cde = bookmarkData; + [self setURL:URL forKey:CDEUserDefaultsKeys.simulatorDirectory]; + [[NSNotificationCenter defaultCenter] postNotificationName:CDEUserDefaultsNotifications.didChangeSimulatorDirectory object:self]; } - (void)setApplicationNeedsSetup_cde:(BOOL)applicationNeedsSetup { diff --git a/Core Data Editor/Core Data Editor/_CDEConfiguration.h b/Core Data Editor/Core Data Editor/_CDEConfiguration.h deleted file mode 100644 index f4441e4..0000000 --- a/Core Data Editor/Core Data Editor/_CDEConfiguration.h +++ /dev/null @@ -1,138 +0,0 @@ -// DO NOT EDIT. This file is machine-generated and constantly overwritten. -// Make changes to CDEConfiguration.h instead. - -#import - - -extern const struct CDEConfigurationAttributes { - __unsafe_unretained NSString *applicationBundleBookmarkData; - __unsafe_unretained NSString *autosaveInformationByEntityName; - __unsafe_unretained NSString *isMacApplication; - __unsafe_unretained NSString *modelBookmarkData; - __unsafe_unretained NSString *storeBookmarkData; -} CDEConfigurationAttributes; - -extern const struct CDEConfigurationRelationships { -} CDEConfigurationRelationships; - -extern const struct CDEConfigurationFetchedProperties { -} CDEConfigurationFetchedProperties; - - - -@class NSDictionary; - - - - -@interface CDEConfigurationID : NSManagedObjectID {} -@end - -@interface _CDEConfiguration : NSManagedObject {} -+ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_; -+ (NSString*)entityName; -+ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_; -- (CDEConfigurationID*)objectID; - - - - - -@property (nonatomic, strong) NSData* applicationBundleBookmarkData; - - - -//- (BOOL)validateApplicationBundleBookmarkData:(id*)value_ error:(NSError**)error_; - - - - - -@property (nonatomic, strong) NSDictionary* autosaveInformationByEntityName; - - - -//- (BOOL)validateAutosaveInformationByEntityName:(id*)value_ error:(NSError**)error_; - - - - - -@property (nonatomic, strong) NSNumber* isMacApplication; - - - -@property BOOL isMacApplicationValue; -- (BOOL)isMacApplicationValue; -- (void)setIsMacApplicationValue:(BOOL)value_; - -//- (BOOL)validateIsMacApplication:(id*)value_ error:(NSError**)error_; - - - - - -@property (nonatomic, strong) NSData* modelBookmarkData; - - - -//- (BOOL)validateModelBookmarkData:(id*)value_ error:(NSError**)error_; - - - - - -@property (nonatomic, strong) NSData* storeBookmarkData; - - - -//- (BOOL)validateStoreBookmarkData:(id*)value_ error:(NSError**)error_; - - - - - - -@end - -@interface _CDEConfiguration (CoreDataGeneratedAccessors) - -@end - -@interface _CDEConfiguration (CoreDataGeneratedPrimitiveAccessors) - - -- (NSData*)primitiveApplicationBundleBookmarkData; -- (void)setPrimitiveApplicationBundleBookmarkData:(NSData*)value; - - - - -- (NSDictionary*)primitiveAutosaveInformationByEntityName; -- (void)setPrimitiveAutosaveInformationByEntityName:(NSDictionary*)value; - - - - -- (NSNumber*)primitiveIsMacApplication; -- (void)setPrimitiveIsMacApplication:(NSNumber*)value; - -- (BOOL)primitiveIsMacApplicationValue; -- (void)setPrimitiveIsMacApplicationValue:(BOOL)value_; - - - - -- (NSData*)primitiveModelBookmarkData; -- (void)setPrimitiveModelBookmarkData:(NSData*)value; - - - - -- (NSData*)primitiveStoreBookmarkData; -- (void)setPrimitiveStoreBookmarkData:(NSData*)value; - - - - -@end diff --git a/Core Data Editor/Core Data Editor/_CDEConfiguration.m b/Core Data Editor/Core Data Editor/_CDEConfiguration.m deleted file mode 100644 index 5b67a16..0000000 --- a/Core Data Editor/Core Data Editor/_CDEConfiguration.m +++ /dev/null @@ -1,117 +0,0 @@ -// DO NOT EDIT. This file is machine-generated and constantly overwritten. -// Make changes to CDEConfiguration.m instead. - -#import "_CDEConfiguration.h" - -const struct CDEConfigurationAttributes CDEConfigurationAttributes = { - .applicationBundleBookmarkData = @"applicationBundleBookmarkData", - .autosaveInformationByEntityName = @"autosaveInformationByEntityName", - .isMacApplication = @"isMacApplication", - .modelBookmarkData = @"modelBookmarkData", - .storeBookmarkData = @"storeBookmarkData", -}; - -const struct CDEConfigurationRelationships CDEConfigurationRelationships = { -}; - -const struct CDEConfigurationFetchedProperties CDEConfigurationFetchedProperties = { -}; - -@implementation CDEConfigurationID -@end - -@implementation _CDEConfiguration - -+ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_ { - NSParameterAssert(moc_); - return [NSEntityDescription insertNewObjectForEntityForName:@"CDEConfiguration" inManagedObjectContext:moc_]; -} - -+ (NSString*)entityName { - return @"CDEConfiguration"; -} - -+ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_ { - NSParameterAssert(moc_); - return [NSEntityDescription entityForName:@"CDEConfiguration" inManagedObjectContext:moc_]; -} - -- (CDEConfigurationID*)objectID { - return (CDEConfigurationID*)[super objectID]; -} - -+ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString*)key { - NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; - - if ([key isEqualToString:@"isMacApplicationValue"]) { - NSSet *affectingKey = [NSSet setWithObject:@"isMacApplication"]; - keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; - return keyPaths; - } - - return keyPaths; -} - - - - -@dynamic applicationBundleBookmarkData; - - - - - - -@dynamic autosaveInformationByEntityName; - - - - - - -@dynamic isMacApplication; - - - -- (BOOL)isMacApplicationValue { - NSNumber *result = [self isMacApplication]; - return [result boolValue]; -} - -- (void)setIsMacApplicationValue:(BOOL)value_ { - [self setIsMacApplication:[NSNumber numberWithBool:value_]]; -} - -- (BOOL)primitiveIsMacApplicationValue { - NSNumber *result = [self primitiveIsMacApplication]; - return [result boolValue]; -} - -- (void)setPrimitiveIsMacApplicationValue:(BOOL)value_ { - [self setPrimitiveIsMacApplication:[NSNumber numberWithBool:value_]]; -} - - - - - -@dynamic modelBookmarkData; - - - - - - -@dynamic storeBookmarkData; - - - - - - - - - - - -@end