diff --git a/.gitignore b/.gitignore index d436556e4..789967a58 100644 --- a/.gitignore +++ b/.gitignore @@ -68,6 +68,7 @@ xcuserdata/ *.moved-aside *.xccheckout *.xcscmblueprint +Key.plist ## Obj-C/Swift specific *.hmap diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 000000000..dd5334923 --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,9 @@ +disabled_rules: +- trailing_whitespace + +excluded: +- Pods +- Diary/App/AppDelegate.swift +- Diary/App/SceneDelegate.swift +- Diary/Model/Diary+CoreDataClass.swift +- Diary/Model/Diary+CoreDataProperties.swift diff --git a/Diary.xcodeproj/project.pbxproj b/Diary.xcodeproj/project.pbxproj index da144935d..5549f4391 100644 --- a/Diary.xcodeproj/project.pbxproj +++ b/Diary.xcodeproj/project.pbxproj @@ -7,25 +7,70 @@ objects = { /* Begin PBXBuildFile section */ + 459D493A878338290A3E0AEF /* Pods_Diary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDF8EB908CAD9D062C72898B /* Pods_Diary.framework */; }; + 632F74F02AB14D2C003E1B97 /* NetworkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 632F74EF2AB14D2C003E1B97 /* NetworkManager.swift */; }; + 632F74F22AB14D8D003E1B97 /* WeatherResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 632F74F12AB14D8D003E1B97 /* WeatherResult.swift */; }; + 632F74F42AB14DBC003E1B97 /* APIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 632F74F32AB14DBC003E1B97 /* APIError.swift */; }; + 63BB62822A9F109400524DCB /* DecodingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63BB62812A9F109400524DCB /* DecodingManager.swift */; }; + 63BB62B22AA181BE00524DCB /* Diary+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63BB62B02AA181BE00524DCB /* Diary+CoreDataClass.swift */; }; + 63BB62B32AA181BE00524DCB /* Diary+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63BB62B12AA181BE00524DCB /* Diary+CoreDataProperties.swift */; }; + 63BB62B52AA182AA00524DCB /* CoreDataManagerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63BB62B42AA182AA00524DCB /* CoreDataManagerProtocol.swift */; }; + 63E527352A9D7EBF0000FBA6 /* .swiftlint.yml in Resources */ = {isa = PBXBuildFile; fileRef = 63E527342A9D7EBF0000FBA6 /* .swiftlint.yml */; }; + 63E527372A9D87660000FBA6 /* DiaryListTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63E527362A9D87660000FBA6 /* DiaryListTableViewCell.swift */; }; + 63E527392A9D97160000FBA6 /* DiaryDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63E527382A9D97160000FBA6 /* DiaryDetailViewController.swift */; }; + BA6463162ABC6DDE0080E80D /* DiaryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA6463152ABC6DDE0080E80D /* DiaryManager.swift */; }; + BABBDAE52A9F13A200D8D50B /* DecodingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BABBDAE42A9F13A200D8D50B /* DecodingError.swift */; }; + BABBDB342AA6D05A00D8D50B /* ShareDisplayable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BABBDB332AA6D05A00D8D50B /* ShareDisplayable.swift */; }; + BABBDB362AAD904100D8D50B /* CoreDataError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BABBDB352AAD904100D8D50B /* CoreDataError.swift */; }; + BAECB2CF2AB15742006B4A46 /* Key.plist in Resources */ = {isa = PBXBuildFile; fileRef = BAECB2CE2AB15742006B4A46 /* Key.plist */; }; + BAECB2D12AB157CB006B4A46 /* NetworkConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAECB2D02AB157CB006B4A46 /* NetworkConfiguration.swift */; }; + BAECB2D92AB18611006B4A46 /* DiaryV2.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = BAECB2D82AB18611006B4A46 /* DiaryV2.xcmappingmodel */; }; + BAECB2DD2AB187D6006B4A46 /* ImageCachingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAECB2DC2AB187D6006B4A46 /* ImageCachingManager.swift */; }; + BAECB2E12AB568A0006B4A46 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BAECB2E32AB568A0006B4A46 /* Localizable.strings */; }; + BAECB2E82AB72869006B4A46 /* AlertBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAECB2E72AB72869006B4A46 /* AlertBuilder.swift */; }; C739AE25284DF28600741E8F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE24284DF28600741E8F /* AppDelegate.swift */; }; C739AE27284DF28600741E8F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE26284DF28600741E8F /* SceneDelegate.swift */; }; - C739AE29284DF28600741E8F /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE28284DF28600741E8F /* ViewController.swift */; }; - C739AE2C284DF28600741E8F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C739AE2A284DF28600741E8F /* Main.storyboard */; }; + C739AE29284DF28600741E8F /* DiaryListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE28284DF28600741E8F /* DiaryListViewController.swift */; }; C739AE2F284DF28600741E8F /* Diary.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = C739AE2D284DF28600741E8F /* Diary.xcdatamodeld */; }; C739AE31284DF28600741E8F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C739AE30284DF28600741E8F /* Assets.xcassets */; }; C739AE34284DF28600741E8F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C739AE32284DF28600741E8F /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 632F74EF2AB14D2C003E1B97 /* NetworkManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkManager.swift; sourceTree = ""; }; + 632F74F12AB14D8D003E1B97 /* WeatherResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeatherResult.swift; sourceTree = ""; }; + 632F74F32AB14DBC003E1B97 /* APIError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIError.swift; sourceTree = ""; }; + 632F74F72AB17E05003E1B97 /* Diary V2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Diary V2.xcdatamodel"; sourceTree = ""; }; + 63BB62812A9F109400524DCB /* DecodingManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecodingManager.swift; sourceTree = ""; }; + 63BB62B02AA181BE00524DCB /* Diary+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "Diary+CoreDataClass.swift"; path = "Diary/Model/CoreData/Diary+CoreDataClass.swift"; sourceTree = SOURCE_ROOT; }; + 63BB62B12AA181BE00524DCB /* Diary+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "Diary+CoreDataProperties.swift"; path = "Diary/Model/CoreData/Diary+CoreDataProperties.swift"; sourceTree = SOURCE_ROOT; }; + 63BB62B42AA182AA00524DCB /* CoreDataManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManagerProtocol.swift; sourceTree = ""; }; + 63E527342A9D7EBF0000FBA6 /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = ""; }; + 63E527362A9D87660000FBA6 /* DiaryListTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryListTableViewCell.swift; sourceTree = ""; }; + 63E527382A9D97160000FBA6 /* DiaryDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryDetailViewController.swift; sourceTree = ""; }; + 7B86D20E06F2B506DECF94F6 /* Pods-Diary.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Diary.release.xcconfig"; path = "Target Support Files/Pods-Diary/Pods-Diary.release.xcconfig"; sourceTree = ""; }; + BA6463152ABC6DDE0080E80D /* DiaryManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryManager.swift; sourceTree = ""; }; + BABBDAE42A9F13A200D8D50B /* DecodingError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecodingError.swift; sourceTree = ""; }; + BABBDB332AA6D05A00D8D50B /* ShareDisplayable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareDisplayable.swift; sourceTree = ""; }; + BABBDB352AAD904100D8D50B /* CoreDataError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataError.swift; sourceTree = ""; }; + BAECB2CE2AB15742006B4A46 /* Key.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Key.plist; sourceTree = ""; }; + BAECB2D02AB157CB006B4A46 /* NetworkConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkConfiguration.swift; sourceTree = ""; }; + BAECB2D82AB18611006B4A46 /* DiaryV2.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = DiaryV2.xcmappingmodel; sourceTree = ""; }; + BAECB2DC2AB187D6006B4A46 /* ImageCachingManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCachingManager.swift; sourceTree = ""; }; + BAECB2E22AB568A0006B4A46 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + BAECB2E42AB568D2006B4A46 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/LaunchScreen.strings; sourceTree = ""; }; + BAECB2E52AB568D2006B4A46 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = ""; }; + BAECB2E72AB72869006B4A46 /* AlertBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertBuilder.swift; sourceTree = ""; }; C739AE21284DF28600741E8F /* Diary.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Diary.app; sourceTree = BUILT_PRODUCTS_DIR; }; C739AE24284DF28600741E8F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C739AE26284DF28600741E8F /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; - C739AE28284DF28600741E8F /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - C739AE2B284DF28600741E8F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + C739AE28284DF28600741E8F /* DiaryListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryListViewController.swift; sourceTree = ""; }; C739AE2E284DF28600741E8F /* Diary.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Diary.xcdatamodel; sourceTree = ""; }; C739AE30284DF28600741E8F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; C739AE33284DF28600741E8F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; C739AE35284DF28600741E8F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D2A4A06DD84A8CE69E772DD0 /* Pods-Diary.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Diary.debug.xcconfig"; path = "Target Support Files/Pods-Diary/Pods-Diary.debug.xcconfig"; sourceTree = ""; }; + EDF8EB908CAD9D062C72898B /* Pods_Diary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Diary.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -33,17 +78,139 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 459D493A878338290A3E0AEF /* Pods_Diary.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 26661DE0A3935A6B3B8FED0D /* Pods */ = { + isa = PBXGroup; + children = ( + D2A4A06DD84A8CE69E772DD0 /* Pods-Diary.debug.xcconfig */, + 7B86D20E06F2B506DECF94F6 /* Pods-Diary.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 524E42FF436814999DB2C64E /* Frameworks */ = { + isa = PBXGroup; + children = ( + EDF8EB908CAD9D062C72898B /* Pods_Diary.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 632F74EE2AB14CF3003E1B97 /* Network */ = { + isa = PBXGroup; + children = ( + 632F74EF2AB14D2C003E1B97 /* NetworkManager.swift */, + BAECB2D02AB157CB006B4A46 /* NetworkConfiguration.swift */, + ); + path = Network; + sourceTree = ""; + }; + 636B19AA2AA6C5C200B5242D /* Protocol */ = { + isa = PBXGroup; + children = ( + BABBDB332AA6D05A00D8D50B /* ShareDisplayable.swift */, + ); + path = Protocol; + sourceTree = ""; + }; + 63BB62B62AA185E700524DCB /* CoreData */ = { + isa = PBXGroup; + children = ( + 63BB62B02AA181BE00524DCB /* Diary+CoreDataClass.swift */, + 63BB62B12AA181BE00524DCB /* Diary+CoreDataProperties.swift */, + 63BB62B42AA182AA00524DCB /* CoreDataManagerProtocol.swift */, + BA6463152ABC6DDE0080E80D /* DiaryManager.swift */, + ); + path = CoreData; + sourceTree = ""; + }; + 63E5273C2A9ECD5A0000FBA6 /* App */ = { + isa = PBXGroup; + children = ( + C739AE24284DF28600741E8F /* AppDelegate.swift */, + C739AE26284DF28600741E8F /* SceneDelegate.swift */, + ); + path = App; + sourceTree = ""; + }; + 63E5273D2A9ECD660000FBA6 /* Model */ = { + isa = PBXGroup; + children = ( + BAECB2DA2AB1877C006B4A46 /* DTO */, + 63BB62B62AA185E700524DCB /* CoreData */, + BAECB2DE2AB18A17006B4A46 /* ImageCache */, + ); + path = Model; + sourceTree = ""; + }; + 63E5273F2A9ECDA90000FBA6 /* Controller */ = { + isa = PBXGroup; + children = ( + C739AE28284DF28600741E8F /* DiaryListViewController.swift */, + 63E527382A9D97160000FBA6 /* DiaryDetailViewController.swift */, + ); + path = Controller; + sourceTree = ""; + }; + 63E527402A9ECDB70000FBA6 /* View */ = { + isa = PBXGroup; + children = ( + C739AE32284DF28600741E8F /* LaunchScreen.storyboard */, + 63E527362A9D87660000FBA6 /* DiaryListTableViewCell.swift */, + ); + path = View; + sourceTree = ""; + }; + BABBDAE62A9F13AE00D8D50B /* Error */ = { + isa = PBXGroup; + children = ( + BABBDAE42A9F13A200D8D50B /* DecodingError.swift */, + BABBDB352AAD904100D8D50B /* CoreDataError.swift */, + 632F74F32AB14DBC003E1B97 /* APIError.swift */, + ); + path = Error; + sourceTree = ""; + }; + BAECB2DA2AB1877C006B4A46 /* DTO */ = { + isa = PBXGroup; + children = ( + 632F74F12AB14D8D003E1B97 /* WeatherResult.swift */, + 63BB62812A9F109400524DCB /* DecodingManager.swift */, + ); + path = DTO; + sourceTree = ""; + }; + BAECB2DE2AB18A17006B4A46 /* ImageCache */ = { + isa = PBXGroup; + children = ( + BAECB2DC2AB187D6006B4A46 /* ImageCachingManager.swift */, + ); + path = ImageCache; + sourceTree = ""; + }; + BAECB2E62AB72855006B4A46 /* Builder */ = { + isa = PBXGroup; + children = ( + BAECB2E72AB72869006B4A46 /* AlertBuilder.swift */, + ); + path = Builder; + sourceTree = ""; + }; C739AE18284DF28600741E8F = { isa = PBXGroup; children = ( + BAECB2E32AB568A0006B4A46 /* Localizable.strings */, + 63E527342A9D7EBF0000FBA6 /* .swiftlint.yml */, C739AE23284DF28600741E8F /* Diary */, C739AE22284DF28600741E8F /* Products */, + 26661DE0A3935A6B3B8FED0D /* Pods */, + 524E42FF436814999DB2C64E /* Frameworks */, ); sourceTree = ""; }; @@ -58,14 +225,19 @@ C739AE23284DF28600741E8F /* Diary */ = { isa = PBXGroup; children = ( - C739AE24284DF28600741E8F /* AppDelegate.swift */, - C739AE26284DF28600741E8F /* SceneDelegate.swift */, - C739AE28284DF28600741E8F /* ViewController.swift */, - C739AE2A284DF28600741E8F /* Main.storyboard */, + BAECB2E62AB72855006B4A46 /* Builder */, + 632F74EE2AB14CF3003E1B97 /* Network */, + 636B19AA2AA6C5C200B5242D /* Protocol */, + 63E5273D2A9ECD660000FBA6 /* Model */, + BABBDAE62A9F13AE00D8D50B /* Error */, + 63E5273F2A9ECDA90000FBA6 /* Controller */, + 63E527402A9ECDB70000FBA6 /* View */, + 63E5273C2A9ECD5A0000FBA6 /* App */, C739AE30284DF28600741E8F /* Assets.xcassets */, - C739AE32284DF28600741E8F /* LaunchScreen.storyboard */, C739AE35284DF28600741E8F /* Info.plist */, + BAECB2CE2AB15742006B4A46 /* Key.plist */, C739AE2D284DF28600741E8F /* Diary.xcdatamodeld */, + BAECB2D82AB18611006B4A46 /* DiaryV2.xcmappingmodel */, ); path = Diary; sourceTree = ""; @@ -77,9 +249,11 @@ isa = PBXNativeTarget; buildConfigurationList = C739AE38284DF28600741E8F /* Build configuration list for PBXNativeTarget "Diary" */; buildPhases = ( + 0395747DD529D532F280B3A4 /* [CP] Check Pods Manifest.lock */, C739AE1D284DF28600741E8F /* Sources */, C739AE1E284DF28600741E8F /* Frameworks */, C739AE1F284DF28600741E8F /* Resources */, + BA1A55DB2A9C98560012C89D /* ShellScript */, ); buildRules = ( ); @@ -112,6 +286,7 @@ knownRegions = ( en, Base, + ko, ); mainGroup = C739AE18284DF28600741E8F; productRefGroup = C739AE22284DF28600741E8F /* Products */; @@ -128,41 +303,105 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + BAECB2E12AB568A0006B4A46 /* Localizable.strings in Resources */, + BAECB2CF2AB15742006B4A46 /* Key.plist in Resources */, + 63E527352A9D7EBF0000FBA6 /* .swiftlint.yml in Resources */, C739AE34284DF28600741E8F /* LaunchScreen.storyboard in Resources */, C739AE31284DF28600741E8F /* Assets.xcassets in Resources */, - C739AE2C284DF28600741E8F /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 0395747DD529D532F280B3A4 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Diary-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + BA1A55DB2A9C98560012C89D /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "${PODS_ROOT}/SwiftLint/swiftlint\n"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ C739AE1D284DF28600741E8F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C739AE29284DF28600741E8F /* ViewController.swift in Sources */, + C739AE29284DF28600741E8F /* DiaryListViewController.swift in Sources */, C739AE25284DF28600741E8F /* AppDelegate.swift in Sources */, + BA6463162ABC6DDE0080E80D /* DiaryManager.swift in Sources */, C739AE27284DF28600741E8F /* SceneDelegate.swift in Sources */, + BAECB2DD2AB187D6006B4A46 /* ImageCachingManager.swift in Sources */, + 63BB62822A9F109400524DCB /* DecodingManager.swift in Sources */, + 632F74F22AB14D8D003E1B97 /* WeatherResult.swift in Sources */, + 63E527372A9D87660000FBA6 /* DiaryListTableViewCell.swift in Sources */, + BAECB2E82AB72869006B4A46 /* AlertBuilder.swift in Sources */, C739AE2F284DF28600741E8F /* Diary.xcdatamodeld in Sources */, + BAECB2D12AB157CB006B4A46 /* NetworkConfiguration.swift in Sources */, + 63BB62B52AA182AA00524DCB /* CoreDataManagerProtocol.swift in Sources */, + 632F74F02AB14D2C003E1B97 /* NetworkManager.swift in Sources */, + BAECB2D92AB18611006B4A46 /* DiaryV2.xcmappingmodel in Sources */, + 63E527392A9D97160000FBA6 /* DiaryDetailViewController.swift in Sources */, + BABBDAE52A9F13A200D8D50B /* DecodingError.swift in Sources */, + BABBDB362AAD904100D8D50B /* CoreDataError.swift in Sources */, + BABBDB342AA6D05A00D8D50B /* ShareDisplayable.swift in Sources */, + 63BB62B32AA181BE00524DCB /* Diary+CoreDataProperties.swift in Sources */, + 63BB62B22AA181BE00524DCB /* Diary+CoreDataClass.swift in Sources */, + 632F74F42AB14DBC003E1B97 /* APIError.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ - C739AE2A284DF28600741E8F /* Main.storyboard */ = { + BAECB2E32AB568A0006B4A46 /* Localizable.strings */ = { isa = PBXVariantGroup; children = ( - C739AE2B284DF28600741E8F /* Base */, + BAECB2E22AB568A0006B4A46 /* en */, + BAECB2E52AB568D2006B4A46 /* ko */, ); - name = Main.storyboard; + name = Localizable.strings; sourceTree = ""; }; C739AE32284DF28600741E8F /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( C739AE33284DF28600741E8F /* Base */, + BAECB2E42AB568D2006B4A46 /* ko */, ); name = LaunchScreen.storyboard; sourceTree = ""; @@ -174,6 +413,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; @@ -235,6 +475,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; @@ -288,6 +529,7 @@ }; C739AE39284DF28600741E8F /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = D2A4A06DD84A8CE69E772DD0 /* Pods-Diary.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -297,7 +539,6 @@ INFOPLIST_FILE = Diary/Info.plist; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UIMainStoryboardFile = Main; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; IPHONEOS_DEPLOYMENT_TARGET = 14.0; @@ -316,6 +557,7 @@ }; C739AE3A284DF28600741E8F /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 7B86D20E06F2B506DECF94F6 /* Pods-Diary.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -325,7 +567,6 @@ INFOPLIST_FILE = Diary/Info.plist; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UIMainStoryboardFile = Main; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; IPHONEOS_DEPLOYMENT_TARGET = 14.0; @@ -369,9 +610,10 @@ C739AE2D284DF28600741E8F /* Diary.xcdatamodeld */ = { isa = XCVersionGroup; children = ( + 632F74F72AB17E05003E1B97 /* Diary V2.xcdatamodel */, C739AE2E284DF28600741E8F /* Diary.xcdatamodel */, ); - currentVersion = C739AE2E284DF28600741E8F /* Diary.xcdatamodel */; + currentVersion = 632F74F72AB17E05003E1B97 /* Diary V2.xcdatamodel */; path = Diary.xcdatamodeld; sourceTree = ""; versionGroupType = wrapper.xcdatamodel; diff --git a/Diary.xcodeproj/xcshareddata/xcschemes/Diary.xcscheme b/Diary.xcodeproj/xcshareddata/xcschemes/Diary.xcscheme new file mode 100644 index 000000000..f5cb22860 --- /dev/null +++ b/Diary.xcodeproj/xcshareddata/xcschemes/Diary.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Diary.xcworkspace/contents.xcworkspacedata b/Diary.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..c97203c77 --- /dev/null +++ b/Diary.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Diary.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Diary.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/Diary.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Diary/App/AppDelegate.swift b/Diary/App/AppDelegate.swift new file mode 100644 index 000000000..0d4067146 --- /dev/null +++ b/Diary/App/AppDelegate.swift @@ -0,0 +1,31 @@ +// +// Diary - AppDelegate.swift +// Created by yagom. +// Copyright © yagom. All rights reserved. +// Last modified by Maxhyunm, Hamg. + +import UIKit +import CoreData + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } +} + diff --git a/Diary/SceneDelegate.swift b/Diary/App/SceneDelegate.swift similarity index 73% rename from Diary/SceneDelegate.swift rename to Diary/App/SceneDelegate.swift index c739cbc38..8f348e891 100644 --- a/Diary/SceneDelegate.swift +++ b/Diary/App/SceneDelegate.swift @@ -1,21 +1,25 @@ // // Diary - SceneDelegate.swift -// Created by yagom. +// Created by yagom. // Copyright © yagom. All rights reserved. -// +// Last modified by Maxhyunm, Hamg. import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - + let diaryManager = DiaryManager() func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { - // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. - // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. - // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). - guard let _ = (scene as? UIWindowScene) else { return } + guard let windowScene = (scene as? UIWindowScene) else { return } + + window = UIWindow(windowScene: windowScene) + let diaryListViewController = DiaryListViewController() + diaryListViewController.diaryManager = diaryManager + let navigationController = UINavigationController(rootViewController: diaryListViewController) + window?.rootViewController = navigationController + window?.makeKeyAndVisible() } func sceneDidDisconnect(_ scene: UIScene) { @@ -46,9 +50,12 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { // to restore the scene back to its current state. // Save changes in the application's managed object context when the application transitions to the background. - (UIApplication.shared.delegate as? AppDelegate)?.saveContext() + do { + try diaryManager.saveContext() + } catch { + fatalError(CoreDataError.saveFailure.message) + } } } - diff --git a/Diary/AppDelegate.swift b/Diary/AppDelegate.swift deleted file mode 100644 index 7efc2f7c0..000000000 --- a/Diary/AppDelegate.swift +++ /dev/null @@ -1,80 +0,0 @@ -// -// Diary - AppDelegate.swift -// Created by yagom. -// Copyright © yagom. All rights reserved. -// - -import UIKit -import CoreData - -@main -class AppDelegate: UIResponder, UIApplicationDelegate { - - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - return true - } - - // MARK: UISceneSession Lifecycle - - func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { - // Called when a new scene session is being created. - // Use this method to select a configuration to create the new scene with. - return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) - } - - func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { - // Called when the user discards a scene session. - // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. - // Use this method to release any resources that were specific to the discarded scenes, as they will not return. - } - - // MARK: - Core Data stack - - lazy var persistentContainer: NSPersistentContainer = { - /* - The persistent container for the application. This implementation - creates and returns a container, having loaded the store for the - application to it. This property is optional since there are legitimate - error conditions that could cause the creation of the store to fail. - */ - let container = NSPersistentContainer(name: "Diary") - container.loadPersistentStores(completionHandler: { (storeDescription, error) in - if let error = error as NSError? { - // Replace this implementation with code to handle the error appropriately. - // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. - - /* - Typical reasons for an error here include: - * The parent directory does not exist, cannot be created, or disallows writing. - * The persistent store is not accessible, due to permissions or data protection when the device is locked. - * The device is out of space. - * The store could not be migrated to the current model version. - Check the error message to determine what the actual problem was. - */ - fatalError("Unresolved error \(error), \(error.userInfo)") - } - }) - return container - }() - - // MARK: - Core Data Saving support - - func saveContext () { - let context = persistentContainer.viewContext - if context.hasChanges { - do { - try context.save() - } catch { - // Replace this implementation with code to handle the error appropriately. - // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. - let nserror = error as NSError - fatalError("Unresolved error \(nserror), \(nserror.userInfo)") - } - } - } - -} - diff --git a/Diary/Assets.xcassets/sample.dataset/Contents.json b/Diary/Assets.xcassets/sample.dataset/Contents.json new file mode 100644 index 000000000..4a27eac56 --- /dev/null +++ b/Diary/Assets.xcassets/sample.dataset/Contents.json @@ -0,0 +1,12 @@ +{ + "data" : [ + { + "filename" : "sample.json", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Diary/Assets.xcassets/sample.dataset/sample.json b/Diary/Assets.xcassets/sample.dataset/sample.json new file mode 100644 index 000000000..6746d8848 --- /dev/null +++ b/Diary/Assets.xcassets/sample.dataset/sample.json @@ -0,0 +1,77 @@ +[ + { + "title": "똘기떵이호치새초미자축인묘", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + }, + { + "title": "드라고요롱이마초미미진사오미", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + }, + { + "title": "몽키키키강달찡찡신유술해", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + }, + { + "title": "네번째", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + }, + { + "title": "승리는 우리의 것", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + }, + { + "title": "호롤ㄹ로롤롤로로로롤롤로롤롤ㄹ롤롤 나방이 홓ㄹ로롤롤ㄹ로로로ㅗ롤로롤", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + }, + { + "title": "이것은 리스트의 아이템입니다. 쪼매 제목이 길쥬? 그렇습니다. 그래도 뭐... 해야죠 뭐", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + }, + { + "title": "우주 외계인 그는 무서운 암흑대왕", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + }, + { + "title": "이것은 리스트의 아이템입니다. 쪼매 제목이 길쥬? 그렇습니다. 그래도 뭐... 해야죠 뭐", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + }, + { + "title": "하나면 하나지 둘이겠느냐~", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + }, + { + "title": "더 내려가봐유?", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + }, + { + "title": "이것은 리스트의 아이템입니다. 쪼매 제목이 길쥬? 그렇습니다. 그래도 뭐... 해야죠 뭐", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + }, + { + "title": "이것은 리스트의 아이템입니다. 쪼매 제목이 길쥬? 그렇습니다. 그래도 뭐... 해야죠 뭐", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + }, + { + "title": "이것은 리스트의 아이템입니다. 쪼매 제목이 길쥬? 그렇습니다. 그래도 뭐... 해야죠 뭐", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + }, + { + "title": "이것은 리스트의 아이템입니다. 쪼매 제목이 길쥬? 그렇습니다. 그래도 뭐... 해야죠 뭐", + "body": "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath", + "created_at": 1608651333 + } +] \ No newline at end of file diff --git a/Diary/Base.lproj/Main.storyboard b/Diary/Base.lproj/Main.storyboard deleted file mode 100644 index 25a763858..000000000 --- a/Diary/Base.lproj/Main.storyboard +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Diary/Builder/AlertBuilder.swift b/Diary/Builder/AlertBuilder.swift new file mode 100644 index 000000000..b9e84fda7 --- /dev/null +++ b/Diary/Builder/AlertBuilder.swift @@ -0,0 +1,110 @@ +// +// AlertBuilder.swift +// Diary +// +// Created by Min Hyun on 2023/09/17. +// + +import UIKit + +final class AlertBuilder { + private let viewController: UIViewController + private let alertController: UIAlertController + + private var type: AlertType? + private var alertActions: [UIAlertAction] = [] + + init(viewController: UIViewController, prefferedStyle: UIAlertController.Style) { + self.viewController = viewController + self.alertController = UIAlertController(title: nil, message: nil, preferredStyle: prefferedStyle) + } + + func setType(_ type: AlertType) { + self.type = type + } + + func addAction(_ actionType: AlertActionType, action: ((UIAlertAction) -> Void)? = nil) { + let action = UIAlertAction(title: actionType.title, style: actionType.style, handler: action) + alertActions.append(action) + } + + @discardableResult + func show() -> Self { + alertController.title = type?.title + alertController.message = type?.message + alertActions.forEach { alertController.addAction($0) } + + viewController.present(alertController, animated: true) + + return self + } +} + +extension AlertBuilder { + enum AlertType { + case decodingError(error: DecodingError) + case apiError(error: APIError) + case coreDataError(error: CoreDataError) + case delete + case actionSheet + + var title: String? { + switch self { + case .decodingError, .apiError: + return NSLocalizedString("networkError", comment: "") + case .coreDataError(let error): + return error.alertTitle + case .delete: + return NSLocalizedString("deleteTitle", comment: "") + case .actionSheet: + return nil + } + } + + var message: String? { + switch self { + case .decodingError(let error): + return error.message + case .apiError(let error): + return error.message + case .coreDataError(let error): + return error.message + case .delete: + return NSLocalizedString("deleteMessage", comment: "") + case .actionSheet: + return nil + } + } + } + + enum AlertActionType { + case confirm + case cancel + case share + case delete + + var title: String { + switch self { + case .confirm: + return NSLocalizedString("confirm", comment: "") + case .cancel: + return NSLocalizedString("cancel", comment: "") + case .share: + return NSLocalizedString("share", comment: "") + case .delete: + return NSLocalizedString("delete", comment: "") + } + } + + var style: UIAlertAction.Style { + switch self { + case .cancel: + return .cancel + case .delete: + return .destructive + default: + return .default + } + } + } +} diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift new file mode 100644 index 000000000..afec5a043 --- /dev/null +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -0,0 +1,258 @@ +// +// DiaryDetailViewController.swift +// Diary +// +// Created by Maxhyunm, Hamg on 2023/08/29. +// + +import UIKit + +final class DiaryDetailViewController: UIViewController, ShareDisplayable { + private let textView: UITextView = { + let textView = UITextView() + textView.translatesAutoresizingMaskIntoConstraints = false + textView.font = .preferredFont(forTextStyle: .body) + + return textView + }() + + private let diaryManager: DiaryManager + private var diary: Diary + private var isNew: Bool + private var latitude: Double? + private var longitude: Double? + + init(latitude: Double?, longitude: Double?, diaryManager: DiaryManager) { + self.diaryManager = diaryManager + self.diary = diaryManager.createDiary() + self.isNew = true + self.latitude = latitude + self.longitude = longitude + + super.init(nibName: nil, bundle: nil) + fetchWeather() + } + + init(_ diary: Diary, diaryManager: DiaryManager) { + self.diaryManager = diaryManager + self.diary = diary + self.isNew = false + + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + configureUI() + setupBodyText() + setupNavigationBarButton() + setupNotification() + } + + private func configureUI() { + view.backgroundColor = .systemBackground + + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .long + dateFormatter.timeStyle = .none + self.title = dateFormatter.string(from: diary.createdAt ?? Date()) + view.addSubview(textView) + textView.delegate = self + + if isNew { + textView.becomeFirstResponder() + } + + NSLayoutConstraint.activate([ + textView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + textView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), + textView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + textView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) + ]) + } + + private func setupBodyText() { + guard let title = diary.title, + let body = diary.body else { + return + } + + textView.text = "\(title)\n\(body)" + setupFontStyle(title: title, body: body) + } + + private func splitTitleAndBody() -> (title: String, body: String) { + let contents = textView.text.components(separatedBy: "\n") + guard !contents.isEmpty, + let title = contents.first else { + return (title: "", body: "") + } + + let body = contents.dropFirst().joined(separator: "\n") + + return (title: title, body: body) + } + + private func setupFontStyle(title: String, body: String) { + let attributeString = NSMutableAttributedString(string: textView.text) + attributeString.addAttribute(.font, + value: UIFont.preferredFont(forTextStyle: .title1), + range: (textView.text as NSString).range(of: title)) + attributeString.addAttribute(.font, + value: UIFont.preferredFont(forTextStyle: .body), + range: (textView.text as NSString).range(of: body)) + textView.attributedText = attributeString + } + + private func setupNavigationBarButton() { + let moreButton = UIBarButtonItem(title: NSLocalizedString("moreOptions", comment: ""), + style: .plain, + target: self, + action: #selector(showMoreOptions)) + navigationItem.rightBarButtonItem = moreButton + } + + private func setupNotification() { + NotificationCenter.default.addObserver(self, + selector: #selector(keyboardWillShow), + name: UIResponder.keyboardWillShowNotification, + object: nil + ) + + NotificationCenter.default.addObserver(self, + selector: #selector(keyboardWillHide), + name: UIResponder.keyboardWillHideNotification, + object: nil + ) + } + + private func showDeleteAlert() { + let alertBuilder = AlertBuilder(viewController: self, prefferedStyle: .alert) + alertBuilder.setType(.delete) + alertBuilder.addAction(.cancel) + alertBuilder.addAction(.delete) { [weak self] _ in + guard let self else { return } + do { + try diaryManager.deleteData(self.diary) + self.navigationController?.popViewController(animated: true) + } catch CoreDataError.deleteFailure { + let additionalAlertBuilder = AlertBuilder(viewController: self, prefferedStyle: .alert) + additionalAlertBuilder.setType(.coreDataError(error: .deleteFailure)) + additionalAlertBuilder.addAction(.confirm) + additionalAlertBuilder.show() + } catch { + let additionalAlertBuilder = AlertBuilder(viewController: self, prefferedStyle: .alert) + additionalAlertBuilder.setType(.coreDataError(error: .unknown)) + additionalAlertBuilder.addAction(.confirm) + additionalAlertBuilder.show() + } + } + + alertBuilder.show() + } + + deinit { + NotificationCenter.default.removeObserver(self) + } +} + +extension DiaryDetailViewController { + @objc private func keyboardWillShow(_ notification: Notification) { + guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] + as? CGRect else { return } + + textView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardFrame.size.height, right: 0) + } + + @objc private func showMoreOptions() { + let alertBuilder = AlertBuilder(viewController: self, prefferedStyle: .actionSheet) + alertBuilder.setType(.actionSheet) + alertBuilder.addAction(.delete) { [weak self] _ in + guard let self else { return } + self.showDeleteAlert() + } + alertBuilder.addAction(.share) { [weak self] _ in + guard let self else { return } + self.shareDiary(self.diary) + } + alertBuilder.addAction(.cancel) + alertBuilder.show() + } + + @objc private func keyboardWillHide(_ notification: Notification) { + textView.contentInset = .zero + } +} + +extension DiaryDetailViewController: UITextViewDelegate { + func textViewDidEndEditing(_ textView: UITextView) { + let contents = textView.text.split(separator: "\n") + guard !contents.isEmpty else { return } + + do { + try diaryManager.saveContext() + } catch CoreDataError.saveFailure { + let alertBulder = AlertBuilder(viewController: self, prefferedStyle: .alert) + alertBulder.setType(.coreDataError(error: .saveFailure)) + alertBulder.addAction(.confirm) + alertBulder.show() + } catch { + let alertBulder = AlertBuilder(viewController: self, prefferedStyle: .alert) + alertBulder.setType(.coreDataError(error: .unknown)) + alertBulder.addAction(.confirm) + alertBulder.show() + } + } + + func textViewDidChange(_ textView: UITextView) { + let splitText = splitTitleAndBody() + + diary.title = splitText.title + diary.body = splitText.body + + setupFontStyle(title: splitText.title, body: splitText.body) + } +} + +extension DiaryDetailViewController { + func fetchWeather() { + guard let latitude, let longitude else { return } + + NetworkManager.shared.fetchData( + NetworkConfiguration.weatherAPI(latitude: latitude, longitude: longitude) + ) { [weak self] result in + guard let self else { return } + + switch result { + case .success(let data): + do { + let decodingData: WeatherResult = try DecodingManager.decodeData(from: data) + guard let weatherMain = decodingData.weather.first?.main, + let weatherIcon = decodingData.weather.first?.icon else { + return + } + self.diary.weatherMain = weatherMain + self.diary.weatherIcon = weatherIcon + } catch { + DispatchQueue.main.async { + let alertBulder = AlertBuilder(viewController: self, prefferedStyle: .alert) + alertBulder.setType(.decodingError(error: .decodingFailure)) + alertBulder.addAction(.confirm) + alertBulder.show() + } + } + case .failure: + DispatchQueue.main.async { + let alertBulder = AlertBuilder(viewController: self, prefferedStyle: .alert) + alertBulder.setType(.apiError(error: .requestFailure)) + alertBulder.addAction(.confirm) + alertBulder.show() + } + } + } + } +} diff --git a/Diary/Controller/DiaryListViewController.swift b/Diary/Controller/DiaryListViewController.swift new file mode 100644 index 000000000..98d89d182 --- /dev/null +++ b/Diary/Controller/DiaryListViewController.swift @@ -0,0 +1,234 @@ +// +// Diary - DiaryListViewController.swift +// Created by yagom. +// Copyright © yagom. All rights reserved. +// Last modified by Maxhyunm, Hamg. + +import UIKit +import CoreLocation + +final class DiaryListViewController: UIViewController { + private var locationManager = CLLocationManager() + private let tableView: UITableView = { + let tableView = UITableView() + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.separatorStyle = .singleLine + + return tableView + }() + + private let dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateStyle = .long + formatter.timeStyle = .none + + return formatter + }() + + var diaryManager: DiaryManager? + private var diaryList = [Diary]() + + private var latitude: Double? + private var longitude: Double? + + override func viewDidLoad() { + super.viewDidLoad() + setupLocationManager() + updateLocation() + configureUI() + setupNavigationBarButton() + setupTableView() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + readCoreData() + } + + private func configureUI() { + view.backgroundColor = .systemBackground + self.title = NSLocalizedString("titleLabel", comment: "") + + view.addSubview(tableView) + + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), + tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + tableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) + ]) + } + + private func setupNavigationBarButton() { + let addDiary = UIAction(image: UIImage(systemName: "plus")) { [weak self] _ in + guard let self, let diaryManager else { return } + let createDiaryView = DiaryDetailViewController(latitude: self.latitude, + longitude: self.longitude, + diaryManager: diaryManager) + self.navigationController?.pushViewController(createDiaryView, animated: true) + } + + navigationItem.rightBarButtonItem = UIBarButtonItem(primaryAction: addDiary) + } + + private func setupTableView() { + tableView.dataSource = self + tableView.delegate = self + tableView.register(DiaryListTableViewCell.self, forCellReuseIdentifier: DiaryListTableViewCell.identifier) + } + + private func readCoreData() { + guard let diaryManager else { return } + + do { + diaryList = try diaryManager.fetchDiary() + tableView.reloadData() + } catch CoreDataError.dataNotFound { + let alertBuilder = AlertBuilder(viewController: self, prefferedStyle: .alert) + alertBuilder.setType(.coreDataError(error: .dataNotFound)) + alertBuilder.addAction(.confirm) + alertBuilder.show() + } catch { + let alertBuilder = AlertBuilder(viewController: self, prefferedStyle: .alert) + alertBuilder.setType(.coreDataError(error: .unknown)) + alertBuilder.addAction(.confirm) + alertBuilder.show() + } + } +} + +extension DiaryListViewController: UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + diaryList.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let cell = tableView.dequeueReusableCell(withIdentifier: DiaryListTableViewCell.identifier, + for: indexPath) as? + DiaryListTableViewCell else { return UITableViewCell() } + + let diaryEntity = diaryList[indexPath.row] + guard let title = diaryEntity.title, + let createdAt = diaryEntity.createdAt, + let body = diaryEntity.body?.split(separator: "\n").joined(separator: "\n") else { + return UITableViewCell() + } + let date = dateFormatter.string(from: createdAt) + cell.setModel(title: title, date: date, body: body, icon: diaryEntity.weatherIcon) + + return cell + } + + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + let searchBar = UISearchBar() + searchBar.delegate = self + + return searchBar + } +} + +extension DiaryListViewController: UITableViewDelegate, ShareDisplayable { + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + let diaryToEdit = diaryList[indexPath.row] + + guard let diaryManager else { return } + + let createVC = DiaryDetailViewController(diaryToEdit, diaryManager: diaryManager) + + navigationController?.pushViewController(createVC, animated: true) + } + + func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> + UISwipeActionsConfiguration? { + guard let diaryManager else { return nil } + + let delete = UIContextualAction(style: .normal, title: "") { (_, _, success: @escaping (Bool) -> Void) in + let selectedDiary = self.diaryList[indexPath.row] + do { + try diaryManager.deleteData(selectedDiary) + self.readCoreData() + success(true) + } catch CoreDataError.deleteFailure { + let alertBuilder = AlertBuilder(viewController: self, prefferedStyle: .alert) + alertBuilder.setType(.coreDataError(error: .deleteFailure)) + alertBuilder.addAction(.confirm) + alertBuilder.show() + } catch { + let alertBuilder = AlertBuilder(viewController: self, prefferedStyle: .alert) + alertBuilder.setType(.coreDataError(error: .unknown)) + alertBuilder.addAction(.confirm) + alertBuilder.show() + } + } + + let share = UIContextualAction(style: .normal, title: "") { (_, _, success: @escaping (Bool) -> Void) in + let selectedDiary = self.diaryList[indexPath.row] + + self.shareDiary(selectedDiary) + success(true) + } + + delete.backgroundColor = .systemRed + delete.image = UIImage(systemName: "trash.fill") + share.backgroundColor = .systemBlue + share.image = UIImage(systemName: "square.and.arrow.up") + + return UISwipeActionsConfiguration(actions: [delete, share]) + } +} + +extension DiaryListViewController: CLLocationManagerDelegate { + private func setupLocationManager() { + locationManager.delegate = self + locationManager.requestWhenInUseAuthorization() + locationManager.desiredAccuracy = kCLLocationAccuracyBest + } + + private func updateLocation() { + let locationStatus: [CLAuthorizationStatus] = [.authorizedAlways, .authorizedWhenInUse] + + guard locationStatus.contains(locationManager.authorizationStatus) else { return } + + locationManager.startUpdatingLocation() + + guard let location: CLLocationCoordinate2D = locationManager.location?.coordinate else { return } + + latitude = location.latitude + longitude = location.longitude + + locationManager.stopUpdatingLocation() + } +} + +extension DiaryListViewController: UISearchBarDelegate { + func searchDiary(with keyword: String) { + guard let diaryManager else { return } + + if keyword.count > 0 { + do { + diaryList = try diaryManager.filterDiary(keyword) + tableView.reloadData() + } catch CoreDataError.dataNotFound { + let alertBuilder = AlertBuilder(viewController: self, prefferedStyle: .alert) + alertBuilder.setType(.coreDataError(error: .dataNotFound)) + alertBuilder.addAction(.confirm) + alertBuilder.show() + } catch { + let alertBuilder = AlertBuilder(viewController: self, prefferedStyle: .alert) + alertBuilder.setType(.coreDataError(error: .unknown)) + alertBuilder.addAction(.confirm) + alertBuilder.show() + } + } + + if keyword.count == 0 { + readCoreData() + } + } + + func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { + searchDiary(with: searchText) + } +} diff --git a/Diary/Diary.xcdatamodeld/.xccurrentversion b/Diary/Diary.xcdatamodeld/.xccurrentversion index d49fecccc..6937865e6 100644 --- a/Diary/Diary.xcdatamodeld/.xccurrentversion +++ b/Diary/Diary.xcdatamodeld/.xccurrentversion @@ -3,6 +3,6 @@ _XCCurrentVersionName - Diary.xcdatamodel + Diary V2.xcdatamodel diff --git a/Diary/Diary.xcdatamodeld/Diary V2.xcdatamodel/contents b/Diary/Diary.xcdatamodeld/Diary V2.xcdatamodel/contents new file mode 100644 index 000000000..1186dc07d --- /dev/null +++ b/Diary/Diary.xcdatamodeld/Diary V2.xcdatamodel/contents @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Diary/Diary.xcdatamodeld/Diary.xcdatamodel/contents b/Diary/Diary.xcdatamodeld/Diary.xcdatamodel/contents index 50d2514e8..b15a20237 100644 --- a/Diary/Diary.xcdatamodeld/Diary.xcdatamodel/contents +++ b/Diary/Diary.xcdatamodeld/Diary.xcdatamodel/contents @@ -1,4 +1,9 @@ - - + + + + + + + \ No newline at end of file diff --git a/Diary/DiaryV2.xcmappingmodel/xcmapping.xml b/Diary/DiaryV2.xcmappingmodel/xcmapping.xml new file mode 100644 index 000000000..771e4b631 --- /dev/null +++ b/Diary/DiaryV2.xcmappingmodel/xcmapping.xml @@ -0,0 +1,94 @@ + + + + + + 134481920 + 41993D1A-FB78-4E19-8E82-EA817904BCE2 + 109 + + + + NSPersistenceFrameworkVersion + 1244 + NSStoreModelVersionHashes + + XDDevAttributeMapping + + 0plcXXRN7XHKl5CcF+fwriFmUpON3ZtcI/AfK748aWc= + + XDDevEntityMapping + + qeN1Ym3TkWN1G6dU9RfX6Kd2ccEvcDVWHpd3LpLgboI= + + XDDevMappingModel + + EqtMzvRnVZWkXwBHu4VeVGy8UyoOe+bi67KC79kphlQ= + + XDDevPropertyMapping + + XN33V44TTGY4JETlMoOB5yyTKxB+u4slvDIinv0rtGA= + + XDDevRelationshipMapping + + akYY9LhehVA/mCb4ATLWuI9XGLcjpm14wWL1oEBtIcs= + + + NSStoreModelVersionHashesDigest + +Hmc2uYZK6og+Pvx5GUJ7oW75UG4V/ksQanTjfTKUnxyGWJRMtB5tIRgVwGsrd7lz/QR57++wbvWsr6nxwyS0A== + NSStoreModelVersionHashesVersion + 3 + NSStoreModelVersionIdentifiers + + + + + + + + + Diary/Diary.xcdatamodeld/Diary.xcdatamodel + YnBsaXN0MDDUAAEAAgADAAQABQAGAAcAClgkdmVyc2lvblkkYXJjaGl2ZXJUJHRvcFgkb2JqZWN0 +cxIAAYagXxAPTlNLZXllZEFyY2hpdmVy0QAIAAlUcm9vdIABrxCuAAsADAAbADcAOAA5AEEAQgBdAF4AXwBlAGYAcgCIAIkAigCLAIwAjQCOAI8AkACRAKoArQC0ALoAyQDYANsA6gD5APwAXAEMARsBHwEjATIBOAE5AUEBUAFZAWUBZgFnAWgBaQF+AX8BhwGIAYkBlQGpAaoBqwGsAa0BrgGvAbABsQHAAc8B3gHiAfECAAIBAhACHwIuAjoCTAJNAk4CTwJQAlECUgJTAmICcQKAAo8CkAKfAq4CvQLFAtoC2wLjAu8DAwMSAyEDMAM0A0MDUgNhA3ADfwOLA50DrAO7A8oD2QPaA+kD+AQHBBwEHQQlBDEERQRUBGMEcgR2BIUElASjBLIEwQTNBN8E7gT9BQwFGwUqBTkFSAVdBV4FZgVyBYYFlQWkBbMFtwXGBdUF5AXzBgIGDgYgBi8GPgZNBlwGXQZsBnsGigaLBo4GlwabBp8GowarBq4GsgazVSRudWxs1wANAA4ADwAQABEAEgATABQAFQAWABcAGAAXABpfEA9feGRfcm9vdFBhY2thZ2VWJGNsYXNzXF94ZF9jb21tZW50c18QEF94ZF9tb2RlbE1hbmFnZXJfEBVfY29uZmlndXJhdGlvbnNCeU5hbWVdX3hkX21vZGVsTmFtZV8QF19tb2RlbFZlcnNpb25JZGVudGlmaWVygAKArYCqgACAq4AAgKzeABwAHQAeAB8AIAAhACIADgAjACQAJQAmACcAKAApACoAKwAJACkAFwAvADAAMQAyADMAKQApABdfEBxYREJ1Y2tldEZvckNsYXNzZXN3YXNFbmNvZGVkXxAaWERCdWNrZXRGb3JQYWNrYWdlc3N0b3JhZ2VfEBxYREJ1Y2tldEZvckludGVyZmFjZXNzdG9yYWdlXxAPX3hkX293bmluZ01vZGVsXxAdWERCdWNrZXRGb3JQYWNrYWdlc3dhc0VuY29kZWRWX293bmVyXxAbWERCdWNrZXRGb3JEYXRhVHlwZXNzdG9yYWdlW192aXNpYmlsaXR5XxAZWERCdWNrZXRGb3JDbGFzc2Vzc3RvcmFnZVVfbmFtZV8QH1hEQnVja2V0Rm9ySW50ZXJmYWNlc3dhc0VuY29kZWRfEB5YREJ1Y2tldEZvckRhdGFUeXBlc3dhc0VuY29kZWRfEBBfdW5pcXVlRWxlbWVudElEgASAqICmgAGABIAAgKeAqRAAgAWAA4AEgASAAFBTWUVT0wA6ADsADgA8AD4AQFdOUy5rZXlzWk5TLm9iamVjdHOhAD2ABqEAP4AHgCVVRGlhcnnfEBAAQwBEAEUARgAhAEcASAAjAEkASgAOACUASwBMACgATQBOAE8AKQApABQAUwBUADEAKQBOAFcAPQBOAFoAWwBcXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNvcmRlcmVkXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNzdG9yYWdlXxAgWERCdWNrZXRGb3JTdGVyZW90eXBlc3dhc0VuY29kZWRfECRYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3dhc0VuY29kZWRfEB1YREJ1Y2tldEZvclN0ZXJlb3R5cGVzc3RvcmFnZV8QJFhEQnVja2V0Rm9yR2VuZXJhbGl6YXRpb25zZHVwbGljYXRlc18QJFhEQnVja2V0Rm9yR2VuZXJhbGl6YXRpb25zd2FzRW5jb2RlZF8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNvcmRlcmVkXxAhWERCdWNrZXRGb3JHZW5lcmFsaXphdGlvbnNvcmRlcmVkXxAhWERCdWNrZXRGb3JHZW5lcmFsaXphdGlvbnNzdG9yYWdlW19pc0Fic3RyYWN0gAmALIAEgASAAoAKgKOABIAJgKWABoAJgKSACAgSQDB8E1dvcmRlcmVk0wA6ADsADgBgAGIAQKEAYYALoQBjgAyAJV5YRF9QU3RlcmVvdHlwZdkAIQAlAGcADgAoAGgAIwBNAGkAPwBhAE4AbQAXACkAMQBcAHFfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc29yZGVyZWRfECRYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3dhc0VuY29kZWRfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3N0b3JhZ2WAB4ALgAmAK4AAgAQIgA3TADoAOwAOAHMAfQBAqQB0AHUAdgB3AHgAeQB6AHsAfIAOgA+AEIARgBKAE4AUgBWAFqkAfgB/AIAAgQCCAIMAhACFAIaAF4AbgByAHoAfgCGAI4AmgCqAJV8QE1hEUE1Db21wb3VuZEluZGV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uHe8d8R3zHfQd9R33HfgeNx45HjsePR4/HkAeQR5CHkMeRR5HHkgeSR5LHkweix6NHo8ekR6THpQelR6WHpcemR6bHpwenR6fHqAe3x7hHuMe5R7nHuge6R7qHuse7R7vHvAe8R7zHvQe9x82HzgfOh88Hz4fPx9AH0EfQh9EH0YfRx9IH0ofSx+KH4wfjh+QH5Ifkx+UH5Uflh+YH5ofmx+cH54fnx/eH+Af4h/kH+Yf5x/oH+kf6h/sH+4f7x/wH/If8yA+IGEggSChIKMgpSCnIKkgqyCsIK0gryCwILIgsyC1ILcguCC5ILsgvCDBIM4g0yDVINcg3CDeIOAg4iEHISshUiF2IXgheiF8IX4hgCGCIYMhhSGSIaMhpSGnIakhqyGtIa8hsSGzIcQhxiHIIcohzCHOIdAh0iHUIdYiFSIXIhkiGyIdIh4iHyIgIiEiIyIlIiYiJyIpIioiaSJrIm0ibyJxInIicyJ0InUidyJ5InoieyJ9In4ivSK/IsEiwyLFIsYixyLIIskiyyLNIs4izyLRItIi3yLgIuEi4yMiIyQjJiMoIyojKyMsIy0jLiMwIzIjMyM0IzYjNyN2I3gjeiN8I34jfyOAI4EjgiOEI4YjhyOII4ojiyPKI8wjziPQI9Ij0yPUI9Uj1iPYI9oj2yPcI94j3yQeJCAkIiQkJCYkJyQoJCkkKiQsJC4kLyQwJDIkMyRyJHQkdiR4JHokeyR8JH0kfiSAJIIkgySEJIYkhySsJNAk9yUbJR0lHyUhJSMlJSUnJSglKiU3JUYlSCVKJUwlTiVQJVIlVCVjJWUlZyVpJWslbSVvJXElcyWyJbQltiW4JboluyW8Jb0lviXAJcIlwyXEJcYlxyYGJggmCiYMJg4mDyYQJhEmEiYUJhYmFyYYJhomGyZaJlwmXiZgJmImYyZkJmUmZiZoJmomayZsJm4mbyauJrAmsia0JrYmtya4Jrkmuia8Jr4mvybAJsImwycCJwQnBicIJwonCycMJw0nDicQJxInEycUJxYnFydWJ1gnWidcJ14nXydgJ2EnYidkJ2YnZydoJ2onayeqJ6wnriewJ7Insye0J7Untie4J7onuye8J74nvygKKC0oTShtKG8ocShzKHUodyh4KHkoeyh8KH4ofyiBKIMohCiFKIcoiCiRKJ4ooyilKKcorCiuKLAosijXKPspIilGKUgpSilMKU4pUClSKVMpVSliKXMpdSl3KXkpeyl9KX8pgSmDKZQplimYKZopnCmeKaApoimkKaYp5SnnKekp6yntKe4p7ynwKfEp8yn1KfYp9yn5KfoqOSo7Kj0qPypBKkIqQypEKkUqRypJKkoqSypNKk4qjSqPKpEqkyqVKpYqlyqYKpkqmyqdKp4qnyqhKqIqryqwKrEqsyryKvQq9ir4Kvoq+yr8Kv0q/isAKwIrAysEKwYrBytGK0grSitMK04rTytQK1ErUitUK1YrVytYK1orWyuaK5wrniugK6IroyukK6UrpiuoK6orqyusK64rryvuK/Ar8iv0K/Yr9yv4K/kr+iv8K/4r/ywALAIsAyxCLEQsRixILEosSyxMLE0sTixQLFIsUyxULFYsVyx8LKAsxyzrLO0s7yzxLPMs9Sz3LPgs+i0HLRYtGC0aLRwtHi0gLSItJC0zLTUtNy05LTstPS0/LUEtQy2CLYQthi2ILYotiy2MLY0tji2QLZItky2ULZYtly3WLdgt2i3cLd4t3y3gLeEt4i3kLeYt5y3oLeot6y4qLiwuLi4wLjIuMy40LjUuNi44LjouOy48Lj4uPy5+LoAugi6ELoYuhy6ILokuii6MLo4ujy6QLpIuky6WLtUu1y7ZLtsu3S7eLt8u4C7hLuMu5S7mLucu6S7qLykvKy8tLy8vMS8yLzMvNC81LzcvOS86LzsvPS8+L30vfy+BL4MvhS+GL4cviC+JL4svjS+OL48vkS+SL50vpi+nL6kvsi+9L8wv1y/lL/owDjAlMDcwRDBFMEYwSDBVMFYwVzBZMGYwZzBoMGowczCCMI8wnjCwMMQw2zDtMPYw9zD5MQYxBzEIMQoxCzEUMR4xJQAAAAAAAAICAAAAAAAABrcAAAAAAAAAAAAAAAAAADEt + + Diary/Diary.xcdatamodeld/Diary V2.xcdatamodel + YnBsaXN0MDDUAAEAAgADAAQABQAGAAcAClgkdmVyc2lvblkkYXJjaGl2ZXJUJHRvcFgkb2JqZWN0 +cxIAAYagXxAPTlNLZXllZEFyY2hpdmVy0QAIAAlUcm9vdIABrxDeAAsADAAbADcAOAA5AEEAQgBdAF4AXwBlAGYAcgCIAIkAigCLAIwAjQCOAI8AkACRAKoArQC0ALoAyQDYANsA6gD5APwAXAEMARsBHwEjATIBOAE5AUEBUAFZAWkBagFrAWwBbQFuAW8BhAGFAY0BjgGPAZsBrwGwAbEBsgGzAbQBtQG2AbcBxgHVAeQB6AH3AgYCBwIWAiUCNAJAAlICUwJUAlUCVgJXAlgCWQJoAncChgKVApYCpQK0AsMCywLgAuEC6QL1AwkDGAMnAzYDOgNJA1gDZwN2A4UDkQOjA7IDwQPQA98D4APvA/4EDQQiBCMEKwQ3BEsEWgRpBHgEfASLBJoEqQS4BMcE0wTlBPQFAwUSBSEFMAU/BU4FYwVkBWwFeAWMBZsFqgW5Bb0FzAXbBeoF+QYIBhQGJgY1BkQGUwZiBnEGgAaPBqQGpQatBrkGzQbcBusG+gb+Bw0HHAcrBzoHSQdVB2cHdgeFB5QHoweyB8EH0AflB+YH7gf6CA4IHQgsCDsIPwhOCF0IbAh7CIoIlgioCLcIxgjVCOQI5Qj0CQMJEgkTCRYJHwkjCScJKwkzCTYJOgk7VSRudWxs1wANAA4ADwAQABEAEgATABQAFQAWABcAGAAXABpfEA9feGRfcm9vdFBhY2thZ2VWJGNsYXNzXF94ZF9jb21tZW50c18QEF94ZF9tb2RlbE1hbmFnZXJfEBVfY29uZmlndXJhdGlvbnNCeU5hbWVdX3hkX21vZGVsTmFtZV8QF19tb2RlbFZlcnNpb25JZGVudGlmaWVygAKA3YDagACA24AAgNzeABwAHQAeAB8AIAAhACIADgAjACQAJQAmACcAKAApACoAKwAJACkAFwAvADAAMQAyADMAKQApABdfEBxYREJ1Y2tldEZvckNsYXNzZXN3YXNFbmNvZGVkXxAaWERCdWNrZXRGb3JQYWNrYWdlc3N0b3JhZ2VfEBxYREJ1Y2tldEZvckludGVyZmFjZXNzdG9yYWdlXxAPX3hkX293bmluZ01vZGVsXxAdWERCdWNrZXRGb3JQYWNrYWdlc3dhc0VuY29kZWRWX293bmVyXxAbWERCdWNrZXRGb3JEYXRhVHlwZXNzdG9yYWdlW192aXNpYmlsaXR5XxAZWERCdWNrZXRGb3JDbGFzc2Vzc3RvcmFnZVVfbmFtZV8QH1hEQnVja2V0Rm9ySW50ZXJmYWNlc3dhc0VuY29kZWRfEB5YREJ1Y2tldEZvckRhdGFUeXBlc3dhc0VuY29kZWRfEBBfdW5pcXVlRWxlbWVudElEgASA2IDWgAGABIAAgNeA2RAAgAWAA4AEgASAAFBTWUVT0wA6ADsADgA8AD4AQFdOUy5rZXlzWk5TLm9iamVjdHOhAD2ABqEAP4AHgCVVRGlhcnnfEBAAQwBEAEUARgAhAEcASAAjAEkASgAOACUASwBMACgATQBOAE8AKQApABQAUwBUADEAKQBOAFcAPQBOAFoAWwBcXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNvcmRlcmVkXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNzdG9yYWdlXxAgWERCdWNrZXRGb3JTdGVyZW90eXBlc3dhc0VuY29kZWRfECRYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3dhc0VuY29kZWRfEB1YREJ1Y2tldEZvclN0ZXJlb3R5cGVzc3RvcmFnZV8QJFhEQnVja2V0Rm9yR2VuZXJhbGl6YXRpb25zZHVwbGljYXRlc18QJFhEQnVja2V0Rm9yR2VuZXJhbGl6YXRpb25zd2FzRW5jb2RlZF8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNvcmRlcmVkXxAhWERCdWNrZXRGb3JHZW5lcmFsaXphdGlvbnNvcmRlcmVkXxAhWERCdWNrZXRGb3JHZW5lcmFsaXphdGlvbnNzdG9yYWdlW19pc0Fic3RyYWN0gAmALIAEgASAAoAKgNOABIAJgNWABoAJgNSACAgSds+OmVdvcmRlcmVk0wA6ADsADgBgAGIAQKEAYYALoQBjgAyAJV5YRF9QU3RlcmVvdHlwZdkAIQAlAGcADgAoAGgAIwBNAGkAPwBhAE4AbQAXACkAMQBcAHFfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc29yZGVyZWRfECRYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3dhc0VuY29kZWRfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3N0b3JhZ2WAB4ALgAmAK4AAgAQIgA3TADoAOwAOAHMAfQB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AMIAxgDKmAWIBYwFkAWUBZgFngDOAXoB2gI2ApIC7gCVUYm9keVJpZFV0aXRsZVt3ZWF0aGVyTWFpblt3ZWF0aGVySWNvblljcmVhdGVkQXTfEBIAkgCTAJQBcAAhAJYAlwFxACMAlQFyAJgADgAlAJkAmgAoAJsAFwAXABcAKQA/AFwAXAF6ADEAXABOAFwBfgFbAFwAXAGCAFxfECBYREJ1Y2tldEZvclN0ZXJlb3R5cGVzd2FzRW5jb2RlZF8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNzdG9yYWdlXxAdWERCdWNrZXRGb3JTdGVyZW90eXBlc29yZGVyZWSAAIAAgACABIAHCAiANQiACQiAXYAtCAiANAgS5ejxwtMAOgA7AA4BhgGJAECiAYcBiIA2gDeiAYoBi4A4gEyAJV8QElhEX1BQcm9wU3RlcmVvdHlwZV8QElhEX1BBdHRfU3RlcmVvdHlwZdkAIQAlAZAADgAoAZEAIwBNAZIBYgGHAE4AbQAXACkAMQBcAZpfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc29yZGVyZWRfECRYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3dhc0VuY29kZWRfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3N0b3JhZ2WAM4A2gAmAK4AAgAQIgDnTADoAOwAOAZwBpQBAqAGdAZ4BnwGgAaEBogGjAaSAOoA7gDyAPYA+gD+AQIBBqAGmAacBqAGpAaoBqwGsAa2AQoBDgESARoBHgEmASoBLgCVfEBtYRF9QUFNLX2lzU3RvcmVkSW5UcnV0aEZpbGVfEBtYRF9QUFNLX3ZlcnNpb25IYXNoTW9kaWZpZXJfEBBYRF9QUFNLX3VzZXJJbmZvXxARWERfUFBTS19pc0luZGV4ZWRfEBJYRF9QUFNLX2lzT3B0aW9uYWxfEBpYRF9QUFNLX2lzU3BvdGxpZ2h0SW5kZXhlZF8QEVhEX1BQU0tfZWxlbWVudElEXxATWERfUFBTS19pc1RyYW5zaWVudN8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXAP4AFwGKAFwAXABcADEAXACkAZ0AXABcABcAXIAAgCKAAIA4CAgICIAagDoICIAACN8QDwCSAJMAlAAhAJUAlgCXACM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rZXRGb3JPd25lZEF0dHJpYnV0ZXN3YXNFbmNvZGVkXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNzdG9yYWdlgKSAN4AJgCuAAIAECICz0wA6ADsADgdWB14AQKcCQgJDAkQCRQJGAkcCSIBOgE+AUIBRgFKAU4BUpwdfB2AHYQdiB2MHZAdlgLSAtYC2gLeAuIC5gLqAJd8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXABcAFwarAFwAXABcADEAXACkAkIAXABcABcAXIAAgACAAICyCAgICIAagE4ICIAACN8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXAP4AFwarAFwAXABcADEAXACkAkMAXABcABcAXIAAgCKAAICyCAgICIAagE8ICIAACN8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXABcAFwarAFwAXABcADEAXACkAkQAXABcABcAXIAAgACAAICyCAgICIAagFAICIAACN8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXAogAFwarAFwAXABcADEAXACkAkUAXABcABcAXIAAgFmAAICyCAgICIAagFEICIAACN8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXABcAFwarAFwAXABcADEAXACkAkYAXABcABcAXIAAgACAAICyCAgICIAagFIICIAACN8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXABcAFwarAFwAXABcADEAXACkAkcAXABcABcAXIAAgACAAICyCAgICIAagFMICIAACN8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXABcAFwarAFwAXABcADEAXACkAkgAXABcABcAXIAAgACAAICyCAgICIAagFQICIAACN8QEgCSAJMAlAfRACEAlgCXB9IAIwCVB9MAmAAOACUAmQCaACgAmwAXABcAFwApAD8AXABcB9sAMQBcAE4AXAF+AWAAXABcB+MAXF8QIFhEQnVja2V0Rm9yU3RlcmVvdHlwZXN3YXNFbmNvZGVkXxAdWERCdWNrZXRGb3JTdGVyZW90eXBlc3N0b3JhZ2VfEB1YREJ1Y2tldEZvclN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AF4EXgheEF4UXxBfGF8gXyhfMF80XzhfPF9AX0hfUF9UX1hfYF9kYGBgaGBwYHhggGCEYIhgjGCQYJhgoGCkYKhgsGC0YNhhEGFEYXxhsGH8YlhioGPMZFhk2GVYZWBlaGVwZXhlgGWEZYhlkGWUZZxloGWoZbBltGW4ZcBlxGXYZgxmIGYoZjBmRGZMZlRmXGbwZ4BoHGisaLRovGjEaMxo1GjcaOBo6GkcaWBpaGlwaXhpgGmIaZBpmGmgaeRp7Gn0afxqBGoMahRqHGokaixrKGswazhrQGtIa0xrUGtUa1hrYGtoa2xrcGt4a3xseGyAbIhskGyYbJxsoGykbKhssGy4bLxswGzIbMxtyG3Qbdht4G3obext8G30bfhuAG4IbgxuEG4YbhxuUG5UblhuYG9cb2RvbG90b3xvgG+Eb4hvjG+Ub5xvoG+kb6xvsHCscLRwvHDEcMxw0HDUcNhw3HDkcOxw8HD0cPxxAHH8cgRyDHIUchxyIHIkcihyLHI0cjxyQHJEckxyUHNMc1RzXHNkc2xzcHN0c3hzfHOEc4xzkHOUc5xzoHScdKR0rHS0dLx0wHTEdMh0zHTUdNx04HTkdOx08HWEdhR2sHdAd0h3UHdYd2B3aHdwd3R3fHewd+x39Hf8eAR4DHgUeBx4JHhgeGh4cHh4eIB4iHiQeJh4oHmceaR5rHm0ebx5wHnEech5zHnUedx54Hnkeex58HrsevR6/HsEewx7EHsUexh7HHskeyx7MHs0ezx7QHw8fER8THxUfFx8YHxkfGh8bHx0fHx8gHyEfIx8kH2MfZR9nH2kfax9sH20fbh9vH3Efcx90H3Ufdx94H3sfuh+8H74fwB/CH8MfxB/FH8YfyB/KH8sfzB/OH88gDiAQIBIgFCAWIBcgGCAZIBogHCAeIB8gICAiICMgYiBkIGYgaCBqIGsgbCBtIG4gcCByIHMgdCB2IHcgwiDlIQUhJSEnISkhKyEtIS8hMCExITMhNCE2ITchOSE7ITwhPSE/IUAhRSFSIVchWSFbIWAhYiFkIWYhiyGvIdYh+iH8If4iACICIgQiBiIHIgkiFiInIikiKyItIi8iMSIzIjUiNyJIIkoiTCJOIlAiUiJUIlYiWCJaIpkimyKdIp8ioSKiIqMipCKlIqciqSKqIqsirSKuIu0i7yLxIvMi9SL2Ivci+CL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2OLs4vTi/OMQ4xjjIOMo47zkTOTo5XjlgOWI5ZDlmOWg5ajlrOW05ejmLOY05jzmROZM5lTmXOZk5mzmsOa45sDmyObQ5tjm4Obo5vDm+Of05/zoBOgM6BToGOgc6CDoJOgs6DToOOg86EToSOlE6UzpVOlc6WTpaOls6XDpdOl86YTpiOmM6ZTpmOqU6pzqpOqs6rTquOq86sDqxOrM6tTq2Orc6uTq6Osc6yDrJOss7CjsMOw47EDsSOxM7FDsVOxY7GDsaOxs7HDseOx87XjtgO2I7ZDtmO2c7aDtpO2o7bDtuO287cDtyO3M7sju0O7Y7uDu6O7s7vDu9O747wDvCO8M7xDvGO8c8BjwIPAo8DDwOPA88EDwRPBI8FDwWPBc8GDwaPBs8WjxcPF48YDxiPGM8ZDxlPGY8aDxqPGs8bDxuPG88lDy4PN89Az0FPQc9CT0LPQ09Dz0QPRI9Hz0uPTA9Mj00PTY9OD06PTw9Sz1NPU89UT1TPVU9Vz1ZPVs9mj2cPZ49oD2iPaM9pD2lPaY9qD2qPas9rD2uPa897j3wPfI99D32Pfc9+D35Pfo9/D3+Pf8+AD4CPgM+Qj5EPkY+SD5KPks+TD5NPk4+UD5SPlM+VD5WPlc+lj6YPpo+nD6ePp8+oD6hPqI+pD6mPqc+qD6qPqs+rj7tPu8+8T7zPvU+9j73Pvg++T77Pv0+/j7/PwE/Aj9BP0M/RT9HP0k/Sj9LP0w/TT9PP1E/Uj9TP1U/Vj+VP5c/mT+bP50/nj+fP6A/oT+jP6U/pj+nP6k/qj+1P74/vz/BP8o/1T/kP+8//UASQCZAPUBPQFxAXUBeQGBAbUBuQG9AcUB+QH9AgECCQItAmkCnQLZAyEDcQPNBBUEOQQ9BEUEeQR9BIEEiQSNBLEE2QT0AAAAAAAACAgAAAAAAAAk/AAAAAAAAAAAAAAAAAABBRQ== + + + + + id + + + + weatherIcon + + + + weatherMain + + + + Diary + Undefined + 1 + Diary + 1 + + + + + + body + + + + title + + + + createdAt + + + \ No newline at end of file diff --git a/Diary/Error/APIError.swift b/Diary/Error/APIError.swift new file mode 100644 index 000000000..b1922e675 --- /dev/null +++ b/Diary/Error/APIError.swift @@ -0,0 +1,33 @@ +// +// APIError.swift +// Diary +// +// Created by Max, Hemg on 2023/09/13. +// +import Foundation + +enum APIError: Error { + case invalidURL + case requestFailure + case invalidData + case dataTransferFailure + case invalidHTTPStatusCode + case requestTimeOut + + var message: String? { + switch self { + case .invalidURL: + return NSLocalizedString("invalidURL", comment: "") + case .requestFailure: + return NSLocalizedString("requestFailure", comment: "") + case .invalidData: + return NSLocalizedString("invalidData", comment: "") + case .dataTransferFailure: + return NSLocalizedString("dataTransferFailure", comment: "") + case .invalidHTTPStatusCode: + return NSLocalizedString("invalidHTTPStatusCode", comment: "") + case . requestTimeOut: + return NSLocalizedString("requestTimeOut", comment: "") + } + } +} diff --git a/Diary/Error/CoreDataError.swift b/Diary/Error/CoreDataError.swift new file mode 100644 index 000000000..edbc0e9f6 --- /dev/null +++ b/Diary/Error/CoreDataError.swift @@ -0,0 +1,51 @@ +// +// CoreDataError.swift +// Diary +// +// Created by Max, Hemg on 2023/09/10. +// + +import Foundation + +enum CoreDataError: Error { + case createFailure + case dataNotFound + case saveFailure + case updateFailure + case deleteFailure + case unknown + + var alertTitle: String { + switch self { + case .createFailure: + return NSLocalizedString("createFailureTitle", comment: "") + case .dataNotFound: + return NSLocalizedString("dataNotFoundTitle", comment: "") + case .saveFailure: + return NSLocalizedString("saveFailureTitle", comment: "") + case .updateFailure: + return NSLocalizedString("updateFailureTitle", comment: "") + case .deleteFailure: + return NSLocalizedString("deleteFailureTitle", comment: "") + case .unknown: + return NSLocalizedString("unknownErrorTitle", comment: "") + } + } + + var message: String { + switch self { + case .createFailure: + return NSLocalizedString("createFailure", comment: "") + case .dataNotFound: + return NSLocalizedString("dataNotFound", comment: "") + case .saveFailure: + return NSLocalizedString("saveFailure", comment: "") + case .updateFailure: + return NSLocalizedString("updateFailure", comment: "") + case .deleteFailure: + return NSLocalizedString("deleteFailure", comment: "") + case .unknown: + return NSLocalizedString("unknownError", comment: "") + } + } +} diff --git a/Diary/Error/DecodingError.swift b/Diary/Error/DecodingError.swift new file mode 100644 index 000000000..57ceec6ea --- /dev/null +++ b/Diary/Error/DecodingError.swift @@ -0,0 +1,25 @@ +// +// Error.swift +// Diary +// +// Created by Max, Hemg on 2023/08/30. +// + +import Foundation + +enum DecodingError: Error { + case fileNotFound + case decodingFailure + case unknown + + var message: String { + switch self { + case .fileNotFound: + return NSLocalizedString("fileNotFound", comment: "") + case .decodingFailure: + return NSLocalizedString("decodingFailure", comment: "") + case .unknown: + return NSLocalizedString("unknownError", comment: "") + } + } +} diff --git a/Diary/Info.plist b/Diary/Info.plist index dd3c9afda..4e929752e 100644 --- a/Diary/Info.plist +++ b/Diary/Info.plist @@ -2,6 +2,8 @@ + NSLocationWhenInUseUsageDescription + 위치 정보 수집을 수락합니다 UIApplicationSceneManifest UIApplicationSupportsMultipleScenes @@ -15,8 +17,6 @@ Default Configuration UISceneDelegateClassName $(PRODUCT_MODULE_NAME).SceneDelegate - UISceneStoryboardFile - Main diff --git a/Diary/Model/CoreData/CoreDataManagerProtocol.swift b/Diary/Model/CoreData/CoreDataManagerProtocol.swift new file mode 100644 index 000000000..455ec8938 --- /dev/null +++ b/Diary/Model/CoreData/CoreDataManagerProtocol.swift @@ -0,0 +1,67 @@ +// +// CoreDataManager.swift +// Diary +// +// Created by Max, Hemg on 2023/09/01. +// + +import CoreData + +protocol CoreDataManagerProtocol { + associatedtype Entity where Entity: NSManagedObject + var persistentContainer: NSPersistentContainer { get set } +} + +extension CoreDataManagerProtocol { + func fetchEntity(predicate: NSPredicate? = nil, sortBy: String? = nil) throws -> [Entity] { + let request: NSFetchRequest = NSFetchRequest(entityName: persistentContainer.name) + if let predicate { + request.predicate = predicate + } + + if let sortBy { + let sorted = NSSortDescriptor(key: sortBy, ascending: false) + request.sortDescriptors = [sorted] + } + + do { + let entities: [Entity] = try persistentContainer.viewContext.fetch(request) + return entities + } catch { + throw CoreDataError.dataNotFound + } + } + + func createData() throws -> Entity { + let newData = Entity(context: persistentContainer.viewContext) + try saveContext() + return newData + } + + func updateData(_ entity: Entity?, key: String?, value: String?) throws { + guard let entity, let key, let value else { + throw CoreDataError.updateFailure + } + entity.setValue(value, forKey: key) + try saveContext() + } + + func deleteData(_ entity: Entity?) throws { + guard let entity else { + throw CoreDataError.deleteFailure + } + persistentContainer.viewContext.delete(entity) + try saveContext() + } + + func saveContext() throws { + let context = persistentContainer.viewContext + if context.hasChanges { + do { + try context.save() + } catch { + throw CoreDataError.saveFailure + } + } + } +} diff --git a/Diary/Model/CoreData/Diary+CoreDataClass.swift b/Diary/Model/CoreData/Diary+CoreDataClass.swift new file mode 100644 index 000000000..6e10ad6aa --- /dev/null +++ b/Diary/Model/CoreData/Diary+CoreDataClass.swift @@ -0,0 +1,12 @@ +// +// Diary+CoreDataClass.swift +// Diary +// +// Created by Max, Hemg on 2023/09/01. +// +// + +import CoreData + +@objc(Diary) +public class Diary: NSManagedObject {} diff --git a/Diary/Model/CoreData/Diary+CoreDataProperties.swift b/Diary/Model/CoreData/Diary+CoreDataProperties.swift new file mode 100644 index 000000000..f9459d5f4 --- /dev/null +++ b/Diary/Model/CoreData/Diary+CoreDataProperties.swift @@ -0,0 +1,25 @@ +// +// Diary+CoreDataProperties.swift +// Diary +// +// Created by Max, Hemg on 2023/09/01. +// +// + +import CoreData + +extension Diary { + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "Diary") + } + + @NSManaged public var title: String? + @NSManaged public var body: String? + @NSManaged public var createdAt: Date? + @NSManaged public var weatherIcon: String? + @NSManaged public var weatherMain: String? +} + +extension Diary: Identifiable { + @NSManaged public var id: UUID? +} diff --git a/Diary/Model/CoreData/DiaryManager.swift b/Diary/Model/CoreData/DiaryManager.swift new file mode 100644 index 000000000..4cafaef1c --- /dev/null +++ b/Diary/Model/CoreData/DiaryManager.swift @@ -0,0 +1,45 @@ +// +// DiaryManager.swift +// Diary +// +// Created by Min Hyun on 2023/09/21. +// + +import CoreData + +class DiaryManager: CoreDataManagerProtocol { + var persistentContainer: NSPersistentContainer + + init() { + persistentContainer = { + let container = NSPersistentContainer(name: "Diary") + container.loadPersistentStores(completionHandler: { (_, error) in + if let error = error as NSError? { + fatalError("Unresolved error \(error), \(error.userInfo)") + } + }) + return container + }() + } + + func createDiary() -> Entity { + let newDiary: Entity = Entity(context: persistentContainer.viewContext) + newDiary.id = UUID() + newDiary.createdAt = Date() + return newDiary + } + + func fetchDiary() throws -> [Entity] { + let predicated = NSPredicate(format: "title != nil") + let filtered = try fetchEntity(predicate: predicated, sortBy: "createdAt") + return filtered + } + + func filterDiary(_ keyword: String) throws -> [Entity] { + let predicate = "title CONTAINS[cd] %@ OR body CONTAINS[cd] %@ AND title != nil" + let predicated = NSPredicate(format: predicate, keyword, keyword) + let filtered = try fetchEntity(predicate: predicated, sortBy: "createdAt") + + return filtered + } +} diff --git a/Diary/Model/DTO/DecodingManager.swift b/Diary/Model/DTO/DecodingManager.swift new file mode 100644 index 000000000..748f6f341 --- /dev/null +++ b/Diary/Model/DTO/DecodingManager.swift @@ -0,0 +1,20 @@ +// +// DecodingManager.swift +// Diary +// +// Created by Maxhyunm, Hamg on 2023/08/30. +// + +import UIKit + +final class DecodingManager { + static func decodeData(from data: Data) throws -> T { + let decoder = JSONDecoder() + + guard let decodedData = try? decoder.decode(T.self, from: data) else { + throw DecodingError.decodingFailure + } + + return decodedData + } +} diff --git a/Diary/Model/DTO/WeatherResult.swift b/Diary/Model/DTO/WeatherResult.swift new file mode 100644 index 000000000..c1e7fcdeb --- /dev/null +++ b/Diary/Model/DTO/WeatherResult.swift @@ -0,0 +1,17 @@ +// +// WeatherResult.swift +// Diary +// +// Created by Max, Hemg on 2023/09/13. +// + +struct WeatherResult: Decodable { + let weather: [Weather] + + struct Weather: Decodable { + let id: Int + let main: String + let description: String + let icon: String + } +} diff --git a/Diary/Model/ImageCache/ImageCachingManager.swift b/Diary/Model/ImageCache/ImageCachingManager.swift new file mode 100644 index 000000000..e6ba2af05 --- /dev/null +++ b/Diary/Model/ImageCache/ImageCachingManager.swift @@ -0,0 +1,14 @@ +// +// ImageCachingManager.swift +// Diary +// +// Created by Maxhyunm, Hamg on 2023/09/13. +// + +import UIKit + +class ImageCachingManager { + static let shared = NSCache() + + private init() {} +} diff --git a/Diary/Network/NetworkConfiguration.swift b/Diary/Network/NetworkConfiguration.swift new file mode 100644 index 000000000..c6609a40a --- /dev/null +++ b/Diary/Network/NetworkConfiguration.swift @@ -0,0 +1,32 @@ +// +// NetworkConfiguration.swift +// Diary +// +// Created by Maxhyunm, Hamg on 2023/09/13. +// + +import Foundation + +enum NetworkConfiguration { + case weatherAPI(latitude: Double, longitude: Double) + case weatherIcon(id: String) + + var url: String? { + switch self { + case .weatherAPI(let latitude, let longitude): + guard let apiKey = NetworkConfiguration.apiKey else { return nil } + return "https://api.openweathermap.org/data/2.5/weather?lat=\(latitude)&lon=\(longitude)&appid=\(apiKey)" + case .weatherIcon(let id): + return "https://openweathermap.org/img/wn/\(id).png" + } + } + + static var apiKey: String? { + guard let path = Bundle.main.url(forResource: "Key", withExtension: "plist"), + let plist = NSDictionary(contentsOf: path), + let key = plist.value(forKey: "WeatherAPIKey") else { + return nil + } + return "\(key)" + } +} diff --git a/Diary/Network/NetworkManager.swift b/Diary/Network/NetworkManager.swift new file mode 100644 index 000000000..e6b631a59 --- /dev/null +++ b/Diary/Network/NetworkManager.swift @@ -0,0 +1,42 @@ +// +// NetworkManager.swift +// Diary +// +// Created by Max, Hemg on 2023/09/13. +// + +import CoreLocation + +final class NetworkManager { + static let shared = NetworkManager() + private var dataTask: URLSessionDataTask? + + private init() {} + + func fetchData(_ networkType: NetworkConfiguration, completionHandler: @escaping(Result) -> Void) { + guard let urlString = networkType.url, + let url = URL(string: urlString) else { + completionHandler(.failure(APIError.invalidURL)) + return + } + + dataTask = URLSession.shared.dataTask(with: url) { data, response, error in + if error != nil { + completionHandler(.failure(.requestFailure)) + } + + guard let httpResponse = response as? HTTPURLResponse, (200...299) ~= httpResponse.statusCode else { + completionHandler(.failure(.invalidData)) + return + } + + guard let data else { + completionHandler(.failure(.invalidData)) + return + } + + completionHandler(.success(data)) + } + self.dataTask?.resume() + } +} diff --git a/Diary/Protocol/ShareDisplayable.swift b/Diary/Protocol/ShareDisplayable.swift new file mode 100644 index 000000000..e19c6e1eb --- /dev/null +++ b/Diary/Protocol/ShareDisplayable.swift @@ -0,0 +1,37 @@ +// +// ShareDiary.swift +// Diary +// +// Created by Max, Hemg on 2023/09/05. +// + +import UIKit + +protocol ShareDisplayable { + func shareDiary(_ diary: Diary?) +} + +extension ShareDisplayable where Self: UIViewController { + func shareDiary(_ diary: Diary?) { + guard let diary, + let title = diary.title, + let createdAt = diary.createdAt, + let body = diary.body else { + return + } + + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .long + dateFormatter.timeStyle = .none + let date = dateFormatter.string(from: createdAt) + let shareText = """ + 제목: \(title) + 작성일자: \(date) + 내용: \(body) + """ + let activityViewController = UIActivityViewController(activityItems: [shareText], applicationActivities: nil) + activityViewController.popoverPresentationController?.sourceView = self.view + + self.present(activityViewController, animated: true, completion: nil) + } +} diff --git a/Diary/Base.lproj/LaunchScreen.storyboard b/Diary/View/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from Diary/Base.lproj/LaunchScreen.storyboard rename to Diary/View/Base.lproj/LaunchScreen.storyboard diff --git a/Diary/View/DiaryListTableViewCell.swift b/Diary/View/DiaryListTableViewCell.swift new file mode 100644 index 000000000..119356660 --- /dev/null +++ b/Diary/View/DiaryListTableViewCell.swift @@ -0,0 +1,131 @@ +// +// DiaryListTableViewCell.swift +// Diary +// +// Created by by Maxhyunm, Hamg on 2023/08/29. +// + +import UIKit + +final class DiaryListTableViewCell: UITableViewCell { + static let identifier: String = "cell" + private let titleLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.adjustsFontForContentSizeCategory = true + label.font = .preferredFont(forTextStyle: .body) + label.setContentCompressionResistancePriority(.required, for: .vertical) + label.setContentHuggingPriority(.required, for: .vertical) + + return label + }() + + private let dateLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.adjustsFontForContentSizeCategory = true + label.font = .preferredFont(forTextStyle: .callout) + label.setContentCompressionResistancePriority(.required, for: .horizontal) + label.setContentHuggingPriority(.required, for: .horizontal) + label.setContentCompressionResistancePriority(.required, for: .vertical) + label.setContentHuggingPriority(.required, for: .vertical) + + return label + }() + + private let bodyLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.adjustsFontForContentSizeCategory = true + label.font = .preferredFont(forTextStyle: .caption2) + label.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) + label.setContentCompressionResistancePriority(.required, for: .vertical) + label.setContentHuggingPriority(.required, for: .vertical) + + return label + }() + + private let weatherIconImageView: UIImageView = { + let imageView = UIImageView() + imageView.translatesAutoresizingMaskIntoConstraints = false + imageView.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal) + imageView.setContentHuggingPriority(.required, for: .horizontal) + imageView.setContentCompressionResistancePriority(.required, for: .vertical) + imageView.setContentHuggingPriority(.required, for: .vertical) + + return imageView + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupLabel() + configureUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func prepareForReuse() { + weatherIconImageView.image = nil + } + + private func setupLabel() { + contentView.addSubview(titleLabel) + contentView.addSubview(dateLabel) + contentView.addSubview(weatherIconImageView) + contentView.addSubview(bodyLabel) + } + + private func configureUI() { + accessoryType = .disclosureIndicator + + NSLayoutConstraint.activate([ + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8), + titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -30), + + dateLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8), + dateLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + dateLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8), + + weatherIconImageView.leadingAnchor.constraint(equalTo: dateLabel.trailingAnchor, constant: 15), + weatherIconImageView.centerYAnchor.constraint(equalTo: dateLabel.centerYAnchor), + weatherIconImageView.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: 0.3), + weatherIconImageView.widthAnchor.constraint(equalTo: weatherIconImageView.heightAnchor), + + bodyLabel.leadingAnchor.constraint(equalTo: weatherIconImageView.trailingAnchor, constant: 15), + bodyLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -30), + bodyLabel.centerYAnchor.constraint(equalTo: dateLabel.centerYAnchor) + ]) + } + + func setModel(title: String, date: String, body: String, icon: String?) { + titleLabel.text = title + dateLabel.text = date + bodyLabel.text = body + + if let icon { + guard let cachedImage = ImageCachingManager.shared.object(forKey: NSString(string: icon)) else { + setImageView(icon: icon) + return + } + weatherIconImageView.image = cachedImage + } + } + + func setImageView(icon: String) { + NetworkManager.shared.fetchData(NetworkConfiguration.weatherIcon(id: icon)) { [weak self] result in + switch result { + case .success(let data): + guard let image = UIImage(data: data) else { return } + DispatchQueue.main.async { + ImageCachingManager.shared.setObject(image, forKey: NSString(string: icon)) + self?.weatherIconImageView.image = image + } + case .failure(let error): + print(error) + } + } + } +} diff --git a/Diary/View/ko.lproj/LaunchScreen.strings b/Diary/View/ko.lproj/LaunchScreen.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Diary/View/ko.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/Diary/ViewController.swift b/Diary/ViewController.swift deleted file mode 100644 index dd724e13a..000000000 --- a/Diary/ViewController.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// Diary - ViewController.swift -// Created by yagom. -// Copyright © yagom. All rights reserved. -// - -import UIKit - -class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view. - } - - -} - diff --git a/DiaryV2.xcmappingmodel/xcmapping.xml b/DiaryV2.xcmappingmodel/xcmapping.xml new file mode 100644 index 000000000..8fe98616a --- /dev/null +++ b/DiaryV2.xcmappingmodel/xcmapping.xml @@ -0,0 +1,94 @@ + + + + + + 134481920 + 30BCF772-41D1-4E5C-A435-CDC6A84C00E1 + 109 + + + + NSPersistenceFrameworkVersion + 1244 + NSStoreModelVersionHashes + + XDDevAttributeMapping + + 0plcXXRN7XHKl5CcF+fwriFmUpON3ZtcI/AfK748aWc= + + XDDevEntityMapping + + qeN1Ym3TkWN1G6dU9RfX6Kd2ccEvcDVWHpd3LpLgboI= + + XDDevMappingModel + + EqtMzvRnVZWkXwBHu4VeVGy8UyoOe+bi67KC79kphlQ= + + XDDevPropertyMapping + + XN33V44TTGY4JETlMoOB5yyTKxB+u4slvDIinv0rtGA= + + XDDevRelationshipMapping + + akYY9LhehVA/mCb4ATLWuI9XGLcjpm14wWL1oEBtIcs= + + + NSStoreModelVersionHashesDigest + +Hmc2uYZK6og+Pvx5GUJ7oW75UG4V/ksQanTjfTKUnxyGWJRMtB5tIRgVwGsrd7lz/QR57++wbvWsr6nxwyS0A== + NSStoreModelVersionHashesVersion + 3 + NSStoreModelVersionIdentifiers + + + + + + + + + weatherMain + + + + createdAt + + + + body + + + + id + + + + title + + + + weatherIcon + + + + Diary + Undefined + 1 + Diary + 1 + + + + + + Diary/Diary.xcdatamodeld/Diary.xcdatamodel + YnBsaXN0MDDUAAEAAgADAAQABQAGAAcAClgkdmVyc2lvblkkYXJjaGl2ZXJUJHRvcFgkb2JqZWN0 +cxIAAYagXxAPTlNLZXllZEFyY2hpdmVy0QAIAAlUcm9vdIABrxCuAAsADAAbADcAOAA5AEEAQgBdAF4AXwBlAGYAcgCIAIkAigCLAIwAjQCOAI8AkACRAKoArQC0ALoAyQDYANsA6gD5APwAXAEMARsBHwEjATIBOAE5AUEBUAFZAWUBZgFnAWgBaQF+AX8BhwGIAYkBlQGpAaoBqwGsAa0BrgGvAbABsQHAAc8B3gHiAfECAAIBAhACHwIuAjoCTAJNAk4CTwJQAlECUgJTAmICcQKAAo8CkAKfAq4CvQLFAtoC2wLjAu8DAwMSAyEDMAM0A0MDUgNhA3ADfwOLA50DrAO7A8oD2QPaA+kD+AQHBBwEHQQlBDEERQRUBGMEcgR2BIUElASjBLIEwQTNBN8E7gT9BQwFGwUqBTkFSAVdBV4FZgVyBYYFlQWkBbMFtwXGBdUF5AXzBgIGDgYgBi8GPgZNBlwGXQZsBnsGigaLBo4GlwabBp8GowarBq4GsgazVSRudWxs1wANAA4ADwAQABEAEgATABQAFQAWABcAGAAXABpfEA9feGRfcm9vdFBhY2thZ2VWJGNsYXNzXF94ZF9jb21tZW50c18QEF94ZF9tb2RlbE1hbmFnZXJfEBVfY29uZmlndXJhdGlvbnNCeU5hbWVdX3hkX21vZGVsTmFtZV8QF19tb2RlbFZlcnNpb25JZGVudGlmaWVygAKArYCqgACAq4AAgKzeABwAHQAeAB8AIAAhACIADgAjACQAJQAmACcAKAApACoAKwAJACkAFwAvADAAMQAyADMAKQApABdfEBxYREJ1Y2tldEZvckNsYXNzZXN3YXNFbmNvZGVkXxAaWERCdWNrZXRGb3JQYWNrYWdlc3N0b3JhZ2VfEBxYREJ1Y2tldEZvckludGVyZmFjZXNzdG9yYWdlXxAPX3hkX293bmluZ01vZGVsXxAdWERCdWNrZXRGb3JQYWNrYWdlc3dhc0VuY29kZWRWX293bmVyXxAbWERCdWNrZXRGb3JEYXRhVHlwZXNzdG9yYWdlW192aXNpYmlsaXR5XxAZWERCdWNrZXRGb3JDbGFzc2Vzc3RvcmFnZVVfbmFtZV8QH1hEQnVja2V0Rm9ySW50ZXJmYWNlc3dhc0VuY29kZWRfEB5YREJ1Y2tldEZvckRhdGFUeXBlc3dhc0VuY29kZWRfEBBfdW5pcXVlRWxlbWVudElEgASAqICmgAGABIAAgKeAqRAAgAWAA4AEgASAAFBTWUVT0wA6ADsADgA8AD4AQFdOUy5rZXlzWk5TLm9iamVjdHOhAD2ABqEAP4AHgCVVRGlhcnnfEBAAQwBEAEUARgAhAEcASAAjAEkASgAOACUASwBMACgATQBOAE8AKQApABQAUwBUADEAKQBOAFcAPQBOAFoAWwBcXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNvcmRlcmVkXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNzdG9yYWdlXxAgWERCdWNrZXRGb3JTdGVyZW90eXBlc3dhc0VuY29kZWRfECRYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3dhc0VuY29kZWRfEB1YREJ1Y2tldEZvclN0ZXJlb3R5cGVzc3RvcmFnZV8QJFhEQnVja2V0Rm9yR2VuZXJhbGl6YXRpb25zZHVwbGljYXRlc18QJFhEQnVja2V0Rm9yR2VuZXJhbGl6YXRpb25zd2FzRW5jb2RlZF8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNvcmRlcmVkXxAhWERCdWNrZXRGb3JHZW5lcmFsaXphdGlvbnNvcmRlcmVkXxAhWERCdWNrZXRGb3JHZW5lcmFsaXphdGlvbnNzdG9yYWdlW19pc0Fic3RyYWN0gAmALIAEgASAAoAKgKOABIAJgKWABoAJgKSACAgS/uys2VdvcmRlcmVk0wA6ADsADgBgAGIAQKEAYYALoQBjgAyAJV5YRF9QU3RlcmVvdHlwZdkAIQAlAGcADgAoAGgAIwBNAGkAPwBhAE4AbQAXACkAMQBcAHFfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc29yZGVyZWRfECRYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3dhc0VuY29kZWRfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3N0b3JhZ2WAB4ALgAmAK4AAgAQIgA3TADoAOwAOAHMAfQBAqQB0AHUAdgB3AHgAeQB6AHsAfIAOgA+AEIARgBKAE4AUgBWAFqkAfgB/AIAAgQCCAIMAhACFAIaAF4AbgByAHoAfgCGAI4AmgCqAJV8QE1hEUE1Db21wb3VuZEluZGV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uHe8d8R3zHfQd9R33HfgeNx45HjsePR4/HkAeQR5CHkMeRR5HHkgeSR5LHkweix6NHo8ekR6THpQelR6WHpcemR6bHpwenR6fHqAe3x7hHuMe5R7nHuge6R7qHuse7R7vHvAe8R7zHvQe9x82HzgfOh88Hz4fPx9AH0EfQh9EH0YfRx9IH0ofSx+KH4wfjh+QH5Ifkx+UH5Uflh+YH5ofmx+cH54fnx/eH+Af4h/kH+Yf5x/oH+kf6h/sH+4f7x/wH/If8yA+IGEggSChIKMgpSCnIKkgqyCsIK0gryCwILIgsyC1ILcguCC5ILsgvCDFINIg1yDZINsg4CDiIOQg5iELIS8hViF6IXwhfiGAIYIhhCGGIYchiSGWIachqSGrIa0hryGxIbMhtSG3IcghyiHMIc4h0CHSIdQh1iHYIdoiGSIbIh0iHyIhIiIiIyIkIiUiJyIpIioiKyItIi4ibSJvInEicyJ1InYidyJ4InkieyJ9In4ifyKBIoIiwSLDIsUixyLJIsoiyyLMIs0izyLRItIi0yLVItYi4yLkIuUi5yMmIygjKiMsIy4jLyMwIzEjMiM0IzYjNyM4IzojOyN6I3wjfiOAI4IjgyOEI4UjhiOII4ojiyOMI44jjyPOI9Aj0iPUI9Yj1yPYI9kj2iPcI94j3yPgI+Ij4yQiJCQkJiQoJCokKyQsJC0kLiQwJDIkMyQ0JDYkNyR2JHgkeiR8JH4kfySAJIEkgiSEJIYkhySIJIokiySwJNQk+yUfJSElIyUlJSclKSUrJSwlLiU7JUolTCVOJVAlUiVUJVYlWCVnJWklayVtJW8lcSVzJXUldyW2JbgluiW8Jb4lvyXAJcElwiXEJcYlxyXIJcolyyYKJgwmDiYQJhImEyYUJhUmFiYYJhomGyYcJh4mHyZeJmAmYiZkJmYmZyZoJmkmaiZsJm4mbyZwJnImcyayJrQmtia4Jromuya8Jr0mvibAJsImwybEJsYmxycGJwgnCicMJw4nDycQJxEnEicUJxYnFycYJxonGydaJ1wnXidgJ2InYydkJ2UnZidoJ2onaydsJ24nbyeuJ7Ansie0J7Yntye4J7knuie8J74nvyfAJ8InwygOKDEoUShxKHModSh3KHkoeyh8KH0ofyiAKIIogyiFKIcoiCiJKIsojCiRKJ4ooyilKKcorCiuKLAosijXKPspIilGKUgpSilMKU4pUClSKVMpVSliKXMpdSl3KXkpeyl9KX8pgSmDKZQplimYKZopnCmeKaApoimkKaYp5SnnKekp6yntKe4p7ynwKfEp8yn1KfYp9yn5KfoqOSo7Kj0qPypBKkIqQypEKkUqRypJKkoqSypNKk4qjSqPKpEqkyqVKpYqlyqYKpkqmyqdKp4qnyqhKqIqryqwKrEqsyryKvQq9ir4Kvoq+yr8Kv0q/isAKwIrAysEKwYrBytGK0grSitMK04rTytQK1ErUitUK1YrVytYK1orWyuaK5wrniugK6IroyukK6UrpiuoK6orqyusK64rryvuK/Ar8iv0K/Yr9yv4K/kr+iv8K/4r/ywALAIsAyxCLEQsRixILEosSyxMLE0sTixQLFIsUyxULFYsVyx8LKAsxyzrLO0s7yzxLPMs9Sz3LPgs+i0HLRYtGC0aLRwtHi0gLSItJC0zLTUtNy05LTstPS0/LUEtQy2CLYQthi2ILYotiy2MLY0tji2QLZItky2ULZYtly3WLdgt2i3cLd4t3y3gLeEt4i3kLeYt5y3oLeot6y4qLiwuLi4wLjIuMy40LjUuNi44LjouOy48Lj4uPy5+LoAugi6ELoYuhy6ILokuii6MLo4ujy6QLpIuky6WLtUu1y7ZLtsu3S7eLt8u4C7hLuMu5S7mLucu6S7qLykvKy8tLy8vMS8yLzMvNC81LzcvOS86LzsvPS8+L30vfy+BL4MvhS+GL4cviC+JL4svjS+OL48vkS+SL50vpi+nL6kvsi+9L8wv1y/lL/owDjAlMDcwRDBFMEYwSDBVMFYwVzBZMGYwZzBoMGowczCCMI8wnjCwMMQw2zDtMPYw9zD5MQYxBzEIMQoxCzEUMR4xJQAAAAAAAAICAAAAAAAABrcAAAAAAAAAAAAAAAAAADEt + + Diary/Diary.xcdatamodeld/Diary V2.xcdatamodel + YnBsaXN0MDDUAAEAAgADAAQABQAGAAcAClgkdmVyc2lvblkkYXJjaGl2ZXJUJHRvcFgkb2JqZWN0 +cxIAAYagXxAPTlNLZXllZEFyY2hpdmVy0QAIAAlUcm9vdIABrxDeAAsADAAbADcAOAA5AEEAQgBdAF4AXwBlAGYAcgCIAIkAigCLAIwAjQCOAI8AkACRAKoArQC0ALoAyQDYANsA6gD5APwAXAEMARsBHwEjATIBOAE5AUEBUAFZAWkBagFrAWwBbQFuAW8BhAGFAY0BjgGPAZsBrwGwAbEBsgGzAbQBtQG2AbcBxgHVAeQB6AH3AgYCBwIWAiUCNAJAAlICUwJUAlUCVgJXAlgCWQJoAncChgKVApYCpQK0AsMCywLgAuEC6QL1AwkDGAMnAzYDOgNJA1gDZwN2A4UDkQOjA7IDwQPQA98D4APvA/4EDQQiBCMEKwQ3BEsEWgRpBHgEfASLBJoEqQS4BMcE0wTlBPQFAwUSBSEFMAU/BU4FYwVkBWwFeAWMBZsFqgW5Bb0FzAXbBeoF+QYIBhQGJgY1BkQGUwZiBnEGgAaPBqQGpQatBrkGzQbcBusG+gb+Bw0HHAcrBzoHSQdVB2cHdgeFB5QHoweyB8EH0AflB+YH7gf6CA4IHQgsCDsIPwhOCF0IbAh7CIoIlgioCLcIxgjVCOQI5Qj0CQMJEgkTCRYJHwkjCScJKwkzCTYJOgk7VSRudWxs1wANAA4ADwAQABEAEgATABQAFQAWABcAGAAXABpfEA9feGRfcm9vdFBhY2thZ2VWJGNsYXNzXF94ZF9jb21tZW50c18QEF94ZF9tb2RlbE1hbmFnZXJfEBVfY29uZmlndXJhdGlvbnNCeU5hbWVdX3hkX21vZGVsTmFtZV8QF19tb2RlbFZlcnNpb25JZGVudGlmaWVygAKA3YDagACA24AAgNzeABwAHQAeAB8AIAAhACIADgAjACQAJQAmACcAKAApACoAKwAJACkAFwAvADAAMQAyADMAKQApABdfEBxYREJ1Y2tldEZvckNsYXNzZXN3YXNFbmNvZGVkXxAaWERCdWNrZXRGb3JQYWNrYWdlc3N0b3JhZ2VfEBxYREJ1Y2tldEZvckludGVyZmFjZXNzdG9yYWdlXxAPX3hkX293bmluZ01vZGVsXxAdWERCdWNrZXRGb3JQYWNrYWdlc3dhc0VuY29kZWRWX293bmVyXxAbWERCdWNrZXRGb3JEYXRhVHlwZXNzdG9yYWdlW192aXNpYmlsaXR5XxAZWERCdWNrZXRGb3JDbGFzc2Vzc3RvcmFnZVVfbmFtZV8QH1hEQnVja2V0Rm9ySW50ZXJmYWNlc3dhc0VuY29kZWRfEB5YREJ1Y2tldEZvckRhdGFUeXBlc3dhc0VuY29kZWRfEBBfdW5pcXVlRWxlbWVudElEgASA2IDWgAGABIAAgNeA2RAAgAWAA4AEgASAAFBTWUVT0wA6ADsADgA8AD4AQFdOUy5rZXlzWk5TLm9iamVjdHOhAD2ABqEAP4AHgCVVRGlhcnnfEBAAQwBEAEUARgAhAEcASAAjAEkASgAOACUASwBMACgATQBOAE8AKQApABQAUwBUADEAKQBOAFcAPQBOAFoAWwBcXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNvcmRlcmVkXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNzdG9yYWdlXxAgWERCdWNrZXRGb3JTdGVyZW90eXBlc3dhc0VuY29kZWRfECRYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3dhc0VuY29kZWRfEB1YREJ1Y2tldEZvclN0ZXJlb3R5cGVzc3RvcmFnZV8QJFhEQnVja2V0Rm9yR2VuZXJhbGl6YXRpb25zZHVwbGljYXRlc18QJFhEQnVja2V0Rm9yR2VuZXJhbGl6YXRpb25zd2FzRW5jb2RlZF8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNvcmRlcmVkXxAhWERCdWNrZXRGb3JHZW5lcmFsaXphdGlvbnNvcmRlcmVkXxAhWERCdWNrZXRGb3JHZW5lcmFsaXphdGlvbnNzdG9yYWdlW19pc0Fic3RyYWN0gAmALIAEgASAAoAKgNOABIAJgNWABoAJgNSACAgSsgAYSVdvcmRlcmVk0wA6ADsADgBgAGIAQKEAYYALoQBjgAyAJV5YRF9QU3RlcmVvdHlwZdkAIQAlAGcADgAoAGgAIwBNAGkAPwBhAE4AbQAXACkAMQBcAHFfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc29yZGVyZWRfECRYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3dhc0VuY29kZWRfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3N0b3JhZ2WAB4ALgAmAK4AAgAQIgA3TADoAOwAOAHMAfQB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AMIAxgDKmAWIBYwFkAWUBZgFngDOAXoB2gI2ApIC7gCVUYm9keVJpZFV0aXRsZVt3ZWF0aGVyTWFpblt3ZWF0aGVySWNvblljcmVhdGVkQXTfEBIAkgCTAJQBcAAhAJYAlwFxACMAlQFyAJgADgAlAJkAmgAoAJsAFwAXABcAKQA/AFwAXAF6ADEAXABOAFwBfgFbAFwAXAGCAFxfECBYREJ1Y2tldEZvclN0ZXJlb3R5cGVzd2FzRW5jb2RlZF8QHVhEQnVja2V0Rm9yU3RlcmVvdHlwZXNzdG9yYWdlXxAdWERCdWNrZXRGb3JTdGVyZW90eXBlc29yZGVyZWSAAIAAgACABIAHCAiANQiACQiAXYAtCAiANAgStaJqI9MAOgA7AA4BhgGJAECiAYcBiIA2gDeiAYoBi4A4gEyAJV8QElhEX1BQcm9wU3RlcmVvdHlwZV8QElhEX1BBdHRfU3RlcmVvdHlwZdkAIQAlAZAADgAoAZEAIwBNAZIBYgGHAE4AbQAXACkAMQBcAZpfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc29yZGVyZWRfECRYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3dhc0VuY29kZWRfECFYREJ1Y2tldEZvck93bmVkQXR0cmlidXRlc3N0b3JhZ2WAM4A2gAmAK4AAgAQIgDnTADoAOwAOAZwBpQBAqAGdAZ4BnwGgAaEBogGjAaSAOoA7gDyAPYA+gD+AQIBBqAGmAacBqAGpAaoBqwGsAa2AQoBDgESARoBHgEmASoBLgCVfEBtYRF9QUFNLX2lzU3RvcmVkSW5UcnV0aEZpbGVfEBtYRF9QUFNLX3ZlcnNpb25IYXNoTW9kaWZpZXJfEBBYRF9QUFNLX3VzZXJJbmZvXxARWERfUFBTS19pc0luZGV4ZWRfEBJYRF9QUFNLX2lzT3B0aW9uYWxfEBpYRF9QUFNLX2lzU3BvdGxpZ2h0SW5kZXhlZF8QEVhEX1BQU0tfZWxlbWVudElEXxATWERfUFBTS19pc1RyYW5zaWVudN8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXAP4AFwGKAFwAXABcADEAXACkAZ0AXABcABcAXIAAgCKAAIA4CAgICIAagDoICIAACN8QDwCSAJMAlAAhAJUAlgCXACM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lcmVkXxAkWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXN3YXNFbmNvZGVkXxAhWERCdWNrZXRGb3JPd25lZEF0dHJpYnV0ZXNzdG9yYWdlgKSAN4AJgCuAAIAECICz0wA6ADsADgdWB14AQKcCQgJDAkQCRQJGAkcCSIBOgE+AUIBRgFKAU4BUpwdfB2AHYQdiB2MHZAdlgLSAtYC2gLeAuIC5gLqAJd8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXABcAFwarAFwAXABcADEAXACkAkIAXABcABcAXIAAgACAAICyCAgICIAagE4ICIAACN8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXAP4AFwarAFwAXABcADEAXACkAkMAXABcABcAXIAAgCKAAICyCAgICIAagE8ICIAACN8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXABcAFwarAFwAXABcADEAXACkAkQAXABcABcAXIAAgACAAICyCAgICIAagFAICIAACN8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXAogAFwarAFwAXABcADEAXACkAkUAXABcABcAXIAAgFmAAICyCAgICIAagFEICIAACN8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXABcAFwarAFwAXABcADEAXACkAkYAXABcABcAXIAAgACAAICyCAgICIAagFIICIAACN8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXABcAFwarAFwAXABcADEAXACkAkcAXABcABcAXIAAgACAAICyCAgICIAagFMICIAACN8QDwCSAJMAlAAhAJUAlgCXACMAmAAOACUAmQCaACgAmwAXABcAFwarAFwAXABcADEAXACkAkgAXABcABcAXIAAgACAAICyCAgICIAagFQICIAACN8QEgCSAJMAlAfRACEAlgCXB9IAIwCVB9MAmAAOACUAmQCaACgAmwAXABcAFwApAD8AXABcB9sAMQBcAE4AXAF+AWAAXABcB+MAXF8QIFhEQnVja2V0Rm9yU3RlcmVvdHlwZXN3YXNFbmNvZGVkXxAdWERCdWNrZXRGb3JTdGVyZW90eXBlc3N0b3JhZ2VfEB1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4F3kXehd7F3wXfheAF4EXgheEF4UXxBfGF8gXyhfMF80XzhfPF9AX0hfUF9UX1hfYF9kYGBgaGBwYHhggGCEYIhgjGCQYJhgoGCkYKhgsGC0YNhhEGFEYXxhsGH8YlhioGPMZFhk2GVYZWBlaGVwZXhlgGWEZYhlkGWUZZxloGWoZbBltGW4ZcBlxGXYZgxmIGYoZjBmRGZMZlRmXGbwZ4BoHGisaLRovGjEaMxo1GjcaOBo6GkcaWBpaGlwaXhpgGmIaZBpmGmgaeRp7Gn0afxqBGoMahRqHGokaixrKGswazhrQGtIa0xrUGtUa1hrYGtoa2xrcGt4a3xseGyAbIhskGyYbJxsoGykbKhssGy4bLxswGzIbMxtyG3Qbdht4G3obext8G30bfhuAG4IbgxuEG4YbhxuUG5UblhuYG9cb2RvbG90b3xvgG+Eb4hvjG+Ub5xvoG+kb6xvsHCscLRwvHDEcMxw0HDUcNhw3HDkcOxw8HD0cPxxAHH8cgRyDHIUchxyIHIkcihyLHI0cjxyQHJEckxyUHNMc1RzXHNkc2xzcHN0c3hzfHOEc4xzkHOUc5xzoHScdKR0rHS0dLx0wHTEdMh0zHTUdNx04HTkdOx08HWEdhR2sHdAd0h3UHdYd2B3aHdwd3R3fHewd+x39Hf8eAR4DHgUeBx4JHhgeGh4cHh4eIB4iHiQeJh4oHmceaR5rHm0ebx5wHnEech5zHnUedx54Hnkeex58HrsevR6/HsEewx7EHsUexh7HHskeyx7MHs0ezx7QHw8fER8THxUfFx8YHxkfGh8bHx0fHx8gHyEfIx8kH2MfZR9nH2kfax9sH20fbh9vH3Efcx90H3Ufdx94H3sfuh+8H74fwB/CH8MfxB/FH8YfyB/KH8sfzB/OH88gDiAQIBIgFCAWIBcgGCAZIBogHCAeIB8gICAiICMgYiBkIGYgaCBqIGsgbCBtIG4gcCByIHMgdCB2IHcgwiDlIQUhJSEnISkhKyEtIS8hMCExITMhNCE2ITchOSE7ITwhPSE/IUAhSSFWIVshXSFfIWQhZiFoIWohjyGzIdoh/iIAIgIiBCIGIggiCiILIg0iGiIrIi0iLyIxIjMiNSI3IjkiOyJMIk4iUCJSIlQiViJYIloiXCJeIp0inyKhIqMipSKmIqciqCKpIqsirSKuIq8isSKyIvEi8yL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rOKw4rTivOLA4tTjCOMc4yTjLONA40jjUONY4+zkfOUY5ajlsOW45cDlyOXQ5djl3OXk5hjmXOZk5mzmdOZ85oTmjOaU5pzm4Obo5vDm+OcA5wjnEOcY5yDnKOgk6CzoNOg86EToSOhM6FDoVOhc6GToaOhs6HToeOl06XzphOmM6ZTpmOmc6aDppOms6bTpuOm86cTpyOrE6szq1Orc6uTq6Ors6vDq9Or86wTrCOsM6xTrGOtM61DrVOtc7FjsYOxo7HDseOx87IDshOyI7JDsmOyc7KDsqOys7ajtsO247cDtyO3M7dDt1O3Y7eDt6O3s7fDt+O387vjvAO8I7xDvGO8c7yDvJO8o7zDvOO8870DvSO9M8EjwUPBY8GDwaPBs8HDwdPB48IDwiPCM8JDwmPCc8ZjxoPGo8bDxuPG88cDxxPHI8dDx2PHc8eDx6PHs8oDzEPOs9Dz0RPRM9FT0XPRk9Gz0cPR49Kz06PTw9Pj1APUI9RD1GPUg9Vz1ZPVs9XT1fPWE9Yz1lPWc9pj2oPao9rD2uPa89sD2xPbI9tD22Pbc9uD26Pbs9+j38Pf4+AD4CPgM+BD4FPgY+CD4KPgs+DD4OPg8+Tj5QPlI+VD5WPlc+WD5ZPlo+XD5ePl8+YD5iPmM+oj6kPqY+qD6qPqs+rD6tPq4+sD6yPrM+tD62Prc+uj75Pvs+/T7/PwE/Aj8DPwQ/BT8HPwk/Cj8LPw0/Dj9NP08/UT9TP1U/Vj9XP1g/WT9bP10/Xj9fP2E/Yj+hP6M/pT+nP6k/qj+rP6w/rT+vP7E/sj+zP7U/tj/BP8o/yz/NP9Y/4T/wP/tACUAeQDJASUBbQGhAaUBqQGxAeUB6QHtAfUCKQItAjECOQJdApkCzQMJA1EDoQP9BEUEaQRtBHUEqQStBLEEuQS9BOEFCQUkAAAAAAAACAgAAAAAAAAk/AAAAAAAAAAAAAAAAAABBUQ== + + + + \ No newline at end of file diff --git a/Podfile b/Podfile new file mode 100644 index 000000000..9ff2145de --- /dev/null +++ b/Podfile @@ -0,0 +1,12 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +target 'Diary' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + +pod 'SwiftLint' + + # Pods for Diary + +end diff --git a/Podfile.lock b/Podfile.lock new file mode 100644 index 000000000..e07aad683 --- /dev/null +++ b/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - SwiftLint (0.52.4) + +DEPENDENCIES: + - SwiftLint + +SPEC REPOS: + trunk: + - SwiftLint + +SPEC CHECKSUMS: + SwiftLint: 1cc5cd61ba9bacb2194e340aeb47a2a37fda00b3 + +PODFILE CHECKSUM: 26a171089eeca562e9c5056f6cdc55fb1e4058a8 + +COCOAPODS: 1.12.1 diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock new file mode 100644 index 000000000..e07aad683 --- /dev/null +++ b/Pods/Manifest.lock @@ -0,0 +1,16 @@ +PODS: + - SwiftLint (0.52.4) + +DEPENDENCIES: + - SwiftLint + +SPEC REPOS: + trunk: + - SwiftLint + +SPEC CHECKSUMS: + SwiftLint: 1cc5cd61ba9bacb2194e340aeb47a2a37fda00b3 + +PODFILE CHECKSUM: 26a171089eeca562e9c5056f6cdc55fb1e4058a8 + +COCOAPODS: 1.12.1 diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 000000000..46b6b54b0 --- /dev/null +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,514 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 52B60EC2A583F24ACBB69C113F5488B9 /* SwiftLint */ = { + isa = PBXAggregateTarget; + buildConfigurationList = AE7B4FB01588B9E6DF09CB79FC7CE7BD /* Build configuration list for PBXAggregateTarget "SwiftLint" */; + buildPhases = ( + ); + dependencies = ( + ); + name = SwiftLint; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 0884DEC90EC5021937887473691319CD /* Pods-Diary-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 19DE7212F35C78A673D6477BA6CEAC2A /* Pods-Diary-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F9ED98D46A33EEC7D22FA8472E6B867 /* Pods-Diary-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E9F08608B8CE4E23C232C8395DE1D73 /* Pods-Diary-dummy.m */; }; + F4D566A90F4C9EDEF161892ED1DB0DDB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 30E6EC47021682C037F08513CFF65D44 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 52B60EC2A583F24ACBB69C113F5488B9; + remoteInfo = SwiftLint; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 19DE7212F35C78A673D6477BA6CEAC2A /* Pods-Diary-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Diary-umbrella.h"; sourceTree = ""; }; + 265D739AF741CF836D39D207D2C2EDE5 /* Pods-Diary.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Diary.release.xcconfig"; sourceTree = ""; }; + 2E9F08608B8CE4E23C232C8395DE1D73 /* Pods-Diary-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Diary-dummy.m"; sourceTree = ""; }; + 3E9672C16ADD0ADF8116C4CEFDC7496B /* Pods-Diary-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Diary-Info.plist"; sourceTree = ""; }; + 3EC0124719FE8EF5FDDD72C26F8A2F57 /* SwiftLint.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftLint.debug.xcconfig; sourceTree = ""; }; + 47D8831BB94EC6B924653BD7DECCED8A /* Pods-Diary.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-Diary.modulemap"; sourceTree = ""; }; + 711DFE1E31ECE1AD7B6CFA4BFF4984D0 /* Pods-Diary-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Diary-acknowledgements.plist"; sourceTree = ""; }; + 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 7EAB1DA481EDDC005A251D3A5E6BE4CD /* SwiftLint.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftLint.release.xcconfig; sourceTree = ""; }; + 982010C5B6E494CA0DB1297E322FC900 /* Pods-Diary-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Diary-acknowledgements.markdown"; sourceTree = ""; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + A96125BBD2DEF0B8F60A2D8F4EA9FC50 /* Pods-Diary */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-Diary"; path = Pods_Diary.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + ABF16B16FE7DE4E56B49FC2D6C7CA936 /* Pods-Diary.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Diary.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + E2AE8D23BADE67436183EB321C191CFA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F4D566A90F4C9EDEF161892ED1DB0DDB /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 578452D2E740E91742655AC8F1636D1F /* iOS */ = { + isa = PBXGroup; + children = ( + 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */, + ); + name = iOS; + sourceTree = ""; + }; + 5D2180268F3D5A4BB6B1331844B35450 /* Pods-Diary */ = { + isa = PBXGroup; + children = ( + 47D8831BB94EC6B924653BD7DECCED8A /* Pods-Diary.modulemap */, + 982010C5B6E494CA0DB1297E322FC900 /* Pods-Diary-acknowledgements.markdown */, + 711DFE1E31ECE1AD7B6CFA4BFF4984D0 /* Pods-Diary-acknowledgements.plist */, + 2E9F08608B8CE4E23C232C8395DE1D73 /* Pods-Diary-dummy.m */, + 3E9672C16ADD0ADF8116C4CEFDC7496B /* Pods-Diary-Info.plist */, + 19DE7212F35C78A673D6477BA6CEAC2A /* Pods-Diary-umbrella.h */, + ABF16B16FE7DE4E56B49FC2D6C7CA936 /* Pods-Diary.debug.xcconfig */, + 265D739AF741CF836D39D207D2C2EDE5 /* Pods-Diary.release.xcconfig */, + ); + name = "Pods-Diary"; + path = "Target Support Files/Pods-Diary"; + sourceTree = ""; + }; + 75C6DC192FF5EB664615F978FFB66B35 /* Products */ = { + isa = PBXGroup; + children = ( + A96125BBD2DEF0B8F60A2D8F4EA9FC50 /* Pods-Diary */, + ); + name = Products; + sourceTree = ""; + }; + 7FDA596DBE0337ACDFE55A210D54EF26 /* Support Files */ = { + isa = PBXGroup; + children = ( + 3EC0124719FE8EF5FDDD72C26F8A2F57 /* SwiftLint.debug.xcconfig */, + 7EAB1DA481EDDC005A251D3A5E6BE4CD /* SwiftLint.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/SwiftLint"; + sourceTree = ""; + }; + 965877409E01FB3D85D85E90E6B30185 /* Pods */ = { + isa = PBXGroup; + children = ( + D96179D43A67C5D5323B0682D32C133C /* SwiftLint */, + ); + name = Pods; + sourceTree = ""; + }; + A44497EC80C51940FA159F2CD94CFC3D /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 5D2180268F3D5A4BB6B1331844B35450 /* Pods-Diary */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + CF1408CF629C7361332E53B88F7BD30C = { + isa = PBXGroup; + children = ( + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */, + 965877409E01FB3D85D85E90E6B30185 /* Pods */, + 75C6DC192FF5EB664615F978FFB66B35 /* Products */, + A44497EC80C51940FA159F2CD94CFC3D /* Targets Support Files */, + ); + sourceTree = ""; + }; + D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 578452D2E740E91742655AC8F1636D1F /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + D96179D43A67C5D5323B0682D32C133C /* SwiftLint */ = { + isa = PBXGroup; + children = ( + 7FDA596DBE0337ACDFE55A210D54EF26 /* Support Files */, + ); + name = SwiftLint; + path = SwiftLint; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + C319DA9EA295D5148C43D6C22A20152C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0884DEC90EC5021937887473691319CD /* Pods-Diary-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 94BCD16A333E90AD0C2F07AE6FB3D29D /* Pods-Diary */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8741FB36C60252E0472A071A841FF231 /* Build configuration list for PBXNativeTarget "Pods-Diary" */; + buildPhases = ( + C319DA9EA295D5148C43D6C22A20152C /* Headers */, + ADD864007835BC006F689B86E00B4628 /* Sources */, + E2AE8D23BADE67436183EB321C191CFA /* Frameworks */, + BCD7056F84D39331C909A81303287AE0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + B4E9CB15B2C80F2FA6632BE3A29F4D44 /* PBXTargetDependency */, + ); + name = "Pods-Diary"; + productName = Pods_Diary; + productReference = A96125BBD2DEF0B8F60A2D8F4EA9FC50 /* Pods-Diary */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BFDFE7DC352907FC980B868725387E98 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1300; + LastUpgradeCheck = 1300; + }; + buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = CF1408CF629C7361332E53B88F7BD30C; + productRefGroup = 75C6DC192FF5EB664615F978FFB66B35 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 94BCD16A333E90AD0C2F07AE6FB3D29D /* Pods-Diary */, + 52B60EC2A583F24ACBB69C113F5488B9 /* SwiftLint */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + BCD7056F84D39331C909A81303287AE0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + ADD864007835BC006F689B86E00B4628 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9F9ED98D46A33EEC7D22FA8472E6B867 /* Pods-Diary-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + B4E9CB15B2C80F2FA6632BE3A29F4D44 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SwiftLint; + target = 52B60EC2A583F24ACBB69C113F5488B9 /* SwiftLint */; + targetProxy = 30E6EC47021682C037F08513CFF65D44 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 26EA5A9600226D2B7D8D25152A304F3B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7EAB1DA481EDDC005A251D3A5E6BE4CD /* SwiftLint.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_OBJC_WEAK = NO; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 4BC7450F9457737EE3E637BA155B56F7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + 8B5A46FF8D3C1289CDEE3BAFACABCD2A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + BDC0CA5C1E8BA9D1458D8EED751FD34F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 265D739AF741CF836D39D207D2C2EDE5 /* Pods-Diary.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-Diary/Pods-Diary-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Diary/Pods-Diary.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + E33F37054C18098516E9C610250CF2D5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = ABF16B16FE7DE4E56B49FC2D6C7CA936 /* Pods-Diary.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-Diary/Pods-Diary-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Diary/Pods-Diary.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + E9E1A48A750B946DE9877594C6E735E4 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3EC0124719FE8EF5FDDD72C26F8A2F57 /* SwiftLint.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_OBJC_WEAK = NO; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4BC7450F9457737EE3E637BA155B56F7 /* Debug */, + 8B5A46FF8D3C1289CDEE3BAFACABCD2A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8741FB36C60252E0472A071A841FF231 /* Build configuration list for PBXNativeTarget "Pods-Diary" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E33F37054C18098516E9C610250CF2D5 /* Debug */, + BDC0CA5C1E8BA9D1458D8EED751FD34F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + AE7B4FB01588B9E6DF09CB79FC7CE7BD /* Build configuration list for PBXAggregateTarget "SwiftLint" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E9E1A48A750B946DE9877594C6E735E4 /* Debug */, + 26EA5A9600226D2B7D8D25152A304F3B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; +} diff --git a/Pods/SwiftLint/LICENSE b/Pods/SwiftLint/LICENSE new file mode 100644 index 000000000..042037627 --- /dev/null +++ b/Pods/SwiftLint/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2020 Realm Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Pods/SwiftLint/swiftlint b/Pods/SwiftLint/swiftlint new file mode 100755 index 000000000..0f1e2fd09 Binary files /dev/null and b/Pods/SwiftLint/swiftlint differ diff --git a/Pods/Target Support Files/Pods-Diary/Pods-Diary-Info.plist b/Pods/Target Support Files/Pods-Diary/Pods-Diary-Info.plist new file mode 100644 index 000000000..19cf209d2 --- /dev/null +++ b/Pods/Target Support Files/Pods-Diary/Pods-Diary-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/Pods-Diary/Pods-Diary-acknowledgements.markdown b/Pods/Target Support Files/Pods-Diary/Pods-Diary-acknowledgements.markdown new file mode 100644 index 000000000..ca921c3d6 --- /dev/null +++ b/Pods/Target Support Files/Pods-Diary/Pods-Diary-acknowledgements.markdown @@ -0,0 +1,28 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## SwiftLint + +The MIT License (MIT) + +Copyright (c) 2020 Realm Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Generated by CocoaPods - https://cocoapods.org diff --git a/Pods/Target Support Files/Pods-Diary/Pods-Diary-acknowledgements.plist b/Pods/Target Support Files/Pods-Diary/Pods-Diary-acknowledgements.plist new file mode 100644 index 000000000..ddd65521c --- /dev/null +++ b/Pods/Target Support Files/Pods-Diary/Pods-Diary-acknowledgements.plist @@ -0,0 +1,60 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + The MIT License (MIT) + +Copyright (c) 2020 Realm Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + License + MIT + Title + SwiftLint + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Pods/Target Support Files/Pods-Diary/Pods-Diary-dummy.m b/Pods/Target Support Files/Pods-Diary/Pods-Diary-dummy.m new file mode 100644 index 000000000..861fac7d3 --- /dev/null +++ b/Pods/Target Support Files/Pods-Diary/Pods-Diary-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_Diary : NSObject +@end +@implementation PodsDummy_Pods_Diary +@end diff --git a/Pods/Target Support Files/Pods-Diary/Pods-Diary-umbrella.h b/Pods/Target Support Files/Pods-Diary/Pods-Diary-umbrella.h new file mode 100644 index 000000000..6231f0b83 --- /dev/null +++ b/Pods/Target Support Files/Pods-Diary/Pods-Diary-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_DiaryVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_DiaryVersionString[]; + diff --git a/Pods/Target Support Files/Pods-Diary/Pods-Diary.debug.xcconfig b/Pods/Target Support Files/Pods-Diary/Pods-Diary.debug.xcconfig new file mode 100644 index 000000000..1d2457638 --- /dev/null +++ b/Pods/Target Support Files/Pods-Diary/Pods-Diary.debug.xcconfig @@ -0,0 +1,9 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/Pods-Diary/Pods-Diary.modulemap b/Pods/Target Support Files/Pods-Diary/Pods-Diary.modulemap new file mode 100644 index 000000000..1d1b8194d --- /dev/null +++ b/Pods/Target Support Files/Pods-Diary/Pods-Diary.modulemap @@ -0,0 +1,6 @@ +framework module Pods_Diary { + umbrella header "Pods-Diary-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/Pods-Diary/Pods-Diary.release.xcconfig b/Pods/Target Support Files/Pods-Diary/Pods-Diary.release.xcconfig new file mode 100644 index 000000000..1d2457638 --- /dev/null +++ b/Pods/Target Support Files/Pods-Diary/Pods-Diary.release.xcconfig @@ -0,0 +1,9 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/SwiftLint/SwiftLint.debug.xcconfig b/Pods/Target Support Files/SwiftLint/SwiftLint.debug.xcconfig new file mode 100644 index 000000000..5238df584 --- /dev/null +++ b/Pods/Target Support Files/SwiftLint/SwiftLint.debug.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SwiftLint +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/SwiftLint +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/SwiftLint/SwiftLint.release.xcconfig b/Pods/Target Support Files/SwiftLint/SwiftLint.release.xcconfig new file mode 100644 index 000000000..5238df584 --- /dev/null +++ b/Pods/Target Support Files/SwiftLint/SwiftLint.release.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SwiftLint +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/SwiftLint +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/README.md b/README.md index 497819d76..d924c61b1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,317 @@ -## iOS 커리어 스타터 캠프 +# 📔 일기장 +## 🍀 소개 +>프로젝트 기간: 2023.8.28 ~ 2023.9.15 -### 일기장 프로젝트 저장소 +일기를 생성, 수정, 삭제할 수 있는 앱입니다. 현재 위치에 따라 오늘의 날씨 이모티콘이 함께 들어갑니다. + +
-- 이 저장소를 자신의 저장소로 fork하여 프로젝트를 진행합니다 -- 자신의 브랜치에 PR을 보내는지 꼭 확인한 후 PR을 보냅니다 +## 📖 목차 +1. [👨‍💻 팀원](#1.) +2. [📅 타임라인](#2.) +3. [👀 시각화된 프로젝트 구조](#3.) +4. [💻 실행 화면](#4.) +5. [🪄 핵심 경험](#5.) +6. [🧨 트러블 슈팅](#6.) +7. [📚 참고 링크](#7.) + +
+ +
+## 👨‍💻 팀원 +| Max | hamg | +| :--------: | :--------: | +| | | +|[Github Profile](https://github.com/maxhyunm)|[Github Profile](https://github.com/hemg2) | + + +
+ +
+## 📅 타임라인 +|날짜|내용| +|:--:|--| +|2023.08.28| `SwiftLint` 라이브러리 추가| +|2023.08.29| `SwiftLint` 조건 변경 | +|2023.08.30| `DiaryEntity` `CreateDiaryViewController `생성
`keyboard` `NotificationCenter` 생성 및 구현 | +|2023.09.01| `CoreData`: `Create` 구현| +|2023.09.05| `CoreData`: `UpDate`, `Delete` 구현
`Swipe` `share`, `delete` 구현
`AlertController` 생성 | +|2023.09.06| `CoreData`: `fetchDiary` 구현 | +|2023.09.07| 개인 학습 및 `README` 작성 | +|2023.09.10| `CoreDataError` 생성, 예외처리 추가
`AlertVC`로직수정, `Namespace`생성 | +|2023.09.13| `WeatherAPI`통신 진행
`WeatherIcon Cache` 구현
`CoreLocation` 생성
`Migration-DiaryV2` 구현 | + + +
+ +
+## 👀 시각화된 프로젝트 구조 +### FileTree + ├── Diary + │   ├── Protocol + │   │   ├── AlertDisplayble.swift + │   │   └── ShareDisplayable.swift + │   ├── Extension + │   │   └── DateFormatter+.swift + │   ├── Error + │   │   ├── APIError.swift + │   │   ├── CoreDataError.swift + │   │   └── DecodingError.swift + │   ├── Model + │   │   ├── CoreData + │   │   │   ├── CoreDataManager.swift + │   │   │   ├── Diary+CoreDataClass.swift + │   │   │   └── Diary+CoreDataProperties.swift + │   │   ├── DTO + │   │   │   ├── DecodingManager.swift + │   │   │   └── WeatherResult.swift + │   │   ├── ImageCache + │   │   │   └── ImageCachingManager.swift + │   │   └── Namespace + │   │   ├── AlertNamespace.swift + │   │   └── ButtonNamespace.swift + │   ├── Network + │   │   ├── NetworkConfiguration.swift + │   │   └── NetworkManager.swift + │   ├── Controller + │   │   ├── DiaryDetailViewController.swift + │   │   └── DiaryListViewController.swift + │   ├── View + │   │ └── DiaryListTableViewCell.swift + │   ├── App + │   │   ├── AppDelegate.swift + │   │   └── SceneDelegate.swift + │   ├── Assets.xcassets + │   ├── Info.plist + │   └── Diary.xcdatamodeld + ├── Diary.xcodeproj + └── README.md + +
+ +
+## 💻 실행 화면 + +| 새 일기 작성 | 일기 수정 | 일기 공유 | 일기 삭제 | +|:--:|:--:|:--:|:--:| +||||| + + +
+ +
+## 🪄 핵심 경험 +#### 🌟 CoreData를 활용한 데이터 저장 +일기 데이터를 위한 저장소로 CoreData를 활용하였습니다. +#### 🌟 MappingModel 파일을 활용한 CoreData Migration 진행 +CoreData의 버전 정보를 추가하고 이를 MappingModel로 연결하여 DB 변경사항에 대한 Migration을 진행하였습니다. +#### 🌟 Singleton 패턴을 활용한 CoreDataManager 구현 +데이터 처리를 위한 로직 전반을 Singleton 패턴으로 구현하여 앱 전역에서 활용 가능하도록 하였습니다. +#### 🌟 NotificationCenter를 활용한 키보드 인식 +키보드 활성화 여부에 따라 뷰의 크기를 변경하여 커서 위치가 가려지지 않도록 NotificationCenter를 활용하였습니다. +#### 🌟 여러 개의 생성자를 통한 상황별 데이터 전달 +상황에 따라 ViewController에서 다른 데이터를 표시해야 하는 경우에 대비해 생성자를 활용하였습니다. +#### 🌟 Protocol과 Extension을 활용한 코드 분리 +Alert, Swipe 등 별개의 작업으로 분리할 수 있는 내용들은 Protocol과 Extension을 통해 분리하였습니다. +#### 🌟 URLSessionDataTask를 활용한 NetworkManager 구현 +하나의 NetworkManager 타입을 구현하여 날씨 API 데이터 통신과 아이콘 이미지 관련 통신에 모두 활용하였습니다. + +
+ +
+## 🧨 트러블 슈팅 + +### 1️⃣ **반복적인 날짜 포매팅 처리** +🔒 **문제점**
+ 일기 리스트 화면과 새로운 일기를 생성하는 화면에서 모두 아래와 같이 날짜 포매팅을 사용해야 하는 것을 알 수 있었습니다. +```swift + private let formatter: DateFormatter = { + let formatter = DateFormatter() + formatter.locale = Locale(identifier: "ko_kr") + formatter.dateFormat = "yyyy년MM월dd일" + return formatter +}() +``` +동일한 코드가 두 개의 `ViewController`에서 반복되어 사용하고 있었으며 +반복되는 것을 막기 위해 해당 코드를 분리하고자 했습니다. +

