Cloudkit integration

main
Laurent 3 years ago
parent 76db659137
commit 7690ea7d8c
  1. 390
      Notes.xcodeproj/project.pbxproj
  2. 32
      Notes/AppDelegate.swift
  3. 4
      Notes/Info.plist
  4. 15
      Notes/Model/Note+CoreDataClass.swift
  5. 27
      Notes/Model/Note+CoreDataProperties.swift
  6. 48
      Notes/NoteViewController.swift
  7. 10
      Notes/Notes.entitlements
  8. 8
      Notes/Notes.xcdatamodeld/Notes.xcdatamodel/contents
  9. 2
      Notes/SceneDelegate.swift
  10. 30
      Notes/Storage/CoreDataStorage.swift
  11. 13
      Notes/Storage/Document.swift
  12. 116
      Notes/Storage/FileStorage.swift
  13. 44
      Notes/Storage/PreferencesStorage.swift
  14. 2
      Notes/ViewController.swift
  15. 4
      NotesTests/NotesTests.swift
  16. 4
      NotesUITests/NotesUITests.swift
  17. 4
      NotesUITests/NotesUITestsLaunchTests.swift
  18. 3
      README.md

@ -3,85 +3,92 @@
archiveVersion = 1;
classes = {
};
objectVersion = 55;
objectVersion = 56;
objects = {
/* Begin PBXBuildFile section */
C41A31C628C49B310019B951 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41A31C528C49B310019B951 /* AppDelegate.swift */; };
C41A31C828C49B310019B951 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41A31C728C49B310019B951 /* SceneDelegate.swift */; };
C41A31CA28C49B310019B951 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41A31C928C49B310019B951 /* ViewController.swift */; };
C41A31CD28C49B310019B951 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C41A31CB28C49B310019B951 /* Main.storyboard */; };
C41A31D028C49B310019B951 /* Notes.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = C41A31CE28C49B310019B951 /* Notes.xcdatamodeld */; };
C41A31D228C49B320019B951 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C41A31D128C49B320019B951 /* Assets.xcassets */; };
C41A31D528C49B320019B951 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C41A31D328C49B320019B951 /* LaunchScreen.storyboard */; };
C41A31E028C49B320019B951 /* NotesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41A31DF28C49B320019B951 /* NotesTests.swift */; };
C41A31EA28C49B320019B951 /* NotesUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41A31E928C49B320019B951 /* NotesUITests.swift */; };
C41A31EC28C49B320019B951 /* NotesUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41A31EB28C49B320019B951 /* NotesUITestsLaunchTests.swift */; };
C41A31F928C49DC80019B951 /* NoteViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41A31F828C49DC80019B951 /* NoteViewController.swift */; };
C41A31FB28C4D8040019B951 /* PreferencesStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41A31FA28C4D8040019B951 /* PreferencesStorage.swift */; };
C43417F428D4ADB10098C15A /* FileOperator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43417F328D4ADB10098C15A /* FileOperator.swift */; };
C43417F628D4ADDB0098C15A /* FileStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43417F528D4ADDB0098C15A /* FileStorage.swift */; };
C43417FA28D4B9370098C15A /* Document.swift in Sources */ = {isa = PBXBuildFile; fileRef = C43417F928D4B9370098C15A /* Document.swift */; };
C4EEE40728D89C46003DDC24 /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE40628D89C46003DDC24 /* UIViewController+Extensions.swift */; };
C4EEE41F28DB33D8003DDC24 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE41E28DB33D8003DDC24 /* AppDelegate.swift */; };
C4EEE42128DB33D8003DDC24 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE42028DB33D8003DDC24 /* SceneDelegate.swift */; };
C4EEE42328DB33D8003DDC24 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE42228DB33D8003DDC24 /* ViewController.swift */; };
C4EEE42628DB33D8003DDC24 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C4EEE42428DB33D8003DDC24 /* Main.storyboard */; };
C4EEE42928DB33D8003DDC24 /* Notes.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE42728DB33D8003DDC24 /* Notes.xcdatamodeld */; };
C4EEE42B28DB33D9003DDC24 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C4EEE42A28DB33D9003DDC24 /* Assets.xcassets */; };
C4EEE42E28DB33D9003DDC24 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C4EEE42C28DB33D9003DDC24 /* LaunchScreen.storyboard */; };
C4EEE43928DB33D9003DDC24 /* NotesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE43828DB33D9003DDC24 /* NotesTests.swift */; };
C4EEE44328DB33D9003DDC24 /* NotesUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE44228DB33D9003DDC24 /* NotesUITests.swift */; };
C4EEE44528DB33D9003DDC24 /* NotesUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE44428DB33D9003DDC24 /* NotesUITestsLaunchTests.swift */; };
C4EEE45328DB3423003DDC24 /* NoteViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE45128DB3422003DDC24 /* NoteViewController.swift */; };
C4EEE45428DB3423003DDC24 /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE45228DB3423003DDC24 /* UIViewController+Extensions.swift */; };
C4EEE46728DB3790003DDC24 /* FileOperator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE46528DB3790003DDC24 /* FileOperator.swift */; };
C4EEE46928DB3790003DDC24 /* FileStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE46628DB3790003DDC24 /* FileStorage.swift */; };
C4EEE46A28DB3790003DDC24 /* PreferencesStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE46428DB378F003DDC24 /* PreferencesStorage.swift */; };
C4EEE47628DB3938003DDC24 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C4EEE47528DB3938003DDC24 /* CoreData.framework */; };
C4EEE48128DB39F1003DDC24 /* Note+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE47F28DB39F1003DDC24 /* Note+CoreDataClass.swift */; };
C4EEE48228DB39F1003DDC24 /* Note+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE48028DB39F1003DDC24 /* Note+CoreDataProperties.swift */; };
C4EEE48428DB3B6B003DDC24 /* CoreDataStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EEE48328DB3B6B003DDC24 /* CoreDataStorage.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
C41A31DC28C49B320019B951 /* PBXContainerItemProxy */ = {
C4EEE43528DB33D9003DDC24 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C41A31BA28C49B310019B951 /* Project object */;
containerPortal = C4EEE41328DB33D8003DDC24 /* Project object */;
proxyType = 1;
remoteGlobalIDString = C41A31C128C49B310019B951;
remoteGlobalIDString = C4EEE41A28DB33D8003DDC24;
remoteInfo = Notes;
};
C41A31E628C49B320019B951 /* PBXContainerItemProxy */ = {
C4EEE43F28DB33D9003DDC24 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C41A31BA28C49B310019B951 /* Project object */;
containerPortal = C4EEE41328DB33D8003DDC24 /* Project object */;
proxyType = 1;
remoteGlobalIDString = C41A31C128C49B310019B951;
remoteGlobalIDString = C4EEE41A28DB33D8003DDC24;
remoteInfo = Notes;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
C41A31C228C49B310019B951 /* Notes.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Notes.app; sourceTree = BUILT_PRODUCTS_DIR; };
C41A31C528C49B310019B951 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
C41A31C728C49B310019B951 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
C41A31C928C49B310019B951 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
C41A31CC28C49B310019B951 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
C41A31CF28C49B310019B951 /* Notes.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Notes.xcdatamodel; sourceTree = "<group>"; };
C41A31D128C49B320019B951 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
C41A31D428C49B320019B951 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
C41A31D628C49B320019B951 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C41A31DB28C49B320019B951 /* NotesTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NotesTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
C41A31DF28C49B320019B951 /* NotesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesTests.swift; sourceTree = "<group>"; };
C41A31E528C49B320019B951 /* NotesUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NotesUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
C41A31E928C49B320019B951 /* NotesUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesUITests.swift; sourceTree = "<group>"; };
C41A31EB28C49B320019B951 /* NotesUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesUITestsLaunchTests.swift; sourceTree = "<group>"; };
C41A31F828C49DC80019B951 /* NoteViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoteViewController.swift; sourceTree = "<group>"; };
C41A31FA28C4D8040019B951 /* PreferencesStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesStorage.swift; sourceTree = "<group>"; };
C43417F128D4AACD0098C15A /* Notes.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Notes.entitlements; sourceTree = "<group>"; };
C43417F328D4ADB10098C15A /* FileOperator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileOperator.swift; sourceTree = "<group>"; };
C43417F528D4ADDB0098C15A /* FileStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileStorage.swift; sourceTree = "<group>"; };
C43417F928D4B9370098C15A /* Document.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Document.swift; sourceTree = "<group>"; };
C4EEE40628D89C46003DDC24 /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extensions.swift"; sourceTree = "<group>"; };
C4EEE41B28DB33D8003DDC24 /* Notes.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Notes.app; sourceTree = BUILT_PRODUCTS_DIR; };
C4EEE41E28DB33D8003DDC24 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
C4EEE42028DB33D8003DDC24 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
C4EEE42228DB33D8003DDC24 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
C4EEE42528DB33D8003DDC24 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
C4EEE42828DB33D8003DDC24 /* Notes.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Notes.xcdatamodel; sourceTree = "<group>"; };
C4EEE42A28DB33D9003DDC24 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
C4EEE42D28DB33D9003DDC24 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
C4EEE42F28DB33D9003DDC24 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C4EEE43428DB33D9003DDC24 /* NotesTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NotesTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
C4EEE43828DB33D9003DDC24 /* NotesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesTests.swift; sourceTree = "<group>"; };
C4EEE43E28DB33D9003DDC24 /* NotesUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NotesUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
C4EEE44228DB33D9003DDC24 /* NotesUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesUITests.swift; sourceTree = "<group>"; };
C4EEE44428DB33D9003DDC24 /* NotesUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesUITestsLaunchTests.swift; sourceTree = "<group>"; };
C4EEE45128DB3422003DDC24 /* NoteViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoteViewController.swift; sourceTree = "<group>"; };
C4EEE45228DB3423003DDC24 /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extensions.swift"; sourceTree = "<group>"; };
C4EEE45928DB358A003DDC24 /* Notes.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Notes.entitlements; sourceTree = "<group>"; };
C4EEE46428DB378F003DDC24 /* PreferencesStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesStorage.swift; sourceTree = "<group>"; };
C4EEE46528DB3790003DDC24 /* FileOperator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileOperator.swift; sourceTree = "<group>"; };
C4EEE46628DB3790003DDC24 /* FileStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileStorage.swift; sourceTree = "<group>"; };
C4EEE47528DB3938003DDC24 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
C4EEE47F28DB39F1003DDC24 /* Note+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Note+CoreDataClass.swift"; sourceTree = "<group>"; };
C4EEE48028DB39F1003DDC24 /* Note+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Note+CoreDataProperties.swift"; sourceTree = "<group>"; };
C4EEE48328DB3B6B003DDC24 /* CoreDataStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataStorage.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
C41A31BF28C49B310019B951 /* Frameworks */ = {
C4EEE41828DB33D8003DDC24 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C4EEE47628DB3938003DDC24 /* CoreData.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C41A31D828C49B320019B951 /* Frameworks */ = {
C4EEE43128DB33D9003DDC24 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
C41A31E228C49B320019B951 /* Frameworks */ = {
C4EEE43B28DB33D9003DDC24 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
@ -91,83 +98,102 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
C41A31B928C49B310019B951 = {
C4EEE41228DB33D8003DDC24 = {
isa = PBXGroup;
children = (
C41A31C428C49B310019B951 /* Notes */,
C41A31DE28C49B320019B951 /* NotesTests */,
C41A31E828C49B320019B951 /* NotesUITests */,
C41A31C328C49B310019B951 /* Products */,
C4EEE41D28DB33D8003DDC24 /* Notes */,
C4EEE43728DB33D9003DDC24 /* NotesTests */,
C4EEE44128DB33D9003DDC24 /* NotesUITests */,
C4EEE41C28DB33D8003DDC24 /* Products */,
C4EEE47428DB3938003DDC24 /* Frameworks */,
);
sourceTree = "<group>";
};
C41A31C328C49B310019B951 /* Products */ = {
C4EEE41C28DB33D8003DDC24 /* Products */ = {
isa = PBXGroup;
children = (
C41A31C228C49B310019B951 /* Notes.app */,
C41A31DB28C49B320019B951 /* NotesTests.xctest */,
C41A31E528C49B320019B951 /* NotesUITests.xctest */,
C4EEE41B28DB33D8003DDC24 /* Notes.app */,
C4EEE43428DB33D9003DDC24 /* NotesTests.xctest */,
C4EEE43E28DB33D9003DDC24 /* NotesUITests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
C41A31C428C49B310019B951 /* Notes */ = {
C4EEE41D28DB33D8003DDC24 /* Notes */ = {
isa = PBXGroup;
children = (
C43417F128D4AACD0098C15A /* Notes.entitlements */,
C41A31C528C49B310019B951 /* AppDelegate.swift */,
C41A31C728C49B310019B951 /* SceneDelegate.swift */,
C41A31C928C49B310019B951 /* ViewController.swift */,
C41A31F828C49DC80019B951 /* NoteViewController.swift */,
C4EEE40628D89C46003DDC24 /* UIViewController+Extensions.swift */,
C43417F228D4AD9C0098C15A /* Storage */,
C41A31CB28C49B310019B951 /* Main.storyboard */,
C41A31D128C49B320019B951 /* Assets.xcassets */,
C41A31D328C49B320019B951 /* LaunchScreen.storyboard */,
C41A31D628C49B320019B951 /* Info.plist */,
C41A31CE28C49B310019B951 /* Notes.xcdatamodeld */,
C4EEE45928DB358A003DDC24 /* Notes.entitlements */,
C4EEE41E28DB33D8003DDC24 /* AppDelegate.swift */,
C4EEE42028DB33D8003DDC24 /* SceneDelegate.swift */,
C4EEE42228DB33D8003DDC24 /* ViewController.swift */,
C4EEE45128DB3422003DDC24 /* NoteViewController.swift */,
C4EEE45228DB3423003DDC24 /* UIViewController+Extensions.swift */,
C4EEE46B28DB379B003DDC24 /* Storage */,
C4EEE46228DB3714003DDC24 /* Model */,
C4EEE42428DB33D8003DDC24 /* Main.storyboard */,
C4EEE42A28DB33D9003DDC24 /* Assets.xcassets */,
C4EEE42C28DB33D9003DDC24 /* LaunchScreen.storyboard */,
C4EEE42F28DB33D9003DDC24 /* Info.plist */,
C4EEE42728DB33D8003DDC24 /* Notes.xcdatamodeld */,
);
path = Notes;
sourceTree = "<group>";
};
C41A31DE28C49B320019B951 /* NotesTests */ = {
C4EEE43728DB33D9003DDC24 /* NotesTests */ = {
isa = PBXGroup;
children = (
C41A31DF28C49B320019B951 /* NotesTests.swift */,
C4EEE43828DB33D9003DDC24 /* NotesTests.swift */,
);
path = NotesTests;
sourceTree = "<group>";
};
C41A31E828C49B320019B951 /* NotesUITests */ = {
C4EEE44128DB33D9003DDC24 /* NotesUITests */ = {
isa = PBXGroup;
children = (
C41A31E928C49B320019B951 /* NotesUITests.swift */,
C41A31EB28C49B320019B951 /* NotesUITestsLaunchTests.swift */,
C4EEE44228DB33D9003DDC24 /* NotesUITests.swift */,
C4EEE44428DB33D9003DDC24 /* NotesUITestsLaunchTests.swift */,
);
path = NotesUITests;
sourceTree = "<group>";
};
C43417F228D4AD9C0098C15A /* Storage */ = {
C4EEE46228DB3714003DDC24 /* Model */ = {
isa = PBXGroup;
children = (
C41A31FA28C4D8040019B951 /* PreferencesStorage.swift */,
C43417F328D4ADB10098C15A /* FileOperator.swift */,
C43417F528D4ADDB0098C15A /* FileStorage.swift */,
C43417F928D4B9370098C15A /* Document.swift */,
C4EEE47F28DB39F1003DDC24 /* Note+CoreDataClass.swift */,
C4EEE48028DB39F1003DDC24 /* Note+CoreDataProperties.swift */,
);
path = Model;
sourceTree = "<group>";
};
C4EEE46B28DB379B003DDC24 /* Storage */ = {
isa = PBXGroup;
children = (
C4EEE46528DB3790003DDC24 /* FileOperator.swift */,
C4EEE46628DB3790003DDC24 /* FileStorage.swift */,
C4EEE46428DB378F003DDC24 /* PreferencesStorage.swift */,
C4EEE48328DB3B6B003DDC24 /* CoreDataStorage.swift */,
);
path = Storage;
sourceTree = "<group>";
};
C4EEE47428DB3938003DDC24 /* Frameworks */ = {
isa = PBXGroup;
children = (
C4EEE47528DB3938003DDC24 /* CoreData.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
C41A31C128C49B310019B951 /* Notes */ = {
C4EEE41A28DB33D8003DDC24 /* Notes */ = {
isa = PBXNativeTarget;
buildConfigurationList = C41A31EF28C49B320019B951 /* Build configuration list for PBXNativeTarget "Notes" */;
buildConfigurationList = C4EEE44828DB33D9003DDC24 /* Build configuration list for PBXNativeTarget "Notes" */;
buildPhases = (
C41A31BE28C49B310019B951 /* Sources */,
C41A31BF28C49B310019B951 /* Frameworks */,
C41A31C028C49B310019B951 /* Resources */,
C4EEE41728DB33D8003DDC24 /* Sources */,
C4EEE41828DB33D8003DDC24 /* Frameworks */,
C4EEE41928DB33D8003DDC24 /* Resources */,
);
buildRules = (
);
@ -175,107 +201,107 @@
);
name = Notes;
productName = Notes;
productReference = C41A31C228C49B310019B951 /* Notes.app */;
productReference = C4EEE41B28DB33D8003DDC24 /* Notes.app */;
productType = "com.apple.product-type.application";
};
C41A31DA28C49B320019B951 /* NotesTests */ = {
C4EEE43328DB33D9003DDC24 /* NotesTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = C41A31F228C49B320019B951 /* Build configuration list for PBXNativeTarget "NotesTests" */;
buildConfigurationList = C4EEE44B28DB33D9003DDC24 /* Build configuration list for PBXNativeTarget "NotesTests" */;
buildPhases = (
C41A31D728C49B320019B951 /* Sources */,
C41A31D828C49B320019B951 /* Frameworks */,
C41A31D928C49B320019B951 /* Resources */,
C4EEE43028DB33D9003DDC24 /* Sources */,
C4EEE43128DB33D9003DDC24 /* Frameworks */,
C4EEE43228DB33D9003DDC24 /* Resources */,
);
buildRules = (
);
dependencies = (
C41A31DD28C49B320019B951 /* PBXTargetDependency */,
C4EEE43628DB33D9003DDC24 /* PBXTargetDependency */,
);
name = NotesTests;
productName = NotesTests;
productReference = C41A31DB28C49B320019B951 /* NotesTests.xctest */;
productReference = C4EEE43428DB33D9003DDC24 /* NotesTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
C41A31E428C49B320019B951 /* NotesUITests */ = {
C4EEE43D28DB33D9003DDC24 /* NotesUITests */ = {
isa = PBXNativeTarget;
buildConfigurationList = C41A31F528C49B320019B951 /* Build configuration list for PBXNativeTarget "NotesUITests" */;
buildConfigurationList = C4EEE44E28DB33D9003DDC24 /* Build configuration list for PBXNativeTarget "NotesUITests" */;
buildPhases = (
C41A31E128C49B320019B951 /* Sources */,
C41A31E228C49B320019B951 /* Frameworks */,
C41A31E328C49B320019B951 /* Resources */,
C4EEE43A28DB33D9003DDC24 /* Sources */,
C4EEE43B28DB33D9003DDC24 /* Frameworks */,
C4EEE43C28DB33D9003DDC24 /* Resources */,
);
buildRules = (
);
dependencies = (
C41A31E728C49B320019B951 /* PBXTargetDependency */,
C4EEE44028DB33D9003DDC24 /* PBXTargetDependency */,
);
name = NotesUITests;
productName = NotesUITests;
productReference = C41A31E528C49B320019B951 /* NotesUITests.xctest */;
productReference = C4EEE43E28DB33D9003DDC24 /* NotesUITests.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
C41A31BA28C49B310019B951 /* Project object */ = {
C4EEE41328DB33D8003DDC24 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1340;
LastUpgradeCheck = 1340;
LastSwiftUpdateCheck = 1400;
LastUpgradeCheck = 1400;
TargetAttributes = {
C41A31C128C49B310019B951 = {
CreatedOnToolsVersion = 13.4.1;
C4EEE41A28DB33D8003DDC24 = {
CreatedOnToolsVersion = 14.0;
};
C41A31DA28C49B320019B951 = {
CreatedOnToolsVersion = 13.4.1;
TestTargetID = C41A31C128C49B310019B951;
C4EEE43328DB33D9003DDC24 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = C4EEE41A28DB33D8003DDC24;
};
C41A31E428C49B320019B951 = {
CreatedOnToolsVersion = 13.4.1;
TestTargetID = C41A31C128C49B310019B951;
C4EEE43D28DB33D9003DDC24 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = C4EEE41A28DB33D8003DDC24;
};
};
};
buildConfigurationList = C41A31BD28C49B310019B951 /* Build configuration list for PBXProject "Notes" */;
compatibilityVersion = "Xcode 13.0";
buildConfigurationList = C4EEE41628DB33D8003DDC24 /* Build configuration list for PBXProject "Notes" */;
compatibilityVersion = "Xcode 14.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = C41A31B928C49B310019B951;
productRefGroup = C41A31C328C49B310019B951 /* Products */;
mainGroup = C4EEE41228DB33D8003DDC24;
productRefGroup = C4EEE41C28DB33D8003DDC24 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
C41A31C128C49B310019B951 /* Notes */,
C41A31DA28C49B320019B951 /* NotesTests */,
C41A31E428C49B320019B951 /* NotesUITests */,
C4EEE41A28DB33D8003DDC24 /* Notes */,
C4EEE43328DB33D9003DDC24 /* NotesTests */,
C4EEE43D28DB33D9003DDC24 /* NotesUITests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
C41A31C028C49B310019B951 /* Resources */ = {
C4EEE41928DB33D8003DDC24 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C41A31D528C49B320019B951 /* LaunchScreen.storyboard in Resources */,
C41A31D228C49B320019B951 /* Assets.xcassets in Resources */,
C41A31CD28C49B310019B951 /* Main.storyboard in Resources */,
C4EEE42E28DB33D9003DDC24 /* LaunchScreen.storyboard in Resources */,
C4EEE42B28DB33D9003DDC24 /* Assets.xcassets in Resources */,
C4EEE42628DB33D8003DDC24 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C41A31D928C49B320019B951 /* Resources */ = {
C4EEE43228DB33D9003DDC24 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
C41A31E328C49B320019B951 /* Resources */ = {
C4EEE43C28DB33D9003DDC24 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
@ -285,68 +311,70 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
C41A31BE28C49B310019B951 /* Sources */ = {
C4EEE41728DB33D8003DDC24 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C41A31CA28C49B310019B951 /* ViewController.swift in Sources */,
C41A31C628C49B310019B951 /* AppDelegate.swift in Sources */,
C4EEE40728D89C46003DDC24 /* UIViewController+Extensions.swift in Sources */,
C41A31FB28C4D8040019B951 /* PreferencesStorage.swift in Sources */,
C41A31C828C49B310019B951 /* SceneDelegate.swift in Sources */,
C43417F428D4ADB10098C15A /* FileOperator.swift in Sources */,
C43417FA28D4B9370098C15A /* Document.swift in Sources */,
C43417F628D4ADDB0098C15A /* FileStorage.swift in Sources */,
C41A31F928C49DC80019B951 /* NoteViewController.swift in Sources */,
C41A31D028C49B310019B951 /* Notes.xcdatamodeld in Sources */,
C4EEE48428DB3B6B003DDC24 /* CoreDataStorage.swift in Sources */,
C4EEE48228DB39F1003DDC24 /* Note+CoreDataProperties.swift in Sources */,
C4EEE46A28DB3790003DDC24 /* PreferencesStorage.swift in Sources */,
C4EEE42328DB33D8003DDC24 /* ViewController.swift in Sources */,
C4EEE46928DB3790003DDC24 /* FileStorage.swift in Sources */,
C4EEE41F28DB33D8003DDC24 /* AppDelegate.swift in Sources */,
C4EEE42128DB33D8003DDC24 /* SceneDelegate.swift in Sources */,
C4EEE45328DB3423003DDC24 /* NoteViewController.swift in Sources */,
C4EEE46728DB3790003DDC24 /* FileOperator.swift in Sources */,
C4EEE48128DB39F1003DDC24 /* Note+CoreDataClass.swift in Sources */,
C4EEE45428DB3423003DDC24 /* UIViewController+Extensions.swift in Sources */,
C4EEE42928DB33D8003DDC24 /* Notes.xcdatamodeld in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C41A31D728C49B320019B951 /* Sources */ = {
C4EEE43028DB33D9003DDC24 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C41A31E028C49B320019B951 /* NotesTests.swift in Sources */,
C4EEE43928DB33D9003DDC24 /* NotesTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C41A31E128C49B320019B951 /* Sources */ = {
C4EEE43A28DB33D9003DDC24 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C41A31EC28C49B320019B951 /* NotesUITestsLaunchTests.swift in Sources */,
C41A31EA28C49B320019B951 /* NotesUITests.swift in Sources */,
C4EEE44528DB33D9003DDC24 /* NotesUITestsLaunchTests.swift in Sources */,
C4EEE44328DB33D9003DDC24 /* NotesUITests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
C41A31DD28C49B320019B951 /* PBXTargetDependency */ = {
C4EEE43628DB33D9003DDC24 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = C41A31C128C49B310019B951 /* Notes */;
targetProxy = C41A31DC28C49B320019B951 /* PBXContainerItemProxy */;
target = C4EEE41A28DB33D8003DDC24 /* Notes */;
targetProxy = C4EEE43528DB33D9003DDC24 /* PBXContainerItemProxy */;
};
C41A31E728C49B320019B951 /* PBXTargetDependency */ = {
C4EEE44028DB33D9003DDC24 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = C41A31C128C49B310019B951 /* Notes */;
targetProxy = C41A31E628C49B320019B951 /* PBXContainerItemProxy */;
target = C4EEE41A28DB33D8003DDC24 /* Notes */;
targetProxy = C4EEE43F28DB33D9003DDC24 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
C41A31CB28C49B310019B951 /* Main.storyboard */ = {
C4EEE42428DB33D8003DDC24 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
C41A31CC28C49B310019B951 /* Base */,
C4EEE42528DB33D8003DDC24 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
C41A31D328C49B320019B951 /* LaunchScreen.storyboard */ = {
C4EEE42C28DB33D9003DDC24 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
C41A31D428C49B320019B951 /* Base */,
C4EEE42D28DB33D9003DDC24 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
@ -354,13 +382,13 @@
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
C41A31ED28C49B320019B951 /* Debug */ = {
C4EEE44628DB33D9003DDC24 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
@ -414,13 +442,13 @@
};
name = Debug;
};
C41A31EE28C49B320019B951 /* Release */ = {
C4EEE44728DB33D9003DDC24 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
@ -468,12 +496,11 @@
};
name = Release;
};
C41A31F028C49B320019B951 /* Debug */ = {
C4EEE44928DB33D9003DDC24 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CODE_SIGN_ENTITLEMENTS = Notes/Notes.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
@ -483,7 +510,6 @@
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
@ -499,12 +525,11 @@
};
name = Debug;
};
C41A31F128C49B320019B951 /* Release */ = {
C4EEE44A28DB33D9003DDC24 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CODE_SIGN_ENTITLEMENTS = Notes/Notes.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
@ -514,7 +539,6 @@
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
@ -530,7 +554,7 @@
};
name = Release;
};
C41A31F328C49B320019B951 /* Debug */ = {
C4EEE44C28DB33D9003DDC24 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
@ -539,18 +563,18 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 526E96RFNP;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.staxriver.NotesTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Notes.app/Notes";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Notes.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Notes";
};
name = Debug;
};
C41A31F428C49B320019B951 /* Release */ = {
C4EEE44D28DB33D9003DDC24 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
@ -559,18 +583,18 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 526E96RFNP;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.staxriver.NotesTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Notes.app/Notes";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Notes.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Notes";
};
name = Release;
};
C41A31F628C49B320019B951 /* Debug */ = {
C4EEE44F28DB33D9003DDC24 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
@ -588,7 +612,7 @@
};
name = Debug;
};
C41A31F728C49B320019B951 /* Release */ = {
C4EEE45028DB33D9003DDC24 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
@ -609,38 +633,38 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
C41A31BD28C49B310019B951 /* Build configuration list for PBXProject "Notes" */ = {
C4EEE41628DB33D8003DDC24 /* Build configuration list for PBXProject "Notes" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C41A31ED28C49B320019B951 /* Debug */,
C41A31EE28C49B320019B951 /* Release */,
C4EEE44628DB33D9003DDC24 /* Debug */,
C4EEE44728DB33D9003DDC24 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C41A31EF28C49B320019B951 /* Build configuration list for PBXNativeTarget "Notes" */ = {
C4EEE44828DB33D9003DDC24 /* Build configuration list for PBXNativeTarget "Notes" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C41A31F028C49B320019B951 /* Debug */,
C41A31F128C49B320019B951 /* Release */,
C4EEE44928DB33D9003DDC24 /* Debug */,
C4EEE44A28DB33D9003DDC24 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C41A31F228C49B320019B951 /* Build configuration list for PBXNativeTarget "NotesTests" */ = {
C4EEE44B28DB33D9003DDC24 /* Build configuration list for PBXNativeTarget "NotesTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C41A31F328C49B320019B951 /* Debug */,
C41A31F428C49B320019B951 /* Release */,
C4EEE44C28DB33D9003DDC24 /* Debug */,
C4EEE44D28DB33D9003DDC24 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C41A31F528C49B320019B951 /* Build configuration list for PBXNativeTarget "NotesUITests" */ = {
C4EEE44E28DB33D9003DDC24 /* Build configuration list for PBXNativeTarget "NotesUITests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C41A31F628C49B320019B951 /* Debug */,
C41A31F728C49B320019B951 /* Release */,
C4EEE44F28DB33D9003DDC24 /* Debug */,
C4EEE45028DB33D9003DDC24 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
@ -648,17 +672,17 @@
/* End XCConfigurationList section */
/* Begin XCVersionGroup section */
C41A31CE28C49B310019B951 /* Notes.xcdatamodeld */ = {
C4EEE42728DB33D8003DDC24 /* Notes.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
C41A31CF28C49B310019B951 /* Notes.xcdatamodel */,
C4EEE42828DB33D8003DDC24 /* Notes.xcdatamodel */,
);
currentVersion = C41A31CF28C49B310019B951 /* Notes.xcdatamodel */;
currentVersion = C4EEE42828DB33D8003DDC24 /* Notes.xcdatamodel */;
path = Notes.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};
/* End XCVersionGroup section */
};
rootObject = C41A31BA28C49B310019B951 /* Project object */;
rootObject = C4EEE41328DB33D8003DDC24 /* Project object */;
}

@ -2,7 +2,7 @@
// AppDelegate.swift
// Notes
//
// Created by Laurent Morvillier on 04/09/2022.
// Created by Laurent Morvillier on 21/09/2022.
//
import UIKit
@ -11,23 +11,20 @@ import CoreData
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// let fn = "main"
// if let content = PreferencesStorage.main.getContent(filename: fn) {
// FileStorage.main.requestStorage(filename: "main.txt", content: content)
// }
static var shared: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// for fontFamilyName in UIFont.familyNames {
// print("family: \(fontFamilyName)\n")
//
// for fontName in UIFont.fontNames(forFamilyName: fontFamilyName) {
// print("font: \(fontName)")
// }
// }
if let content = PreferencesStorage.main.getContent(filename: "main.txt") {
let note = Note(context: AppDelegate.viewContext)
note.content = content
AppDelegate.shared.saveContext()
print("default note created")
}
// Override point for customization after application launch.
return true
}
@ -76,7 +73,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// MARK: - Core Data Saving support
static var viewContext: NSManagedObjectContext {
return self.shared.persistentContainer.viewContext
}
func saveContext () {
print("save context...")
let context = persistentContainer.viewContext
if context.hasChanges {
do {

@ -21,5 +21,9 @@
</array>
</dict>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
</dict>
</plist>

@ -0,0 +1,15 @@
//
// Note+CoreDataClass.swift
// Notes
//
// Created by Laurent Morvillier on 21/09/2022.
//
//
import Foundation
import CoreData
public class Note: NSManagedObject {
}

@ -0,0 +1,27 @@
//
// Note+CoreDataProperties.swift
// Notes
//
// Created by Laurent Morvillier on 21/09/2022.
//
//
import Foundation
import CoreData
extension Note {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Note> {
return NSFetchRequest<Note>(entityName: "Note")
}
@NSManaged public var content: String?
@NSManaged public var title: String?
@NSManaged public var lastEditDate: Date?
}
extension Note : Identifiable {
}

@ -10,7 +10,7 @@ import UIKit
class NoteViewController : UIViewController, UITextViewDelegate {
var filename: String = "main.txt"
var note: Note? = nil
@IBOutlet weak var textView: UITextView!
@ -27,11 +27,7 @@ class NoteViewController : UIViewController, UITextViewDelegate {
let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addHandler))
self.navigationItem.rightBarButtonItems = [addButton, shareButton]
do {
self.textView.text = try FileStorage.main.getContent(filename: self.filename)
} catch {
self.showAlert(message: error.localizedDescription, title: "Error :(")
}
self._loadLastNote()
self.textView.font = UIFont.systemFont(ofSize: 18.0, weight: .regular)
self.textView.delegate = self
@ -39,6 +35,12 @@ class NoteViewController : UIViewController, UITextViewDelegate {
self._updateLastEdit()
/// Store notifications
NotificationCenter.default.addObserver(self, selector: #selector(self._storeRemoteChange(notification:)), name: .NSPersistentStoreCoordinatorStoresDidChange, object: nil)
/// Keyboard notifications
NotificationCenter.default.addObserver(
self,
selector: #selector(keyboardDidShow(notification:)),
@ -55,14 +57,44 @@ class NoteViewController : UIViewController, UITextViewDelegate {
}
fileprivate func _loadLastNote() {
let request = Note.fetchRequest()
request.sortDescriptors = [NSSortDescriptor(key: "lastEditDate", ascending: false)]
do {
self.note = try AppDelegate.viewContext.fetch(request).first
self.textView.text = self.note?.content
} catch {
print("Fetch error = \(error)")
}
}
@objc fileprivate func _storeRemoteChange(notification: Notification) {
print("_storeRemoteChange...")
self._loadLastNote()
}
func textViewDidChange(_ textView: UITextView) {
FileStorage.main.requestStorage(filename: self.filename, content: textView.text)
PreferencesStorage.main.requestStorage(filename: "main.txt", content: textView.text)
let note: Note
if let n = self.note {
note = n
} else {
note = Note(context: AppDelegate.viewContext)
self.note = note
}
CoreDataStorage.main.requestStorage(note: note, content: textView.text)
self._updateLastEdit()
}
fileprivate func _updateLastEdit() {
if let date = try? FileStorage.main.lastEditDate(filename: self.filename) {
if let date = self.note?.lastEditDate {
let formattedDate: String = date.formatted()
self._lastEditLabel?.text = "last edit: \(formattedDate)"
}

@ -2,13 +2,15 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.icloud-container-identifiers</key>
<array/>
<array>
<string>iCloud.com.staxriver.Note</string>
</array>
<key>com.apple.developer.icloud-services</key>
<array>
<string>CloudDocuments</string>
<string>CloudKit</string>
</array>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<array/>
</dict>
</plist>

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="1" systemVersion="11A491" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="true" userDefinedModelVersionIdentifier="">
<elements/>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21279" systemVersion="21G83" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="YES" userDefinedModelVersionIdentifier="">
<entity name="Note" representedClassName=".Note" syncable="YES">
<attribute name="content" optional="YES" attributeType="String"/>
<attribute name="lastEditDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="title" optional="YES" attributeType="String"/>
</entity>
</model>

@ -2,7 +2,7 @@
// SceneDelegate.swift
// Notes
//
// Created by Laurent Morvillier on 04/09/2022.
// Created by Laurent Morvillier on 21/09/2022.
//
import UIKit

@ -0,0 +1,30 @@
//
// CoreDataStorage.swift
// Notes
//
// Created by Laurent Morvillier on 21/09/2022.
//
import Foundation
class CoreDataStorage {
static var main: CoreDataStorage = CoreDataStorage()
fileprivate var _timer: Timer? = nil
func requestStorage(note: Note, content: String) {
note.content = content
note.lastEditDate = Date()
self._timer?.invalidate()
self._timer = Timer.scheduledTimer(timeInterval: idleTimeBeforeSaving, target: self, selector: #selector(self._storageRequested), userInfo: nil, repeats: false)
}
@objc fileprivate func _storageRequested() {
AppDelegate.shared.saveContext()
}
}

@ -1,13 +0,0 @@
//
// Document.swift
// Notes
//
// Created by Laurent Morvillier on 16/09/2022.
//
import Foundation
import UIKit
class Document : UIDocument {
}

@ -15,6 +15,14 @@ struct StorageRequest {
let idleTimeBeforeSaving = 2.0
fileprivate extension NSMetadataItem {
var url: URL? {
return self.value(forAttribute: NSMetadataItemURLKey) as? URL
}
}
/// Should we have a way to go from local to iCloud?
/// https://stackoverflow.com/questions/33886846/best-way-to-use-icloud-documents-storage
/// Should we store the files locally whatever the iCloud choice is?
@ -22,21 +30,32 @@ class FileStorage : FileOperator {
static var main: FileStorage = FileStorage()
fileprivate var _containerURL: URL?
fileprivate var _cloudContainerURL: URL?
fileprivate var _cloudStorageDetermined: Bool = false
fileprivate let containerTeamId = "notes"
fileprivate let containerIdentifier = "notes"
fileprivate var _timer: Timer? = nil
fileprivate var _downloadTimer: Timer? = nil
fileprivate var _downloads: [NSMetadataItem] = []
fileprivate var _storageRequests: [String : String] = [:]
init() {
let uit = FileManager.default.ubiquityIdentityToken
print("ubiquityIdentityToken = \(String(describing: uit))")
DispatchQueue.global(qos: .userInteractive).async {
self._containerURL = FileManager.default.url(forUbiquityContainerIdentifier: self.containerIdentifier)
self._cloudContainerURL = FileManager.default.url(forUbiquityContainerIdentifier: nil)
self._cloudStorageDetermined = true
print("Cloud container URL is : \(String(describing: self._containerURL?.absoluteString))")
print("Cloud container URL is : \(String(describing: self._cloudContainerURL?.absoluteString))")
// self._makeLocalCopyIfNecessary()
}
}
@ -45,6 +64,87 @@ class FileStorage : FileOperator {
return documentDirectory
}
fileprivate func _makeLocalCopyIfNecessary() {
// if the local dir is not empty, do nothing
if let docDir = try? self._directoryURL(), let files = try? FileManager.default.contentsOfDirectory(atPath: docDir.absoluteString), files.count > 0 {
return
}
guard let _ = self._cloudContainerURL else {
return
}
NotificationCenter.default.addObserver(self, selector: #selector(metaDataQueryNotified(notification:)), name: NSNotification.Name.NSMetadataQueryDidFinishGathering, object: nil)
let query = NSMetadataQuery()
query.searchScopes = [NSMetadataQueryUbiquitousDocumentsScope]
query.start()
}
@objc func metaDataQueryNotified(notification: Notification) {
guard let query = notification.object as? NSMetadataQuery else {
print("object = \(notification.object ?? "")")
return
}
for case let item as NSMetadataItem in query.results {
if let url = item.value(forAttribute: NSMetadataItemURLKey) as? URL {
self._downloadItem(item, url: url)
} else {
print("item has no URL")
}
}
}
fileprivate func _downloadItem(_ item: NSMetadataItem, url: URL) {
do {
try FileManager.default.startDownloadingUbiquitousItem(at: url)
self._startStatusTimer(item: item)
} catch {
print("error = \(error)")
}
}
fileprivate func _startStatusTimer(item: NSMetadataItem) {
self._downloads.append(item)
if self._downloadTimer == nil {
self._downloadTimer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(self._verifyDownloadStatus), userInfo: nil, repeats: false)
}
}
@objc fileprivate func _verifyDownloadStatus() {
let downloads = Array(self._downloads)
for item in downloads {
if item.value(forAttribute: NSMetadataUbiquitousItemDownloadingStatusKey) as? String == NSMetadataUbiquitousItemDownloadingStatusCurrent {
self._makeLocalCopy(item: item)
self._downloads.removeAll(where: { $0.url == item.url })
}
}
}
fileprivate func _makeLocalCopy(item: NSMetadataItem) {
guard let fileURL = item.url, let docURL = try? self._directoryURL() else {
return
}
do {
try FileManager.default.copyItem(at: fileURL, to: docURL)
} catch {
print("error: \(error)") // TODO
}
}
// MARK: - FileOperator
func requestStorage(filename: String, content: String) {
@ -90,12 +190,18 @@ class FileStorage : FileOperator {
}
fileprivate func _copyToCloudContainerIfNecessary(fileURL: URL, filename: String) throws {
guard let containerURL = self._containerURL else {
guard let containerURL = self._cloudContainerURL else {
print("cloud container is nil, stays local")
return
}
let cloudURL = containerURL.appending(path: filename)
print("cloud copy to: \(cloudURL)...")
// if FileManager.default.fileExists(atPath: cloudURL.absoluteString) {
// try FileManager.default.removeItem(at: cloudURL)
// }
try FileManager.default.copyItem(at: fileURL, to: cloudURL)
print("cloud copy to: \(cloudURL)")
}
deinit {

@ -7,25 +7,25 @@
import Foundation
//class PreferencesStorage : FileOperator {
//
// static var main = PreferencesStorage()
//
// func requestStorage(filename: String, content: String) {
// UserDefaults.standard.set(content, forKey: filename)
// PreferencesStorage._fileChanged(filename: filename)
// }
//
// fileprivate static func _fileChanged(filename: String) {
// UserDefaults.standard.set(Date(), forKey: filename + "_date")
// }
//
// func getContent(filename: String) -> String? {
// return UserDefaults.standard.object(forKey: filename) as? String
// }
//
// func lastEditDate(filename: String) -> Date? {
// return UserDefaults.standard.object(forKey: filename + "_date") as? Date
// }
//
//}
class PreferencesStorage : FileOperator {
static var main = PreferencesStorage()
func requestStorage(filename: String, content: String) {
UserDefaults.standard.set(content, forKey: filename)
PreferencesStorage._fileChanged(filename: filename)
}
fileprivate static func _fileChanged(filename: String) {
UserDefaults.standard.set(Date(), forKey: filename + "_date")
}
func getContent(filename: String) -> String? {
return UserDefaults.standard.object(forKey: filename) as? String
}
func lastEditDate(filename: String) -> Date? {
return UserDefaults.standard.object(forKey: filename + "_date") as? Date
}
}

@ -2,7 +2,7 @@
// ViewController.swift
// Notes
//
// Created by Laurent Morvillier on 04/09/2022.
// Created by Laurent Morvillier on 21/09/2022.
//
import UIKit

@ -2,13 +2,13 @@
// NotesTests.swift
// NotesTests
//
// Created by Laurent Morvillier on 04/09/2022.
// Created by Laurent Morvillier on 21/09/2022.
//
import XCTest
@testable import Notes
class NotesTests: XCTestCase {
final class NotesTests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.

@ -2,12 +2,12 @@
// NotesUITests.swift
// NotesUITests
//
// Created by Laurent Morvillier on 04/09/2022.
// Created by Laurent Morvillier on 21/09/2022.
//
import XCTest
class NotesUITests: XCTestCase {
final class NotesUITests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.

@ -2,12 +2,12 @@
// NotesUITestsLaunchTests.swift
// NotesUITests
//
// Created by Laurent Morvillier on 04/09/2022.
// Created by Laurent Morvillier on 21/09/2022.
//
import XCTest
class NotesUITestsLaunchTests: XCTestCase {
final class NotesUITestsLaunchTests: XCTestCase {
override class var runsForEachTargetApplicationUIConfiguration: Bool {
true

@ -1,3 +0,0 @@
# notes
application iOS de notes
Loading…
Cancel
Save