+ +🔑 **해결방법**
+저장 프로퍼티가 아닌 메서드로 사용하여 재사용성을 높히게 되었습니다. +```swift +extension DateFormatter { + func formatToString(from date: Date, with format: String) -> String { + self.dateFormat = format + + return self.string(from: date) + } +} + +DateFormatter().formatToString(from: entity.createdAt, with: "YYYY년 MM월 dd일") +``` +
+ +### 2️⃣ **화면이 꺼질 때 자동 저장 처리** +🔒 **문제점**
+요구사항에 따르면 사용자가 화면을 벗어날 때마다 자동 저장을 진행해야 했습니다. 이를 구현하기 위해 처음에는 `CreateViewController`의 `viewWillDisappear` 메서드에서 저장처리를 진행할 수 있도록 작업했습니다. +```swift +override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + saveDiary() +} +``` +하지만 이렇게 하니 일기 삭제 처리를 한 뒤 뷰컨트롤러를 pop할 때에도 저장처리를 거치게 되어 오류가 발생하였습니다. +

+ +🔑 **해결방법**
+`TextView`가 수정될 때마다 뷰컨트롤러가 가지고 있는 일기 객체의 내용을 바꿔주고, 저장이 필요한 순간에 `saveContext` 처리만 진행할 수 있도록 아래와 같이 구현하였습니다. +```swift +func textViewDidChange(_ textView: UITextView) { + let contents = textView.text.split(separator: "\n") + guard !contents.isEmpty, + let title = contents.first else { return } + + let body = contents.dropFirst().joined(separator: "\n") + + diary.title = "\(title)" + diary.body = body +} +``` +
+ +### 3️⃣ **빈 일기가 저장되는 현상** +🔒 **문제점(1)**
+처음에는 키보드가 비활성화되면 무조건 내용을 저장하도록 구현을 하였습니다. 하지만 이렇게 하니, 신규 생성 버튼(+)을 누른 뒤 아무런 내용도 입력하지 않고 뒤로 가기 처리를 하면 제목과 내용이 모두 비어있는 일기가 생성이 되었습니다. +```swift +func textViewDidEndEditing(_ textView: UITextView) { + CoreDataManager.shared.saveContext() +} +``` +|빈일기 생성 화면| +|:--:| +|| + +

+ +🔑 **해결방법(1)**
+빈 일기가 생성되는것을 막기 위해 title 이 없을 경우 저장 되지 않게 진행하였습니다. +```swift +func textViewDidEndEditing(_ textView: UITextView) { + let contents = textView.text.split(separator: "\n") + guard !contents.isEmpty else { return } + + CoreDataManager.shared.saveContext() + } +``` +

+🔒 **문제점(2)**
+위의 처리를 통해 더 이상 데이터베이스에 빈 일기가 저장되지는 않았지만, saveContext 되지 않은 객체가 여전히 context 내부에 남아 일시적으로 빈 일기가 리스트에 보이는 현상이 생겼습니다. +```swift +func readCoreData() { + do { + diaryList = try container.viewContext.fetch(Diary.fetchRequest()) + tableView.reloadData() + } catch { + .... + } + } +``` +

+ +🔑 **해결방법(2)**
+fetch해 온 일기들 중에 title이 비어있는 건은 걸러낼 수 있도록 filter 처리를 추가하였습니다. +```swift + private func readCoreData() { + do { + let fetchedDiaries = try CoreDataManager.shared.fetchDiary() + diaryList = fetchedDiaries.filter { $0.title != nil } + tableView.reloadData() + } catch { + ..... + } + } +``` +

+ +### 4️⃣ **아이콘 이미지 통신** +🔒 **문제점**
+일기장 앱은 모든 셀이 서버통신을 통해 아이콘을 가지고 오도록 구현되어 있습니다. 하지만 날씨 아이콘은 몇 개의 정해진 아이콘을 반복하여 활용합니다. 따라서 동일한 이미지를 매번 통신을 통해 가져오는 것은 비효율적이라고 생각되었습니다. +

+ +🔑 **해결방법**
+한 번 활용된 이미지는 `NSCache`를 통해 캐싱 처리하여 바로 보여줄 수 있도록 구현하였습니다. + +```swift +class ImageCachingManager { + static let shared = NSCache() + ... +} +``` + +```swift +guard let image = UIImage(data: data) else { return } +DispatchQueue.main.async { + ImageCachingManager.shared.setObject(image, forKey: NSString(string: icon)) + self?.weatherIconImageView.image = image +} +``` +

+ +### 5️⃣ **CoreLocation** +🔒 **문제점 (1) - CoreLocation을 통해 정보를 받아오는 위치**
+ +실질적으로 Location 정보가 필요한 것은 `DiaryDetailViewController`에서 날씨 API를 호출할 때입니다. 때문에 처음에는 `DiaryDetailViewController`에서 활용 동의를 받고 위치 정보를 업데이트하도록 구현하려 하였습니다. 하지만 이렇게 하면 앱을 실행한 뒤 일기장 생성 화면에 넘어가서야 위치정보 활용 동의 창이 활성화되어 흐름상 어색해지고, 또 위치 정보가 제때 업데이트되지 않아 API 호출이 이루어지지 않는 등 다양한 문제가 발생했습니다. +

+ +🔑 **해결방법 (1)**
+위치 정보 업데이트 자체는 첫 화면인 `DiaryListViewController`에서 진행하고, `DiaryDetailViewController`에서는 API 통신에 필요한 위도, 경도 데이터만 넘겨받을 수 있도록 구현하였습니다. +```swift +let createDiaryView = DiaryDetailViewController(latitude: self.latitude, longitude: self.longitude) +self.navigationController?.pushViewController(createDiaryView, animated: true) +``` + +또한 위치정보 활용에 동의하지 않은 경우에도 일기 자체는 작성 가능하도록 구현하기 위해(날씨 이모티콘만 제외) 위도, 경도 데이터는 nil로도 전달될 수 있도록 하였습니다. + +```swift +init(latitude: Double?, longitude: Double?) { + self.diary = CoreDataManager.shared.createDiary() + self.isNew = true + self.latitude = latitude + self.longitude = longitude + + super.init(nibName: nil, bundle: nil) + fetchWeather() +} +``` +

+ +🔒 **문제점 (2) - 시뮬레이터의 위치 정보 설정**
+ +시뮬레이터로 `CoreLocation` 기능을 테스트하면 시뮬레이터 자체에 설정된 Location 정보에 따라 위치를 표시하게 됩니다. 따라서 이 설정이 None으로 되어있을 경우에는 위치가 정상적으로 불러와지지 않습니다. 이 사실을 간과하여 테스트 과정에서 많은 시행착오를 거쳤습니다. +

+ +🔑 **해결방법 (2)**
+ +Custom Location을 활용하여 정상적으로 테스트를 진행할 수 있었습니다.
+ +
+ + +
+## 📚 참고 링크 + +- [Apple Docs: Adaptivity and Layout](https://developer.apple.com/design/human-interface-guidelines/layout) +- [Apple Docs: DateFormatter](https://developer.apple.com/documentation/foundation/dateformatter) +- [Apple Docs: UITextView](https://developer.apple.com/documentation/uikit/uitextview) +- [Apple Docs: Core Data](https://developer.apple.com/documentation/coredata) +- [Apple Docs: Making Apps with Core Data](https://developer.apple.com/videos/play/wwdc2019/230/) +- [Apple Docs: NSFetchedResultsController](https://developer.apple.com/documentation/coredata/nsfetchedresultscontroller) +- [Apple Docs: UITextViewDelegate](https://developer.apple.com/documentation/uikit/uitextviewdelegate) +- [Apple Docs: UISwipeActionsConfiguration](https://developer.apple.com/documentation/uikit/uiswipeactionsconfiguration) +- [Apple Docs: CoreLocation](https://developer.apple.com/documentation/corelocation) +- [Apple Docs: Migrating your data model automatically](https://developer.apple.com/documentation/coredata/migrating_your_data_model_automatically) +- [Apple Docs: NSCache](https://openweathermap.org/current) +- [Open Weather API](https://openweathermap.org/current) + +
diff --git a/en.lproj/Localizable.strings b/en.lproj/Localizable.strings new file mode 100644 index 000000000..ecdc0fe51 --- /dev/null +++ b/en.lproj/Localizable.strings @@ -0,0 +1,29 @@ +"titleLabel" = "Diary"; +"moreOptions" = "More"; +"share" = "Share..."; +"delete" = "Delete"; +"cancel" = "Cancel"; +"confirm" = "Confirm"; +"networkError" = "Network Error"; +"deleteTitle" = "Really?"; +"deleteMessage" = "Are you sure you want to delete?"; +"unknownError" = "Unknown Error"; +"unknownErrorTitle" = "Unknown"; +"fileNotFound" = "File Not Found"; +"decodingFailure" = "Decoding Failure"; +"createFailureTitle" = "Error"; +"dataNotFoundTitle" = "Error"; +"saveFailureTitle" = "Error"; +"updateFailureTitle" = "Error"; +"deleteFailureTitle" = "Error"; +"createFailure" = "Create Failure"; +"dataNotFound" = "Data Not Found"; +"saveFailure" = "Save Failure"; +"updateFailure" = "Update Failure"; +"deleteFailure" = "Delete Failure"; +"invalidURL" = "Invalid URL"; +"requestFailure" = "Request Failure"; +"invalidData" = "Invalid Data."; +"dataTransferFailure" = "Data Transfer Failure"; +"invalidHTTPStatusCode" = "Invalide HTTP Status Code"; +"requestTimeOut" = "Request Time Out"; diff --git a/ko.lproj/Localizable.strings b/ko.lproj/Localizable.strings new file mode 100644 index 000000000..3bc5f214e --- /dev/null +++ b/ko.lproj/Localizable.strings @@ -0,0 +1,29 @@ +"titleLabel" = "일기장"; +"moreOptions" = "더보기"; +"share" = "공유하기"; +"delete" = "삭제"; +"cancel" = "취소"; +"confirm" = "확인"; +"networkError" = "네트워크 오류"; +"deleteTitle" = "진짜요?"; +"deleteMessage" = "정말로 삭제하시겠어요?"; +"unknownError" = "알 수 없는 오류입니다."; +"unknownErrorTitle" = "알 수 없는 오류"; +"fileNotFound" = "파일을 불러오지 못했습니다."; +"decodingFailure" = "파일을 변환하지 못했습니다."; +"createFailureTitle" = "생성 실패"; +"dataNotFoundTitle" = "읽기 실패"; +"saveFailureTitle" = "저장 실패"; +"updateFailureTitle" = "수정 실패"; +"deleteFailureTitle" = "삭제 실패"; +"createFailure" = "데이터를 생성하지 못했습니다."; +"dataNotFound" = "데이터를 찾지 못했습니다."; +"saveFailure" = "저장에 실패하였습니다."; +"updateFailure" = "수에 실패하였습니다."; +"deleteFailure" = "삭제에 실패하였습니다."; +"invalidURL" = "유효하지 않은 URL입니다."; +"requestFailure" = "요청에 실패했습니다."; +"invalidData" = "잘못된 데이터입니다."; +"dataTransferFailure" = "데이터 변환에 실패했습니다."; +"invalidHTTPStatusCode" = "잘못된 HTTP Status Code입니다."; +"requestTimeOut" = "요청시간이 초과되었습니다.";