diff --git a/.DS_Store b/.DS_Store index 963997f..6a5afbf 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/JH/.DS_Store b/JH/.DS_Store index 3075314..0cd3218 100644 Binary files a/JH/.DS_Store and b/JH/.DS_Store differ diff --git a/JH/Study2_Instagram_Light/Instagram_Light/Assets.xcassets/Data.dataset/Contents.json b/JH/Study2_Instagram_Light/Instagram_Light/Assets.xcassets/Data.dataset/Contents.json new file mode 100644 index 0000000..377a42c --- /dev/null +++ b/JH/Study2_Instagram_Light/Instagram_Light/Assets.xcassets/Data.dataset/Contents.json @@ -0,0 +1,11 @@ +{ + "data" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study2_Instagram_Light/Instagram_Light/ViewController/UserViewController.swift b/JH/Study2_Instagram_Light/Instagram_Light/ViewController/UserViewController.swift index bf1818b..4f598a9 100644 --- a/JH/Study2_Instagram_Light/Instagram_Light/ViewController/UserViewController.swift +++ b/JH/Study2_Instagram_Light/Instagram_Light/ViewController/UserViewController.swift @@ -14,7 +14,7 @@ public let userName = "JaehyeokLim" class UserViewController: UIViewController { - private let userCollectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) + let userCollectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) override func viewDidAppear(_ animated: Bool) { userCollectionView.reloadData() @@ -353,3 +353,5 @@ extension UserViewController: UICollectionViewDelegateFlowLayout { return 3 } } + + diff --git a/JH/Study3_ImagePicker/.DS_Store b/JH/Study3_ImagePicker/.DS_Store new file mode 100644 index 0000000..a3124f1 Binary files /dev/null and b/JH/Study3_ImagePicker/.DS_Store differ diff --git a/JH/Study3_ImagePicker/Podfile b/JH/Study3_ImagePicker/Podfile new file mode 100644 index 0000000..12ef5d9 --- /dev/null +++ b/JH/Study3_ImagePicker/Podfile @@ -0,0 +1,19 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +target 'Study3_ImagePicker' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + # Pods for Study3_ImagePicker + pod 'SnapKit', '~> 5.0.0' + target 'Study3_ImagePickerTests' do + inherit! :search_paths + # Pods for testing + end + + target 'Study3_ImagePickerUITests' do + # Pods for testing + end + +end diff --git a/JH/Study3_ImagePicker/Podfile.lock b/JH/Study3_ImagePicker/Podfile.lock new file mode 100644 index 0000000..fbe50d4 --- /dev/null +++ b/JH/Study3_ImagePicker/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - SnapKit (5.0.1) + +DEPENDENCIES: + - SnapKit (~> 5.0.0) + +SPEC REPOS: + trunk: + - SnapKit + +SPEC CHECKSUMS: + SnapKit: 97b92857e3df3a0c71833cce143274bf6ef8e5eb + +PODFILE CHECKSUM: 3f827d0c98fd113bc8afd5d848950fd5ecded5e7 + +COCOAPODS: 1.11.3 diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker.xcodeproj/project.pbxproj b/JH/Study3_ImagePicker/Study3_ImagePicker.xcodeproj/project.pbxproj new file mode 100644 index 0000000..70acd09 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker.xcodeproj/project.pbxproj @@ -0,0 +1,816 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + 4D11DEA53A5DEF20F7E49714 /* Pods_Study3_ImagePicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D254E4528694BBBE8FD2CAC9 /* Pods_Study3_ImagePicker.framework */; }; + 770AA4C94ED404191317A0DB /* Pods_Study3_ImagePicker_Study3_ImagePickerUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A410507AAFC1AF163F03834 /* Pods_Study3_ImagePicker_Study3_ImagePickerUITests.framework */; }; + C4451F5EF8CF0B69220861FF /* Pods_Study3_ImagePickerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6FFA646E344092D45E0E6419 /* Pods_Study3_ImagePickerTests.framework */; }; + FA1A76CA2867AF73002AC5CA /* SubViewCustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1A76C92867AF73002AC5CA /* SubViewCustomCell.swift */; }; + FA1A76CD2867AFEC002AC5CA /* SubModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1A76CC2867AFEC002AC5CA /* SubModel.swift */; }; + FA1A76CF28685158002AC5CA /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1A76CE28685158002AC5CA /* MainViewController.swift */; }; + FA1A76D128688A20002AC5CA /* MainViewCustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1A76D028688A20002AC5CA /* MainViewCustomCell.swift */; }; + FA1A76D328688A29002AC5CA /* MainModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1A76D228688A29002AC5CA /* MainModel.swift */; }; + FA1A76D9286B5D76002AC5CA /* DetailViewContoller.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1A76D8286B5D76002AC5CA /* DetailViewContoller.swift */; }; + FA1A76DB286B622B002AC5CA /* DetailViewCustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA1A76DA286B622B002AC5CA /* DetailViewCustomCell.swift */; }; + FA2DF131286795F700F2E060 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2DF130286795F700F2E060 /* AppDelegate.swift */; }; + FA2DF133286795F700F2E060 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2DF132286795F700F2E060 /* SceneDelegate.swift */; }; + FA2DF135286795F700F2E060 /* SubViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2DF134286795F700F2E060 /* SubViewController.swift */; }; + FA2DF13B286795F700F2E060 /* Study3_ImagePicker.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = FA2DF139286795F700F2E060 /* Study3_ImagePicker.xcdatamodeld */; }; + FA2DF13D286795F800F2E060 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FA2DF13C286795F800F2E060 /* Assets.xcassets */; }; + FA2DF140286795F800F2E060 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FA2DF13E286795F800F2E060 /* LaunchScreen.storyboard */; }; + FA2DF14B286795F800F2E060 /* Study3_ImagePickerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2DF14A286795F800F2E060 /* Study3_ImagePickerTests.swift */; }; + FA2DF155286795F800F2E060 /* Study3_ImagePickerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2DF154286795F800F2E060 /* Study3_ImagePickerUITests.swift */; }; + FA2DF157286795F800F2E060 /* Study3_ImagePickerUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2DF156286795F800F2E060 /* Study3_ImagePickerUITestsLaunchTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + FA2DF147286795F800F2E060 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FA2DF125286795F700F2E060 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FA2DF12C286795F700F2E060; + remoteInfo = Study3_ImagePicker; + }; + FA2DF151286795F800F2E060 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FA2DF125286795F700F2E060 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FA2DF12C286795F700F2E060; + remoteInfo = Study3_ImagePicker; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 00459A9CDCA97697F5886A79 /* Pods-Study3_ImagePicker-Study3_ImagePickerUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Study3_ImagePicker-Study3_ImagePickerUITests.release.xcconfig"; path = "Target Support Files/Pods-Study3_ImagePicker-Study3_ImagePickerUITests/Pods-Study3_ImagePicker-Study3_ImagePickerUITests.release.xcconfig"; sourceTree = ""; }; + 16034C68B3E742F044A565AB /* Pods-Study3_ImagePickerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Study3_ImagePickerTests.debug.xcconfig"; path = "Target Support Files/Pods-Study3_ImagePickerTests/Pods-Study3_ImagePickerTests.debug.xcconfig"; sourceTree = ""; }; + 3079D34171E673D4D49ED269 /* Pods-Study3_ImagePicker.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Study3_ImagePicker.release.xcconfig"; path = "Target Support Files/Pods-Study3_ImagePicker/Pods-Study3_ImagePicker.release.xcconfig"; sourceTree = ""; }; + 5A410507AAFC1AF163F03834 /* Pods_Study3_ImagePicker_Study3_ImagePickerUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Study3_ImagePicker_Study3_ImagePickerUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6FFA646E344092D45E0E6419 /* Pods_Study3_ImagePickerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Study3_ImagePickerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 935CD4F4B1386A0BF9E54F73 /* Pods-Study3_ImagePickerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Study3_ImagePickerTests.release.xcconfig"; path = "Target Support Files/Pods-Study3_ImagePickerTests/Pods-Study3_ImagePickerTests.release.xcconfig"; sourceTree = ""; }; + CDAFF7626EEFABD3DD3AD9DE /* Pods-Study3_ImagePicker-Study3_ImagePickerUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Study3_ImagePicker-Study3_ImagePickerUITests.debug.xcconfig"; path = "Target Support Files/Pods-Study3_ImagePicker-Study3_ImagePickerUITests/Pods-Study3_ImagePicker-Study3_ImagePickerUITests.debug.xcconfig"; sourceTree = ""; }; + D254E4528694BBBE8FD2CAC9 /* Pods_Study3_ImagePicker.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Study3_ImagePicker.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E7CE6295AF7919F2A3AF78FD /* Pods-Study3_ImagePicker.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Study3_ImagePicker.debug.xcconfig"; path = "Target Support Files/Pods-Study3_ImagePicker/Pods-Study3_ImagePicker.debug.xcconfig"; sourceTree = ""; }; + FA1A76C92867AF73002AC5CA /* SubViewCustomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubViewCustomCell.swift; sourceTree = ""; }; + FA1A76CC2867AFEC002AC5CA /* SubModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubModel.swift; sourceTree = ""; }; + FA1A76CE28685158002AC5CA /* MainViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; }; + FA1A76D028688A20002AC5CA /* MainViewCustomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewCustomCell.swift; sourceTree = ""; }; + FA1A76D228688A29002AC5CA /* MainModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainModel.swift; sourceTree = ""; }; + FA1A76D8286B5D76002AC5CA /* DetailViewContoller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailViewContoller.swift; sourceTree = ""; }; + FA1A76DA286B622B002AC5CA /* DetailViewCustomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailViewCustomCell.swift; sourceTree = ""; }; + FA2DF12D286795F700F2E060 /* Study3_ImagePicker.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Study3_ImagePicker.app; sourceTree = BUILT_PRODUCTS_DIR; }; + FA2DF130286795F700F2E060 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + FA2DF132286795F700F2E060 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + FA2DF134286795F700F2E060 /* SubViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubViewController.swift; sourceTree = ""; }; + FA2DF13A286795F700F2E060 /* Study3_ImagePicker.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Study3_ImagePicker.xcdatamodel; sourceTree = ""; }; + FA2DF13C286795F800F2E060 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + FA2DF13F286795F800F2E060 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + FA2DF141286795F800F2E060 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + FA2DF146286795F800F2E060 /* Study3_ImagePickerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Study3_ImagePickerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + FA2DF14A286795F800F2E060 /* Study3_ImagePickerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Study3_ImagePickerTests.swift; sourceTree = ""; }; + FA2DF150286795F800F2E060 /* Study3_ImagePickerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Study3_ImagePickerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + FA2DF154286795F800F2E060 /* Study3_ImagePickerUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Study3_ImagePickerUITests.swift; sourceTree = ""; }; + FA2DF156286795F800F2E060 /* Study3_ImagePickerUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Study3_ImagePickerUITestsLaunchTests.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + FA2DF12A286795F700F2E060 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D11DEA53A5DEF20F7E49714 /* Pods_Study3_ImagePicker.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA2DF143286795F800F2E060 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C4451F5EF8CF0B69220861FF /* Pods_Study3_ImagePickerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA2DF14D286795F800F2E060 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 770AA4C94ED404191317A0DB /* Pods_Study3_ImagePicker_Study3_ImagePickerUITests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + A12380896CE2FE38A04B6713 /* Frameworks */ = { + isa = PBXGroup; + children = ( + D254E4528694BBBE8FD2CAC9 /* Pods_Study3_ImagePicker.framework */, + 5A410507AAFC1AF163F03834 /* Pods_Study3_ImagePicker_Study3_ImagePickerUITests.framework */, + 6FFA646E344092D45E0E6419 /* Pods_Study3_ImagePickerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + E1694C28BF56C7B2EC6B09DE /* Pods */ = { + isa = PBXGroup; + children = ( + E7CE6295AF7919F2A3AF78FD /* Pods-Study3_ImagePicker.debug.xcconfig */, + 3079D34171E673D4D49ED269 /* Pods-Study3_ImagePicker.release.xcconfig */, + CDAFF7626EEFABD3DD3AD9DE /* Pods-Study3_ImagePicker-Study3_ImagePickerUITests.debug.xcconfig */, + 00459A9CDCA97697F5886A79 /* Pods-Study3_ImagePicker-Study3_ImagePickerUITests.release.xcconfig */, + 16034C68B3E742F044A565AB /* Pods-Study3_ImagePickerTests.debug.xcconfig */, + 935CD4F4B1386A0BF9E54F73 /* Pods-Study3_ImagePickerTests.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + FA1A76C82867AF51002AC5CA /* Cell */ = { + isa = PBXGroup; + children = ( + FA1A76C92867AF73002AC5CA /* SubViewCustomCell.swift */, + FA1A76D028688A20002AC5CA /* MainViewCustomCell.swift */, + FA1A76DA286B622B002AC5CA /* DetailViewCustomCell.swift */, + ); + path = Cell; + sourceTree = ""; + }; + FA1A76CB2867AFB1002AC5CA /* Model */ = { + isa = PBXGroup; + children = ( + FA1A76CC2867AFEC002AC5CA /* SubModel.swift */, + FA1A76D228688A29002AC5CA /* MainModel.swift */, + ); + path = Model; + sourceTree = ""; + }; + FA2DF124286795F700F2E060 = { + isa = PBXGroup; + children = ( + FA2DF12F286795F700F2E060 /* Study3_ImagePicker */, + FA2DF149286795F800F2E060 /* Study3_ImagePickerTests */, + FA2DF153286795F800F2E060 /* Study3_ImagePickerUITests */, + FA2DF12E286795F700F2E060 /* Products */, + E1694C28BF56C7B2EC6B09DE /* Pods */, + A12380896CE2FE38A04B6713 /* Frameworks */, + ); + sourceTree = ""; + }; + FA2DF12E286795F700F2E060 /* Products */ = { + isa = PBXGroup; + children = ( + FA2DF12D286795F700F2E060 /* Study3_ImagePicker.app */, + FA2DF146286795F800F2E060 /* Study3_ImagePickerTests.xctest */, + FA2DF150286795F800F2E060 /* Study3_ImagePickerUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + FA2DF12F286795F700F2E060 /* Study3_ImagePicker */ = { + isa = PBXGroup; + children = ( + FA2DF1632867985D00F2E060 /* ViewController */, + FA1A76C82867AF51002AC5CA /* Cell */, + FA1A76CB2867AFB1002AC5CA /* Model */, + FA2DF130286795F700F2E060 /* AppDelegate.swift */, + FA2DF132286795F700F2E060 /* SceneDelegate.swift */, + FA2DF13C286795F800F2E060 /* Assets.xcassets */, + FA2DF13E286795F800F2E060 /* LaunchScreen.storyboard */, + FA2DF141286795F800F2E060 /* Info.plist */, + FA2DF139286795F700F2E060 /* Study3_ImagePicker.xcdatamodeld */, + ); + path = Study3_ImagePicker; + sourceTree = ""; + }; + FA2DF149286795F800F2E060 /* Study3_ImagePickerTests */ = { + isa = PBXGroup; + children = ( + FA2DF14A286795F800F2E060 /* Study3_ImagePickerTests.swift */, + ); + path = Study3_ImagePickerTests; + sourceTree = ""; + }; + FA2DF153286795F800F2E060 /* Study3_ImagePickerUITests */ = { + isa = PBXGroup; + children = ( + FA2DF154286795F800F2E060 /* Study3_ImagePickerUITests.swift */, + FA2DF156286795F800F2E060 /* Study3_ImagePickerUITestsLaunchTests.swift */, + ); + path = Study3_ImagePickerUITests; + sourceTree = ""; + }; + FA2DF1632867985D00F2E060 /* ViewController */ = { + isa = PBXGroup; + children = ( + FA2DF134286795F700F2E060 /* SubViewController.swift */, + FA1A76CE28685158002AC5CA /* MainViewController.swift */, + FA1A76D8286B5D76002AC5CA /* DetailViewContoller.swift */, + ); + path = ViewController; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + FA2DF12C286795F700F2E060 /* Study3_ImagePicker */ = { + isa = PBXNativeTarget; + buildConfigurationList = FA2DF15A286795F800F2E060 /* Build configuration list for PBXNativeTarget "Study3_ImagePicker" */; + buildPhases = ( + DDC540FE8726EA71FF28E1B7 /* [CP] Check Pods Manifest.lock */, + FA2DF129286795F700F2E060 /* Sources */, + FA2DF12A286795F700F2E060 /* Frameworks */, + FA2DF12B286795F700F2E060 /* Resources */, + 90D5F21BBD179B98821C4BB4 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Study3_ImagePicker; + productName = Study3_ImagePicker; + productReference = FA2DF12D286795F700F2E060 /* Study3_ImagePicker.app */; + productType = "com.apple.product-type.application"; + }; + FA2DF145286795F800F2E060 /* Study3_ImagePickerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = FA2DF15D286795F800F2E060 /* Build configuration list for PBXNativeTarget "Study3_ImagePickerTests" */; + buildPhases = ( + A4E53A167B709874DF0D975F /* [CP] Check Pods Manifest.lock */, + FA2DF142286795F800F2E060 /* Sources */, + FA2DF143286795F800F2E060 /* Frameworks */, + FA2DF144286795F800F2E060 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + FA2DF148286795F800F2E060 /* PBXTargetDependency */, + ); + name = Study3_ImagePickerTests; + productName = Study3_ImagePickerTests; + productReference = FA2DF146286795F800F2E060 /* Study3_ImagePickerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + FA2DF14F286795F800F2E060 /* Study3_ImagePickerUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = FA2DF160286795F800F2E060 /* Build configuration list for PBXNativeTarget "Study3_ImagePickerUITests" */; + buildPhases = ( + 0204F762219303F0413829FC /* [CP] Check Pods Manifest.lock */, + FA2DF14C286795F800F2E060 /* Sources */, + FA2DF14D286795F800F2E060 /* Frameworks */, + FA2DF14E286795F800F2E060 /* Resources */, + B932C8AE1397D5DFE3AD4B38 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + FA2DF152286795F800F2E060 /* PBXTargetDependency */, + ); + name = Study3_ImagePickerUITests; + productName = Study3_ImagePickerUITests; + productReference = FA2DF150286795F800F2E060 /* Study3_ImagePickerUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + FA2DF125286795F700F2E060 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1330; + LastUpgradeCheck = 1330; + TargetAttributes = { + FA2DF12C286795F700F2E060 = { + CreatedOnToolsVersion = 13.3; + }; + FA2DF145286795F800F2E060 = { + CreatedOnToolsVersion = 13.3; + TestTargetID = FA2DF12C286795F700F2E060; + }; + FA2DF14F286795F800F2E060 = { + CreatedOnToolsVersion = 13.3; + TestTargetID = FA2DF12C286795F700F2E060; + }; + }; + }; + buildConfigurationList = FA2DF128286795F700F2E060 /* Build configuration list for PBXProject "Study3_ImagePicker" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = FA2DF124286795F700F2E060; + productRefGroup = FA2DF12E286795F700F2E060 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + FA2DF12C286795F700F2E060 /* Study3_ImagePicker */, + FA2DF145286795F800F2E060 /* Study3_ImagePickerTests */, + FA2DF14F286795F800F2E060 /* Study3_ImagePickerUITests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + FA2DF12B286795F700F2E060 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FA2DF140286795F800F2E060 /* LaunchScreen.storyboard in Resources */, + FA2DF13D286795F800F2E060 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA2DF144286795F800F2E060 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA2DF14E286795F800F2E060 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 0204F762219303F0413829FC /* [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-Study3_ImagePicker-Study3_ImagePickerUITests-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; + }; + 90D5F21BBD179B98821C4BB4 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Study3_ImagePicker/Pods-Study3_ImagePicker-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Study3_ImagePicker/Pods-Study3_ImagePicker-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Study3_ImagePicker/Pods-Study3_ImagePicker-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + A4E53A167B709874DF0D975F /* [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-Study3_ImagePickerTests-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; + }; + B932C8AE1397D5DFE3AD4B38 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Study3_ImagePicker-Study3_ImagePickerUITests/Pods-Study3_ImagePicker-Study3_ImagePickerUITests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Study3_ImagePicker-Study3_ImagePickerUITests/Pods-Study3_ImagePicker-Study3_ImagePickerUITests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Study3_ImagePicker-Study3_ImagePickerUITests/Pods-Study3_ImagePicker-Study3_ImagePickerUITests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + DDC540FE8726EA71FF28E1B7 /* [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-Study3_ImagePicker-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; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + FA2DF129286795F700F2E060 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FA1A76CF28685158002AC5CA /* MainViewController.swift in Sources */, + FA2DF135286795F700F2E060 /* SubViewController.swift in Sources */, + FA1A76D9286B5D76002AC5CA /* DetailViewContoller.swift in Sources */, + FA2DF131286795F700F2E060 /* AppDelegate.swift in Sources */, + FA1A76CD2867AFEC002AC5CA /* SubModel.swift in Sources */, + FA2DF133286795F700F2E060 /* SceneDelegate.swift in Sources */, + FA1A76D328688A29002AC5CA /* MainModel.swift in Sources */, + FA1A76CA2867AF73002AC5CA /* SubViewCustomCell.swift in Sources */, + FA1A76D128688A20002AC5CA /* MainViewCustomCell.swift in Sources */, + FA2DF13B286795F700F2E060 /* Study3_ImagePicker.xcdatamodeld in Sources */, + FA1A76DB286B622B002AC5CA /* DetailViewCustomCell.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA2DF142286795F800F2E060 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FA2DF14B286795F800F2E060 /* Study3_ImagePickerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA2DF14C286795F800F2E060 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FA2DF157286795F800F2E060 /* Study3_ImagePickerUITestsLaunchTests.swift in Sources */, + FA2DF155286795F800F2E060 /* Study3_ImagePickerUITests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + FA2DF148286795F800F2E060 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FA2DF12C286795F700F2E060 /* Study3_ImagePicker */; + targetProxy = FA2DF147286795F800F2E060 /* PBXContainerItemProxy */; + }; + FA2DF152286795F800F2E060 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FA2DF12C286795F700F2E060 /* Study3_ImagePicker */; + targetProxy = FA2DF151286795F800F2E060 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + FA2DF13E286795F800F2E060 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + FA2DF13F286795F800F2E060 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + FA2DF158286795F800F2E060 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_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 = ( + "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 = 15.4; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + FA2DF159286795F800F2E060 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_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_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 = 15.4; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + FA2DF15B286795F800F2E060 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E7CE6295AF7919F2A3AF78FD /* Pods-Study3_ImagePicker.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6578S57CDT; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = Study3_ImagePicker/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "Jaehyeoklim.Study3-ImagePicker"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + FA2DF15C286795F800F2E060 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3079D34171E673D4D49ED269 /* Pods-Study3_ImagePicker.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6578S57CDT; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = Study3_ImagePicker/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "Jaehyeoklim.Study3-ImagePicker"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + FA2DF15E286795F800F2E060 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 16034C68B3E742F044A565AB /* Pods-Study3_ImagePickerTests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6578S57CDT; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.4; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "Jaehyeoklim.Study3-ImagePickerTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Study3_ImagePicker.app/Study3_ImagePicker"; + }; + name = Debug; + }; + FA2DF15F286795F800F2E060 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 935CD4F4B1386A0BF9E54F73 /* Pods-Study3_ImagePickerTests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6578S57CDT; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.4; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "Jaehyeoklim.Study3-ImagePickerTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Study3_ImagePicker.app/Study3_ImagePicker"; + }; + name = Release; + }; + FA2DF161286795F800F2E060 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CDAFF7626EEFABD3DD3AD9DE /* Pods-Study3_ImagePicker-Study3_ImagePickerUITests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6578S57CDT; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "Jaehyeoklim.Study3-ImagePickerUITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = Study3_ImagePicker; + }; + name = Debug; + }; + FA2DF162286795F800F2E060 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 00459A9CDCA97697F5886A79 /* Pods-Study3_ImagePicker-Study3_ImagePickerUITests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6578S57CDT; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "Jaehyeoklim.Study3-ImagePickerUITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = Study3_ImagePicker; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + FA2DF128286795F700F2E060 /* Build configuration list for PBXProject "Study3_ImagePicker" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FA2DF158286795F800F2E060 /* Debug */, + FA2DF159286795F800F2E060 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FA2DF15A286795F800F2E060 /* Build configuration list for PBXNativeTarget "Study3_ImagePicker" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FA2DF15B286795F800F2E060 /* Debug */, + FA2DF15C286795F800F2E060 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FA2DF15D286795F800F2E060 /* Build configuration list for PBXNativeTarget "Study3_ImagePickerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FA2DF15E286795F800F2E060 /* Debug */, + FA2DF15F286795F800F2E060 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FA2DF160286795F800F2E060 /* Build configuration list for PBXNativeTarget "Study3_ImagePickerUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FA2DF161286795F800F2E060 /* Debug */, + FA2DF162286795F800F2E060 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCVersionGroup section */ + FA2DF139286795F700F2E060 /* Study3_ImagePicker.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + FA2DF13A286795F700F2E060 /* Study3_ImagePicker.xcdatamodel */, + ); + currentVersion = FA2DF13A286795F700F2E060 /* Study3_ImagePicker.xcdatamodel */; + path = Study3_ImagePicker.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ + }; + rootObject = FA2DF125286795F700F2E060 /* Project object */; +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/JH/Study3_ImagePicker/Study3_ImagePicker.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/JH/Study3_ImagePicker/Study3_ImagePicker.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker.xcodeproj/xcshareddata/xcschemes/Study3_ImagePicker.xcscheme b/JH/Study3_ImagePicker/Study3_ImagePicker.xcodeproj/xcshareddata/xcschemes/Study3_ImagePicker.xcscheme new file mode 100644 index 0000000..c4ade96 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker.xcodeproj/xcshareddata/xcschemes/Study3_ImagePicker.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker.xcworkspace/contents.xcworkspacedata b/JH/Study3_ImagePicker/Study3_ImagePicker.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..fb5c16e --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/JH/Study3_ImagePicker/Study3_ImagePicker.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/AppDelegate.swift b/JH/Study3_ImagePicker/Study3_ImagePicker/AppDelegate.swift new file mode 100644 index 0000000..9077de8 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/AppDelegate.swift @@ -0,0 +1,81 @@ +// +// AppDelegate.swift +// Study3_ImagePicker +// +// Created by Jaehyeok Lim on 2022/06/26. +// + +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: "Study3_ImagePicker") + 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/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/AccentColor.colorset/Contents.json b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/AppIcon.appiconset/Contents.json b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..9221b9b --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/Contents.json b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/backgroundColor.colorset/Contents.json b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/backgroundColor.colorset/Contents.json new file mode 100644 index 0000000..737e910 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/backgroundColor.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.000", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/commonTextColor.colorset/Contents.json b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/commonTextColor.colorset/Contents.json new file mode 100644 index 0000000..76b961c --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/commonTextColor.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.000", + "red" : "0.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/testImage.imageset/Contents.json b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/testImage.imageset/Contents.json new file mode 100644 index 0000000..c68cb9e --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/testImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "KakaoTalk_Photo_2022-04-26-19-01-21.jpeg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "KakaoTalk_Photo_2022-04-26-19-01-22.jpeg", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "KakaoTalk_Photo_2022-04-26-19-01-23.jpeg", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/testImage.imageset/KakaoTalk_Photo_2022-04-26-19-01-21.jpeg b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/testImage.imageset/KakaoTalk_Photo_2022-04-26-19-01-21.jpeg new file mode 100644 index 0000000..90f153e Binary files /dev/null and b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/testImage.imageset/KakaoTalk_Photo_2022-04-26-19-01-21.jpeg differ diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/testImage.imageset/KakaoTalk_Photo_2022-04-26-19-01-22.jpeg b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/testImage.imageset/KakaoTalk_Photo_2022-04-26-19-01-22.jpeg new file mode 100644 index 0000000..90f153e Binary files /dev/null and b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/testImage.imageset/KakaoTalk_Photo_2022-04-26-19-01-22.jpeg differ diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/testImage.imageset/KakaoTalk_Photo_2022-04-26-19-01-23.jpeg b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/testImage.imageset/KakaoTalk_Photo_2022-04-26-19-01-23.jpeg new file mode 100644 index 0000000..90f153e Binary files /dev/null and b/JH/Study3_ImagePicker/Study3_ImagePicker/Assets.xcassets/testImage.imageset/KakaoTalk_Photo_2022-04-26-19-01-23.jpeg differ diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Base.lproj/LaunchScreen.storyboard b/JH/Study3_ImagePicker/Study3_ImagePicker/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..865e932 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Cell/DetailViewCustomCell.swift b/JH/Study3_ImagePicker/Study3_ImagePicker/Cell/DetailViewCustomCell.swift new file mode 100644 index 0000000..b209ac9 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Cell/DetailViewCustomCell.swift @@ -0,0 +1,127 @@ +// +// DetailViewCustomCell.swift +// Study3_ImagePicker +// +// Created by Jaehyeok Lim on 2022/06/29. +// + +import UIKit +import SnapKit + +class DetailViewCustomCell: UICollectionViewCell { + + static let identifier = "DetailViewCustomCell" + + lazy var scrollView: UIScrollView = { + let scrollView = UIScrollView() + let scrollViewList: [UIView] = [detailViewImage, closeButton, currentAndTotalImageIndex] + + for view in scrollViewList { + scrollView.addSubview(view) + } + + scrollView.delegate = self + scrollView.minimumZoomScale = 1.0 + scrollView.maximumZoomScale = 6.0 + + return scrollView + }() + + let detailViewImage: UIImageView = { + let detailViewImage = UIImageView() + + detailViewImage.image = UIImage(named: "testImage") + detailViewImage.contentMode = .scaleAspectFit + + return detailViewImage + }() + + let closeButton: UIButton = { + let closeButton = UIButton() + + closeButton.setImage(UIImage(systemName: "xmark"), for: .normal) + closeButton.contentVerticalAlignment = .fill + closeButton.contentHorizontalAlignment = .fill + + return closeButton + }() + + let currentAndTotalImageIndex: UILabel = { + let currentAndTotalImageIndex = UILabel() + + currentAndTotalImageIndex.textColor = .white + currentAndTotalImageIndex.font = UIFont.systemFont(ofSize: 20) + + return currentAndTotalImageIndex + }() + + private func setConstraint() { + contentView.backgroundColor = UIColor.black + + contentView.addSubview(scrollView) + + detailViewImage.snp.makeConstraints { make in + make.height.equalTo(scrollView) + make.width.equalTo(scrollView) + } + + closeButton.snp.makeConstraints { make in + make.top.equalTo(contentView).offset(70) + make.leading.equalTo(contentView).offset(30) + make.size.equalTo(CGSize(width: 28, height: 26)) + } + + currentAndTotalImageIndex.snp.makeConstraints { make in + make.top.equalTo(closeButton).offset(5) + make.leading.equalTo(contentView).offset(180) + } +// + scrollView.snp.makeConstraints { make in + make.top.equalToSuperview() + make.leading.equalToSuperview() + make.right.equalToSuperview() + make.bottom.equalToSuperview() + } + + closeButton.addTarget(DetailViewController.closeButtonAction(_:), action: #selector(DetailViewController.closeButtonAction(_:)), for: .touchUpInside) + } + + func transfortImage(image: UIImage) { + detailViewImage.image = image + } + + func transfortLabel(currentImageIndex: String, totalImageIndex: String) { + currentAndTotalImageIndex.text = currentImageIndex + " / " + totalImageIndex + } + + override init(frame: CGRect) { + super.init(frame: frame) + setConstraint() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +extension DetailViewCustomCell: UIScrollViewDelegate { + func viewForZooming(in scrollView: UIScrollView) -> UIView? { + return detailViewImage + } + + func scrollViewDidZoom(_ scrollView: UIScrollView) { + if scrollView.zoomScale > 0.1 { + if let image = detailViewImage.image { + let ratioW = detailViewImage.frame.width / image.size.width + let ratioH = detailViewImage.frame.height / image.size.height + let ratio = ratioW < ratioH ? ratioW:ratioH + let newWidth = image.size.width*ratio + let newHeight = image.size.height*ratio + let left = 0.5 * (newWidth * scrollView.zoomScale > detailViewImage.frame.width ? (newWidth - detailViewImage.frame.width) : (scrollView.frame.width - scrollView.contentSize.width)) + let top = 0.5 * (newHeight * scrollView.zoomScale > detailViewImage.frame.height ? (newHeight - detailViewImage.frame.height) : (scrollView.frame.height - scrollView.contentSize.height)) + + scrollView.contentInset = UIEdgeInsets(top: top, left: left, bottom: top, right: left) + } + } + } +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Cell/MainViewCustomCell.swift b/JH/Study3_ImagePicker/Study3_ImagePicker/Cell/MainViewCustomCell.swift new file mode 100644 index 0000000..814e825 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Cell/MainViewCustomCell.swift @@ -0,0 +1,111 @@ +// +// MainViewCustomCell.swift +// Study3_ImagePicker +// +// Created by Jaehyeok Lim on 2022/06/26. +// + +import UIKit +import SnapKit + +class MainViewCustomCell: UICollectionViewCell { + static let identifier = "MainViewCustomCell" + + let albumTitleImage: UIButton = { + let albumTitleImage = UIButton() + + albumTitleImage.contentHorizontalAlignment = .fill + albumTitleImage.contentVerticalAlignment = .fill + + return albumTitleImage + }() + + let albumTitleLabel: UILabel = { + let albumTitleLabel = UILabel() + + albumTitleLabel.text = "" + albumTitleLabel.font = UIFont.boldSystemFont(ofSize: 20) + albumTitleLabel.textColor = UIColor.commonTextColor + + return albumTitleLabel + }() + + let albumIndexLabel: UILabel = { + let albumIndexLabel = UILabel() + + albumIndexLabel.text = "" + albumIndexLabel.font = UIFont.boldSystemFont(ofSize: 20) + albumIndexLabel.textColor = UIColor.systemBlue + + return albumIndexLabel + }() + + let hashTagIcon: UILabel = { + let hashTagIcon = UILabel() + + hashTagIcon.text = "#" + hashTagIcon.font = UIFont.boldSystemFont(ofSize: 20) + hashTagIcon.textColor = UIColor.systemBlue + + return hashTagIcon + }() + + private func setConstraint() { + contentView.backgroundColor = UIColor.backgroundColor + + let viewList: [UIView] = [albumTitleImage, albumTitleLabel, albumIndexLabel, hashTagIcon] + + for view in viewList { + contentView.addSubview(view) + } + + albumTitleImage.snp.makeConstraints { make in + make.top.equalToSuperview() + make.leading.equalToSuperview() + make.right.equalToSuperview() + make.bottom.equalToSuperview() + } + + albumTitleLabel.snp.makeConstraints { make in + make.top.equalTo(albumTitleImage).offset(-30) + make.leading.equalTo(albumTitleImage).offset(30) + } + + albumIndexLabel.snp.makeConstraints { make in + make.top.equalTo(albumTitleLabel) + make.leading.equalTo(albumTitleLabel).offset(-14) + } + + hashTagIcon.snp.makeConstraints { make in + make.top.equalTo(albumIndexLabel) + make.leading.equalTo(albumIndexLabel).offset(-12) + } + + albumTitleImage.addTarget(MainViewController.albumTitleImageAction, action: #selector(MainViewController.albumTitleImageAction(_:)), for: .touchUpInside) + } + + func transfortImage(image: UIImage) { + albumTitleImage.setImage(image, for: .normal) + } + + func transfortTitleLabel(titleTexts: String) { + albumTitleLabel.text = titleTexts + } + + func transfortIndexLabel(indexTexts: String) { + albumIndexLabel.text = indexTexts + } + + func transfortHashTagIcon(iconTexts: String) { + hashTagIcon.text = iconTexts + } + + override init(frame: CGRect) { + super.init(frame: frame) + setConstraint() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Cell/SubViewCustomCell.swift b/JH/Study3_ImagePicker/Study3_ImagePicker/Cell/SubViewCustomCell.swift new file mode 100644 index 0000000..5da1716 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Cell/SubViewCustomCell.swift @@ -0,0 +1,49 @@ +// +// SubViewCustomCell.swift +// Study3_ImagePicker +// +// Created by Jaehyeok Lim on 2022/06/26. +// + +import UIKit +import SnapKit + +class SubViewCustomCell: UICollectionViewCell { + static let identifier = "SubViewCustomCell" + + let subViewImage: UIButton = { + let subViewImage = UIButton() + + subViewImage.contentHorizontalAlignment = .fill + subViewImage.contentVerticalAlignment = .fill + + return subViewImage + }() + + private func setConstraint() { + contentView.backgroundColor = UIColor.backgroundColor + addSubview(subViewImage) + + subViewImage.snp.makeConstraints { make in + make.top.equalToSuperview() + make.leading.equalToSuperview() + make.right.equalToSuperview() + make.bottom.equalToSuperview() + } + + subViewImage.addTarget(SubViewController.SubImageViewAction(_:), action: #selector(SubViewController.SubImageViewAction(_:)), for: .touchUpInside) + } + + func transfortImage(image: UIImage) { + subViewImage.setImage(image, for: .normal) + } + + override init(frame: CGRect) { + super.init(frame: frame) + setConstraint() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Info.plist b/JH/Study3_ImagePicker/Study3_ImagePicker/Info.plist new file mode 100644 index 0000000..b58f65a --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Info.plist @@ -0,0 +1,27 @@ + + + + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + + + + + NSCameraUsageDescription + Camera permissions for taking photos and videos + NSPhotoLibraryUsageDescription + Album permissions to save videos + + diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Model/MainModel.swift b/JH/Study3_ImagePicker/Study3_ImagePicker/Model/MainModel.swift new file mode 100644 index 0000000..8bbd8e0 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Model/MainModel.swift @@ -0,0 +1,17 @@ +// +// MainModel.swift +// Study3_ImagePicker +// +// Created by Jaehyeok Lim on 2022/06/26. +// + +import UIKit + +var mainList = [MainData]() + +struct MainData { + let albumTitleImage: UIImage + let albumTitleLabel: String + let albumIndex: Int + let totalPhotos: Int +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Model/SubModel.swift b/JH/Study3_ImagePicker/Study3_ImagePicker/Model/SubModel.swift new file mode 100644 index 0000000..938a85f --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Model/SubModel.swift @@ -0,0 +1,15 @@ +// +// SubModel.swift +// Study3_ImagePicker +// +// Created by Jaehyeok Lim on 2022/06/26. +// + +import UIKit + +var subList: [SubData] = [] + +struct SubData { + + let subDataImage: UIImage +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/SceneDelegate.swift b/JH/Study3_ImagePicker/Study3_ImagePicker/SceneDelegate.swift new file mode 100644 index 0000000..6ea082a --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/SceneDelegate.swift @@ -0,0 +1,56 @@ +// +// SceneDelegate.swift +// Study3_ImagePicker +// +// Created by Jaehyeok Lim on 2022/06/26. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + guard let windowScene = (scene as? UIWindowScene) else { return } + window = UIWindow(windowScene: windowScene) + window?.rootViewController = MainViewController() // RootViewController를 ViewController에 연결 + window?.makeKeyAndVisible() + guard let _ = (scene as? UIWindowScene) else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // 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() + } + + +} + diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Study3_ImagePicker.xcdatamodeld/.xccurrentversion b/JH/Study3_ImagePicker/Study3_ImagePicker/Study3_ImagePicker.xcdatamodeld/.xccurrentversion new file mode 100644 index 0000000..da0270f --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Study3_ImagePicker.xcdatamodeld/.xccurrentversion @@ -0,0 +1,8 @@ + + + + + _XCCurrentVersionName + Study3_ImagePicker.xcdatamodel + + diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/Study3_ImagePicker.xcdatamodeld/Study3_ImagePicker.xcdatamodel/contents b/JH/Study3_ImagePicker/Study3_ImagePicker/Study3_ImagePicker.xcdatamodeld/Study3_ImagePicker.xcdatamodel/contents new file mode 100644 index 0000000..50d2514 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/Study3_ImagePicker.xcdatamodeld/Study3_ImagePicker.xcdatamodel/contents @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/ViewController/DetailViewContoller.swift b/JH/Study3_ImagePicker/Study3_ImagePicker/ViewController/DetailViewContoller.swift new file mode 100644 index 0000000..fc87c27 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/ViewController/DetailViewContoller.swift @@ -0,0 +1,94 @@ +// +// DetailViewContoller.swift +// Study3_ImagePicker +// +// Created by Jaehyeok Lim on 2022/06/29. +// + +import UIKit +import SnapKit + +public var indexForDetailView = 0 + +class DetailViewController: UIViewController { + + lazy var collectionView: UICollectionView = { + let flowLayout = UICollectionViewFlowLayout() + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout) + + flowLayout.minimumLineSpacing = 0 + flowLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) + flowLayout.scrollDirection = .horizontal + collectionView.isPagingEnabled = true + + return collectionView + }() + + override func viewDidLoad() { + super.viewDidLoad() + collectionViewLayout() + } + + override func viewWillAppear(_ animated: Bool) { + + } + + private func collectionViewLayout() { + collectionView.register(DetailViewCustomCell.self, forCellWithReuseIdentifier: "DetailViewCustomCell") + + collectionView.dataSource = self + collectionView.delegate = self + + collectionView.backgroundColor = UIColor.black + + view.addSubview(collectionView) + + collectionView.snp.makeConstraints { make in + make.top.equalTo(view) + make.bottom.equalTo(view) + make.leading.equalTo(view) + make.right.equalTo(view) + } + } + + @objc func closeButtonAction(_ sender: UIButton) { + let point = sender.convert(CGPoint.zero, to: collectionView) + guard let indexPath = collectionView.indexPathForItem(at: point) else { return } + + dismiss(animated: true, completion: { indexForDetailView = indexPath.row }) + } +} + +extension DetailViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return mainList[indexPathForViewr].totalPhotos + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DetailViewCustomCell", for: indexPath) as? DetailViewCustomCell else { return UICollectionViewCell() } + + if indexForSubView != 0 { + collectionView.scrollToItem(at: IndexPath(item: indexForSubView, section: 0), at: .init(rawValue: 0), animated: true) + indexForSubView = 0 + } + + if indexPathForViewr == 0 { + cell.transfortImage(image: subList[indexPathForViewr + indexPath.row].subDataImage) + cell.transfortLabel(currentImageIndex: String(indexPath.row + 1), totalImageIndex: String(mainList[indexPathForViewr].totalPhotos)) + } else if indexPathForViewr == 1 { + cell.transfortImage(image: subList[(mainList[0].totalPhotos) + indexPath.row].subDataImage) + cell.transfortLabel(currentImageIndex: String(indexPath.row + 1), totalImageIndex: String(mainList[indexPathForViewr].totalPhotos)) + } else { + cell.transfortImage(image: subList[(mainList[indexPathForViewr - 2].totalPhotos + mainList[indexPathForViewr - 1].totalPhotos) + indexPath.row].subDataImage) + cell.transfortLabel(currentImageIndex: String(indexPath.row + 1), totalImageIndex: String(mainList[indexPathForViewr].totalPhotos)) + } + + return cell + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + + return CGSize(width: view.frame.width, height: view.frame.height) + } +} + diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/ViewController/MainViewController.swift b/JH/Study3_ImagePicker/Study3_ImagePicker/ViewController/MainViewController.swift new file mode 100644 index 0000000..bdacbe7 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/ViewController/MainViewController.swift @@ -0,0 +1,219 @@ +// +// MainViewController.swift +// Study3_ImagePicker +// +// Created by Jaehyeok Lim on 2022/06/26. +// + +import UIKit +import SnapKit +import PhotosUI + +public var indexPathForViewr = 0 + +private var imageArray: [UIImage] = [] +private var itemProviders: [NSItemProvider] = [] + +class MainViewController: UIViewController { + + lazy var collectionView: UICollectionView = { + let flowLayout = UICollectionViewFlowLayout() + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout) + + flowLayout.minimumLineSpacing = 0 + flowLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) + flowLayout.scrollDirection = .horizontal + collectionView.isPagingEnabled = true + + return collectionView + }() + + override func viewDidLoad() { + super.viewDidLoad() + addAlbum() + configureLayout() + collectionViewLayout() + } + + override func viewWillAppear(_ animated: Bool) { + collectionView.reloadData() + } + + private func addView() { + if imageArray.count != 0 { + + let popup = UIAlertController(title: "알림", message: "앨범 이름 작성", preferredStyle: .alert) + + popup.addTextField { (textField) in + + textField.placeholder = "여기에 작성해주세요." + } + + let addTextAlertAction = UIAlertAction(title: "등록", style: .default) { action in + let aaa = UILabel() + aaa.text = popup.textFields?[0].text + + let mainItem: MainData = MainData(albumTitleImage: subList[subList.count - imageArray.count].subDataImage, albumTitleLabel: aaa.text!, albumIndex: 0, totalPhotos: imageArray.count) + + mainList.insert(mainItem, at: mainList.count - 1) + self.collectionView.reloadData() + imageArray.removeAll() + + } + + popup.addAction(addTextAlertAction) + present(popup, animated: true, completion: nil) + } + } + + private func addAlbum() { + let item = [MainData(albumTitleImage: UIImage(systemName: "plus.rectangle")!, albumTitleLabel: "", albumIndex: .zero, totalPhotos: .zero)] + mainList.append(contentsOf: item) + } + + private func configureLayout() { + view.backgroundColor = UIColor.backgroundColor + + let subViewTitleLabel = UILabel() + + subViewTitleLabel.text = "ImagePicker" + subViewTitleLabel.textColor = UIColor.commonTextColor + subViewTitleLabel.font = UIFont.boldSystemFont(ofSize: 30) + + view.addSubview(subViewTitleLabel) + + subViewTitleLabel.snp.makeConstraints { make in + make.top.equalTo(view).offset(80) + make.leading.equalTo(view).offset(20) + } + + let subViewTitleImageView = UIImageView() + + subViewTitleImageView.image = UIImage(systemName: "photo.on.rectangle.angled") + subViewTitleImageView.tintColor = UIColor.systemBlue + + view.addSubview(subViewTitleImageView) + + subViewTitleImageView.snp.makeConstraints { make in + make.top.equalTo(subViewTitleLabel) + make.right.equalTo(subViewTitleLabel).offset(40) + make.size.equalTo(CGSize(width: 35, height: 35)) + } + } + + func collectionViewLayout() { + collectionView.register(MainViewCustomCell.self, forCellWithReuseIdentifier: "MainViewCustomCell") + + collectionView.dataSource = self + collectionView.delegate = self + collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell") + + collectionView.backgroundColor = UIColor.backgroundColor + + view.addSubview(collectionView) + + collectionView.snp.makeConstraints { make in + make.top.equalTo(view).offset(220) + make.bottom.equalTo(view).offset(-220) + make.leading.equalTo(view) + make.right.equalTo(view) + } + } + + @objc func albumTitleImageAction(_ sender: UIButton) { + let point = sender.convert(CGPoint.zero, to: collectionView) + guard let indexPath = collectionView.indexPathForItem(at: point) else { return } + + if indexPath.row == mainList.count - 1 { + + checkAlbumPermission() + + var configuration = PHPickerConfiguration() + + configuration.selectionLimit = 0 + configuration.filter = .any(of: [.images, .videos]) + + let picker = PHPickerViewController(configuration: configuration) + + picker.delegate = self + picker.modalPresentationStyle = .fullScreen + + self.present(picker, animated: true, completion: nil) + + } else { + let myViewController = SubViewController() + indexPathForViewr = indexPath.row + + myViewController.modalPresentationStyle = .fullScreen + present(myViewController, animated: true, completion: nil) + } + } + + func checkAlbumPermission(){ + PHPhotoLibrary.requestAuthorization( { status in + switch status{ + case .authorized: + print("Album: 권한 허용") + case .denied: + print("Album: 권한 거부") + case .restricted, .notDetermined: + print("Album: 선택하지 않음") + default: + break + } + }) + } +} + +extension MainViewController: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return mainList.count + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainViewCustomCell", for: indexPath) as? MainViewCustomCell else { return UICollectionViewCell() } + + cell.transfortImage(image: mainList[indexPath.row].albumTitleImage) + cell.transfortTitleLabel(titleTexts: mainList[indexPath.row].albumTitleLabel) + + if indexPath.row == (mainList.count - 1) { + cell.transfortIndexLabel(indexTexts: "") + cell.transfortHashTagIcon(iconTexts: "") + + } else { + cell.transfortIndexLabel(indexTexts: String(indexPath.row)) + cell.transfortHashTagIcon(iconTexts: "#") + } + + return cell + } + + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + + return CGSize(width: view.frame.width, height: view.frame.height - 550) + } +} + +extension MainViewController: PHPickerViewControllerDelegate { + @available(iOS 14, *) + func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { + picker.dismiss(animated: true, completion: { self.addView(); }) + + itemProviders = results.map(\.itemProvider) + + for item in itemProviders { + if item.canLoadObject(ofClass: UIImage.self) { + item.loadObject(ofClass: UIImage.self) { image, error in + DispatchQueue.main.async { + guard let image = image as? UIImage else { return } + let subListItem: SubData = SubData(subDataImage: image) + + subList.append(subListItem) + imageArray.append(image) + } + } + } + } + } +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePicker/ViewController/SubViewController.swift b/JH/Study3_ImagePicker/Study3_ImagePicker/ViewController/SubViewController.swift new file mode 100644 index 0000000..2476728 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePicker/ViewController/SubViewController.swift @@ -0,0 +1,171 @@ +// +// SubViewController.swift +// Study3_ImagePicker +// +// Created by Jaehyeok Lim on 2022/06/26. +// + +import UIKit +import SnapKit + +public var indexForSubView = 0 + +public extension UIColor { + static let backgroundColor = UIColor(named: "backgroundColor") + static let commonTextColor = UIColor(named: "commonTextColor") +} + +class SubViewController: UIViewController { + + lazy var collectionView: UICollectionView = { + let flowLayout = UICollectionViewFlowLayout() + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout) + + flowLayout.minimumLineSpacing = 0 + flowLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) + flowLayout.scrollDirection = .horizontal + collectionView.isPagingEnabled = true + + return collectionView + }() + + override func viewDidLoad() { + super.viewDidLoad() + + configureLayout() + collectionViewLayout() + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + } + + private func configureLayout() { + view.backgroundColor = UIColor.backgroundColor + + let subViewImagePickUpButton = UIButton() + + subViewImagePickUpButton.backgroundColor = UIColor.systemBlue + subViewImagePickUpButton.setTitle("PickUp Your Image!", for: .normal) + subViewImagePickUpButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20) + subViewImagePickUpButton.layer.borderWidth = 0.5 + subViewImagePickUpButton.layer.borderColor = UIColor.systemBlue.cgColor + subViewImagePickUpButton.layer.cornerRadius = 20 + + view.addSubview(subViewImagePickUpButton) + + subViewImagePickUpButton.snp.makeConstraints { make in + make.top.equalTo(view).offset(700) + make.leading.equalTo(view).offset(45) + make.size.equalTo(CGSize(width: 300, height: 40)) + } + + let addButton = UIButton() + + addButton.setImage(UIImage(systemName: "plus"), for: .normal) + addButton.contentVerticalAlignment = .fill + addButton.contentHorizontalAlignment = .fill + + view.addSubview(addButton) + + addButton.snp.makeConstraints { make in + make.top.equalTo(view).offset(70) + make.right.equalTo(view).offset(-30) + make.size.equalTo(CGSize(width: 32, height: 30)) + } + + let closeButton = UIButton() + + closeButton.setImage(UIImage(systemName: "xmark"), for: .normal) + closeButton.contentVerticalAlignment = .fill + closeButton.contentHorizontalAlignment = .fill + + view.addSubview(closeButton) + + closeButton.snp.makeConstraints { make in + make.top.equalTo(view).offset(70) + make.leading.equalTo(view).offset(30) + make.size.equalTo(CGSize(width: 28, height: 26)) + } + + closeButton.addTarget(self, action: #selector(closeButtonAction(_:)), for: .touchUpInside) + addButton.addTarget(self, action: #selector(addButtonAction(_:)), for: .touchUpInside) +} + + @objc func closeButtonAction(_ sender: UIButton) { + dismiss(animated: true, completion: nil) + + } + + @objc func addButtonAction(_ sender: UIButton) { + dismiss(animated: true, completion: nil) + + } + + func collectionViewLayout() { + + collectionView.register(SubViewCustomCell.self, forCellWithReuseIdentifier: "SubViewCustomCell") + + collectionView.dataSource = self + collectionView.delegate = self + collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell") + + collectionView.backgroundColor = UIColor.backgroundColor + + view.addSubview(collectionView) + + collectionView.snp.makeConstraints { make in + make.top.equalTo(view).offset(220) + make.bottom.equalTo(view).offset(-220) + make.leading.equalTo(view) + make.right.equalTo(view) + } + } + + @objc func SubImageViewAction(_ sender: UIButton) { + let point = sender.convert(CGPoint.zero, to: collectionView) + guard let indexPath = collectionView.indexPathForItem(at: point) else { return } + let myViewController = DetailViewController() + + indexForSubView = indexPath.row + + myViewController.modalPresentationStyle = .fullScreen + present(myViewController, animated: true, completion: nil) + } +} + +extension SubViewController: UICollectionViewDelegate, UICollectionViewDataSource { + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return mainList[indexPathForViewr].totalPhotos + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SubViewCustomCell", for: indexPath) as? SubViewCustomCell else { return UICollectionViewCell() } + + if indexForDetailView != 0 { + collectionView.scrollToItem(at: IndexPath(item: indexForDetailView, section: 0), at: .centeredHorizontally, animated: true) + indexForDetailView = 0 + } + + if indexPathForViewr == 0 { + cell.transfortImage(image: subList[indexPathForViewr + indexPath.row].subDataImage) + } else if indexPathForViewr == 1 { + cell.transfortImage(image: subList[(mainList[0].totalPhotos) + indexPath.row].subDataImage) + } else { + cell.transfortImage(image: subList[(mainList[indexPathForViewr - 2].totalPhotos + mainList[indexPathForViewr - 1].totalPhotos) + indexPath.row].subDataImage) + } + + return cell + } +} + +extension SubViewController: UICollectionViewDelegateFlowLayout { + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + + return CGSize(width: view.frame.width, height: view.frame.height - 550) + } +} + + diff --git a/JH/Study3_ImagePicker/Study3_ImagePickerTests/Study3_ImagePickerTests.swift b/JH/Study3_ImagePicker/Study3_ImagePickerTests/Study3_ImagePickerTests.swift new file mode 100644 index 0000000..18f23be --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePickerTests/Study3_ImagePickerTests.swift @@ -0,0 +1,36 @@ +// +// Study3_ImagePickerTests.swift +// Study3_ImagePickerTests +// +// Created by Jaehyeok Lim on 2022/06/26. +// + +import XCTest +@testable import Study3_ImagePicker + +class Study3_ImagePickerTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePickerUITests/Study3_ImagePickerUITests.swift b/JH/Study3_ImagePicker/Study3_ImagePickerUITests/Study3_ImagePickerUITests.swift new file mode 100644 index 0000000..55f6c87 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePickerUITests/Study3_ImagePickerUITests.swift @@ -0,0 +1,41 @@ +// +// Study3_ImagePickerUITests.swift +// Study3_ImagePickerUITests +// +// Created by Jaehyeok Lim on 2022/06/26. +// + +import XCTest + +class Study3_ImagePickerUITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } +} diff --git a/JH/Study3_ImagePicker/Study3_ImagePickerUITests/Study3_ImagePickerUITestsLaunchTests.swift b/JH/Study3_ImagePicker/Study3_ImagePickerUITests/Study3_ImagePickerUITestsLaunchTests.swift new file mode 100644 index 0000000..0232478 --- /dev/null +++ b/JH/Study3_ImagePicker/Study3_ImagePickerUITests/Study3_ImagePickerUITestsLaunchTests.swift @@ -0,0 +1,32 @@ +// +// Study3_ImagePickerUITestsLaunchTests.swift +// Study3_ImagePickerUITests +// +// Created by Jaehyeok Lim on 2022/06/26. +// + +import XCTest + +class Study3_ImagePickerUITestsLaunchTests: XCTestCase { + + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } + + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +} diff --git a/JH/Study3_MusicPlayer/.DS_Store b/JH/Study3_MusicPlayer/.DS_Store new file mode 100644 index 0000000..35ef159 Binary files /dev/null and b/JH/Study3_MusicPlayer/.DS_Store differ diff --git a/JH/Study3_MusicPlayer/Podfile b/JH/Study3_MusicPlayer/Podfile new file mode 100644 index 0000000..909844c --- /dev/null +++ b/JH/Study3_MusicPlayer/Podfile @@ -0,0 +1,19 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +target 'Study3_MusicPlayer' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + # Pods for Study3_MusicPlayer + pod 'SnapKit', '~> 5.0.0' + target 'Study3_MusicPlayerTests' do + inherit! :search_paths + # Pods for testing + end + + target 'Study3_MusicPlayerUITests' do + # Pods for testing + end + +end diff --git a/JH/Study3_MusicPlayer/Podfile.lock b/JH/Study3_MusicPlayer/Podfile.lock new file mode 100644 index 0000000..7bba313 --- /dev/null +++ b/JH/Study3_MusicPlayer/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - SnapKit (5.0.1) + +DEPENDENCIES: + - SnapKit (~> 5.0.0) + +SPEC REPOS: + trunk: + - SnapKit + +SPEC CHECKSUMS: + SnapKit: 97b92857e3df3a0c71833cce143274bf6ef8e5eb + +PODFILE CHECKSUM: 2b2053eed6408cb5517383648c3da4502d133a14 + +COCOAPODS: 1.11.3 diff --git a/JH/Study3_MusicPlayer/Podfilen b/JH/Study3_MusicPlayer/Podfilen new file mode 100644 index 0000000..7c48629 --- /dev/null +++ b/JH/Study3_MusicPlayer/Podfilen @@ -0,0 +1,19 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +target 'Study3_MusicPlayer' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + # Pods for Study3_MusicPlayer + + target 'Study3_MusicPlayerTests' do + inherit! :search_paths + # Pods for testing + end + + target 'Study3_MusicPlayerUITests' do + # Pods for testing + end + +end diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcodeproj/project.pbxproj b/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcodeproj/project.pbxproj new file mode 100644 index 0000000..b1d72c6 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcodeproj/project.pbxproj @@ -0,0 +1,804 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + 37A255201F47580CEB44E6A2 /* Pods_Study3_MusicPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CF6E3BFF45ECE8FB19AA83 /* Pods_Study3_MusicPlayer.framework */; }; + 8169D054A6BA7BE67897C2DF /* Pods_Study3_MusicPlayerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16E69F689299FD6CA6C2BC6C /* Pods_Study3_MusicPlayerTests.framework */; }; + A99483B776B0DCAD46B277A3 /* Pods_Study3_MusicPlayer_Study3_MusicPlayerUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 417810B6B1D79A10D044C120 /* Pods_Study3_MusicPlayer_Study3_MusicPlayerUITests.framework */; }; + FA2A3E9F286CFEDF009BD28B /* MainCollectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2A3E9E286CFEDF009BD28B /* MainCollectionModel.swift */; }; + FA2F94E228704D6500106E05 /* MainViewTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2F94E128704D6500106E05 /* MainViewTableCell.swift */; }; + FA2F94E428704E0A00106E05 /* MainTableModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2F94E328704E0A00106E05 /* MainTableModel.swift */; }; + FA53AF37286CB0B800A6A309 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA53AF36286CB0B800A6A309 /* AppDelegate.swift */; }; + FA53AF39286CB0B800A6A309 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA53AF38286CB0B800A6A309 /* SceneDelegate.swift */; }; + FA53AF3B286CB0B800A6A309 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA53AF3A286CB0B800A6A309 /* MainViewController.swift */; }; + FA53AF41286CB0B800A6A309 /* Study3_MusicPlayer.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = FA53AF3F286CB0B800A6A309 /* Study3_MusicPlayer.xcdatamodeld */; }; + FA53AF43286CB0B800A6A309 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FA53AF42286CB0B800A6A309 /* Assets.xcassets */; }; + FA53AF46286CB0B800A6A309 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FA53AF44286CB0B800A6A309 /* LaunchScreen.storyboard */; }; + FA53AF51286CB0B900A6A309 /* Study3_MusicPlayerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA53AF50286CB0B900A6A309 /* Study3_MusicPlayerTests.swift */; }; + FA53AF5B286CB0B900A6A309 /* Study3_MusicPlayerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA53AF5A286CB0B900A6A309 /* Study3_MusicPlayerUITests.swift */; }; + FA53AF5D286CB0B900A6A309 /* Study3_MusicPlayerUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA53AF5C286CB0B900A6A309 /* Study3_MusicPlayerUITestsLaunchTests.swift */; }; + FA53AF6D286CB2B100A6A309 /* MainViewCollectionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA53AF6C286CB2B100A6A309 /* MainViewCollectionCell.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + FA53AF4D286CB0B900A6A309 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FA53AF2B286CB0B800A6A309 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FA53AF32286CB0B800A6A309; + remoteInfo = Study3_MusicPlayer; + }; + FA53AF57286CB0B900A6A309 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FA53AF2B286CB0B800A6A309 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FA53AF32286CB0B800A6A309; + remoteInfo = Study3_MusicPlayer; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 165237BC42C24F5A8B606A98 /* Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests.debug.xcconfig"; path = "Target Support Files/Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests/Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests.debug.xcconfig"; sourceTree = ""; }; + 16E69F689299FD6CA6C2BC6C /* Pods_Study3_MusicPlayerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Study3_MusicPlayerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 417810B6B1D79A10D044C120 /* Pods_Study3_MusicPlayer_Study3_MusicPlayerUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Study3_MusicPlayer_Study3_MusicPlayerUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 521BD5E33390A91BD8F92777 /* Pods-Study3_MusicPlayerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Study3_MusicPlayerTests.debug.xcconfig"; path = "Target Support Files/Pods-Study3_MusicPlayerTests/Pods-Study3_MusicPlayerTests.debug.xcconfig"; sourceTree = ""; }; + 6F04D4BEBBE892C7C22ED3EF /* Pods-Study3_MusicPlayer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Study3_MusicPlayer.release.xcconfig"; path = "Target Support Files/Pods-Study3_MusicPlayer/Pods-Study3_MusicPlayer.release.xcconfig"; sourceTree = ""; }; + A7E206B824F26D2BC5D1445C /* Pods-Study3_MusicPlayer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Study3_MusicPlayer.debug.xcconfig"; path = "Target Support Files/Pods-Study3_MusicPlayer/Pods-Study3_MusicPlayer.debug.xcconfig"; sourceTree = ""; }; + B4BD216EE6FF46B60E1E3BB3 /* Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests.release.xcconfig"; path = "Target Support Files/Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests/Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests.release.xcconfig"; sourceTree = ""; }; + C53C6EBBF8EA523B4FEB41FF /* Pods-Study3_MusicPlayerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Study3_MusicPlayerTests.release.xcconfig"; path = "Target Support Files/Pods-Study3_MusicPlayerTests/Pods-Study3_MusicPlayerTests.release.xcconfig"; sourceTree = ""; }; + D3CF6E3BFF45ECE8FB19AA83 /* Pods_Study3_MusicPlayer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Study3_MusicPlayer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FA2A3E9E286CFEDF009BD28B /* MainCollectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainCollectionModel.swift; sourceTree = ""; }; + FA2F94E128704D6500106E05 /* MainViewTableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewTableCell.swift; sourceTree = ""; }; + FA2F94E328704E0A00106E05 /* MainTableModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTableModel.swift; sourceTree = ""; }; + FA53AF33286CB0B800A6A309 /* Study3_MusicPlayer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Study3_MusicPlayer.app; sourceTree = BUILT_PRODUCTS_DIR; }; + FA53AF36286CB0B800A6A309 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + FA53AF38286CB0B800A6A309 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + FA53AF3A286CB0B800A6A309 /* MainViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; }; + FA53AF40286CB0B800A6A309 /* Study3_MusicPlayer.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Study3_MusicPlayer.xcdatamodel; sourceTree = ""; }; + FA53AF42286CB0B800A6A309 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + FA53AF45286CB0B800A6A309 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + FA53AF47286CB0B800A6A309 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + FA53AF4C286CB0B900A6A309 /* Study3_MusicPlayerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Study3_MusicPlayerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + FA53AF50286CB0B900A6A309 /* Study3_MusicPlayerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Study3_MusicPlayerTests.swift; sourceTree = ""; }; + FA53AF56286CB0B900A6A309 /* Study3_MusicPlayerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Study3_MusicPlayerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + FA53AF5A286CB0B900A6A309 /* Study3_MusicPlayerUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Study3_MusicPlayerUITests.swift; sourceTree = ""; }; + FA53AF5C286CB0B900A6A309 /* Study3_MusicPlayerUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Study3_MusicPlayerUITestsLaunchTests.swift; sourceTree = ""; }; + FA53AF6C286CB2B100A6A309 /* MainViewCollectionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewCollectionCell.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + FA53AF30286CB0B800A6A309 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 37A255201F47580CEB44E6A2 /* Pods_Study3_MusicPlayer.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA53AF49286CB0B900A6A309 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8169D054A6BA7BE67897C2DF /* Pods_Study3_MusicPlayerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA53AF53286CB0B900A6A309 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A99483B776B0DCAD46B277A3 /* Pods_Study3_MusicPlayer_Study3_MusicPlayerUITests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2D2E412211AB797C51117050 /* Pods */ = { + isa = PBXGroup; + children = ( + A7E206B824F26D2BC5D1445C /* Pods-Study3_MusicPlayer.debug.xcconfig */, + 6F04D4BEBBE892C7C22ED3EF /* Pods-Study3_MusicPlayer.release.xcconfig */, + 165237BC42C24F5A8B606A98 /* Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests.debug.xcconfig */, + B4BD216EE6FF46B60E1E3BB3 /* Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests.release.xcconfig */, + 521BD5E33390A91BD8F92777 /* Pods-Study3_MusicPlayerTests.debug.xcconfig */, + C53C6EBBF8EA523B4FEB41FF /* Pods-Study3_MusicPlayerTests.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + EF46F8697DE35F684CD455CC /* Frameworks */ = { + isa = PBXGroup; + children = ( + D3CF6E3BFF45ECE8FB19AA83 /* Pods_Study3_MusicPlayer.framework */, + 417810B6B1D79A10D044C120 /* Pods_Study3_MusicPlayer_Study3_MusicPlayerUITests.framework */, + 16E69F689299FD6CA6C2BC6C /* Pods_Study3_MusicPlayerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + FA53AF2A286CB0B800A6A309 = { + isa = PBXGroup; + children = ( + FA53AF35286CB0B800A6A309 /* Study3_MusicPlayer */, + FA53AF4F286CB0B900A6A309 /* Study3_MusicPlayerTests */, + FA53AF59286CB0B900A6A309 /* Study3_MusicPlayerUITests */, + FA53AF34286CB0B800A6A309 /* Products */, + 2D2E412211AB797C51117050 /* Pods */, + EF46F8697DE35F684CD455CC /* Frameworks */, + ); + sourceTree = ""; + }; + FA53AF34286CB0B800A6A309 /* Products */ = { + isa = PBXGroup; + children = ( + FA53AF33286CB0B800A6A309 /* Study3_MusicPlayer.app */, + FA53AF4C286CB0B900A6A309 /* Study3_MusicPlayerTests.xctest */, + FA53AF56286CB0B900A6A309 /* Study3_MusicPlayerUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + FA53AF35286CB0B800A6A309 /* Study3_MusicPlayer */ = { + isa = PBXGroup; + children = ( + FA53AF6B286CB16300A6A309 /* Model */, + FA53AF6A286CB15F00A6A309 /* View */, + FA53AF69286CB15800A6A309 /* ViewController */, + FA53AF36286CB0B800A6A309 /* AppDelegate.swift */, + FA53AF38286CB0B800A6A309 /* SceneDelegate.swift */, + FA53AF42286CB0B800A6A309 /* Assets.xcassets */, + FA53AF44286CB0B800A6A309 /* LaunchScreen.storyboard */, + FA53AF47286CB0B800A6A309 /* Info.plist */, + FA53AF3F286CB0B800A6A309 /* Study3_MusicPlayer.xcdatamodeld */, + ); + path = Study3_MusicPlayer; + sourceTree = ""; + }; + FA53AF4F286CB0B900A6A309 /* Study3_MusicPlayerTests */ = { + isa = PBXGroup; + children = ( + FA53AF50286CB0B900A6A309 /* Study3_MusicPlayerTests.swift */, + ); + path = Study3_MusicPlayerTests; + sourceTree = ""; + }; + FA53AF59286CB0B900A6A309 /* Study3_MusicPlayerUITests */ = { + isa = PBXGroup; + children = ( + FA53AF5A286CB0B900A6A309 /* Study3_MusicPlayerUITests.swift */, + FA53AF5C286CB0B900A6A309 /* Study3_MusicPlayerUITestsLaunchTests.swift */, + ); + path = Study3_MusicPlayerUITests; + sourceTree = ""; + }; + FA53AF69286CB15800A6A309 /* ViewController */ = { + isa = PBXGroup; + children = ( + FA53AF3A286CB0B800A6A309 /* MainViewController.swift */, + ); + path = ViewController; + sourceTree = ""; + }; + FA53AF6A286CB15F00A6A309 /* View */ = { + isa = PBXGroup; + children = ( + FA53AF6C286CB2B100A6A309 /* MainViewCollectionCell.swift */, + FA2F94E128704D6500106E05 /* MainViewTableCell.swift */, + ); + path = View; + sourceTree = ""; + }; + FA53AF6B286CB16300A6A309 /* Model */ = { + isa = PBXGroup; + children = ( + FA2A3E9E286CFEDF009BD28B /* MainCollectionModel.swift */, + FA2F94E328704E0A00106E05 /* MainTableModel.swift */, + ); + path = Model; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + FA53AF32286CB0B800A6A309 /* Study3_MusicPlayer */ = { + isa = PBXNativeTarget; + buildConfigurationList = FA53AF60286CB0B900A6A309 /* Build configuration list for PBXNativeTarget "Study3_MusicPlayer" */; + buildPhases = ( + 7F795F29587E9EF3AB4F6DB5 /* [CP] Check Pods Manifest.lock */, + FA53AF2F286CB0B800A6A309 /* Sources */, + FA53AF30286CB0B800A6A309 /* Frameworks */, + FA53AF31286CB0B800A6A309 /* Resources */, + A2C8B34568F6E8BD39DFA9A7 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Study3_MusicPlayer; + productName = Study3_MusicPlayer; + productReference = FA53AF33286CB0B800A6A309 /* Study3_MusicPlayer.app */; + productType = "com.apple.product-type.application"; + }; + FA53AF4B286CB0B900A6A309 /* Study3_MusicPlayerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = FA53AF63286CB0B900A6A309 /* Build configuration list for PBXNativeTarget "Study3_MusicPlayerTests" */; + buildPhases = ( + E4E0164D25CBDCF58944F1BA /* [CP] Check Pods Manifest.lock */, + FA53AF48286CB0B900A6A309 /* Sources */, + FA53AF49286CB0B900A6A309 /* Frameworks */, + FA53AF4A286CB0B900A6A309 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + FA53AF4E286CB0B900A6A309 /* PBXTargetDependency */, + ); + name = Study3_MusicPlayerTests; + productName = Study3_MusicPlayerTests; + productReference = FA53AF4C286CB0B900A6A309 /* Study3_MusicPlayerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + FA53AF55286CB0B900A6A309 /* Study3_MusicPlayerUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = FA53AF66286CB0B900A6A309 /* Build configuration list for PBXNativeTarget "Study3_MusicPlayerUITests" */; + buildPhases = ( + D809905952660867EB0C4C91 /* [CP] Check Pods Manifest.lock */, + FA53AF52286CB0B900A6A309 /* Sources */, + FA53AF53286CB0B900A6A309 /* Frameworks */, + FA53AF54286CB0B900A6A309 /* Resources */, + 2032B1C9E8F0E24C0E095387 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + FA53AF58286CB0B900A6A309 /* PBXTargetDependency */, + ); + name = Study3_MusicPlayerUITests; + productName = Study3_MusicPlayerUITests; + productReference = FA53AF56286CB0B900A6A309 /* Study3_MusicPlayerUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + FA53AF2B286CB0B800A6A309 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1330; + LastUpgradeCheck = 1330; + TargetAttributes = { + FA53AF32286CB0B800A6A309 = { + CreatedOnToolsVersion = 13.3; + }; + FA53AF4B286CB0B900A6A309 = { + CreatedOnToolsVersion = 13.3; + TestTargetID = FA53AF32286CB0B800A6A309; + }; + FA53AF55286CB0B900A6A309 = { + CreatedOnToolsVersion = 13.3; + TestTargetID = FA53AF32286CB0B800A6A309; + }; + }; + }; + buildConfigurationList = FA53AF2E286CB0B800A6A309 /* Build configuration list for PBXProject "Study3_MusicPlayer" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = FA53AF2A286CB0B800A6A309; + productRefGroup = FA53AF34286CB0B800A6A309 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + FA53AF32286CB0B800A6A309 /* Study3_MusicPlayer */, + FA53AF4B286CB0B900A6A309 /* Study3_MusicPlayerTests */, + FA53AF55286CB0B900A6A309 /* Study3_MusicPlayerUITests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + FA53AF31286CB0B800A6A309 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FA53AF46286CB0B800A6A309 /* LaunchScreen.storyboard in Resources */, + FA53AF43286CB0B800A6A309 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA53AF4A286CB0B900A6A309 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA53AF54286CB0B900A6A309 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 2032B1C9E8F0E24C0E095387 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests/Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests/Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests/Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 7F795F29587E9EF3AB4F6DB5 /* [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-Study3_MusicPlayer-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; + }; + A2C8B34568F6E8BD39DFA9A7 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Study3_MusicPlayer/Pods-Study3_MusicPlayer-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Study3_MusicPlayer/Pods-Study3_MusicPlayer-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Study3_MusicPlayer/Pods-Study3_MusicPlayer-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + D809905952660867EB0C4C91 /* [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-Study3_MusicPlayer-Study3_MusicPlayerUITests-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; + }; + E4E0164D25CBDCF58944F1BA /* [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-Study3_MusicPlayerTests-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; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + FA53AF2F286CB0B800A6A309 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FA53AF41286CB0B800A6A309 /* Study3_MusicPlayer.xcdatamodeld in Sources */, + FA53AF6D286CB2B100A6A309 /* MainViewCollectionCell.swift in Sources */, + FA2A3E9F286CFEDF009BD28B /* MainCollectionModel.swift in Sources */, + FA2F94E228704D6500106E05 /* MainViewTableCell.swift in Sources */, + FA53AF3B286CB0B800A6A309 /* MainViewController.swift in Sources */, + FA2F94E428704E0A00106E05 /* MainTableModel.swift in Sources */, + FA53AF37286CB0B800A6A309 /* AppDelegate.swift in Sources */, + FA53AF39286CB0B800A6A309 /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA53AF48286CB0B900A6A309 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FA53AF51286CB0B900A6A309 /* Study3_MusicPlayerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA53AF52286CB0B900A6A309 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FA53AF5B286CB0B900A6A309 /* Study3_MusicPlayerUITests.swift in Sources */, + FA53AF5D286CB0B900A6A309 /* Study3_MusicPlayerUITestsLaunchTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + FA53AF4E286CB0B900A6A309 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FA53AF32286CB0B800A6A309 /* Study3_MusicPlayer */; + targetProxy = FA53AF4D286CB0B900A6A309 /* PBXContainerItemProxy */; + }; + FA53AF58286CB0B900A6A309 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FA53AF32286CB0B800A6A309 /* Study3_MusicPlayer */; + targetProxy = FA53AF57286CB0B900A6A309 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + FA53AF44286CB0B800A6A309 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + FA53AF45286CB0B800A6A309 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + FA53AF5E286CB0B900A6A309 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_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 = ( + "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 = 15.4; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + FA53AF5F286CB0B900A6A309 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_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_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 = 15.4; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + FA53AF61286CB0B900A6A309 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A7E206B824F26D2BC5D1445C /* Pods-Study3_MusicPlayer.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6578S57CDT; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = Study3_MusicPlayer/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "Jaehyeoklim.Study3-MusicPlayer"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + FA53AF62286CB0B900A6A309 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6F04D4BEBBE892C7C22ED3EF /* Pods-Study3_MusicPlayer.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6578S57CDT; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = Study3_MusicPlayer/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "Jaehyeoklim.Study3-MusicPlayer"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + FA53AF64286CB0B900A6A309 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 521BD5E33390A91BD8F92777 /* Pods-Study3_MusicPlayerTests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6578S57CDT; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.4; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "Jaehyeoklim.Study3-MusicPlayerTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Study3_MusicPlayer.app/Study3_MusicPlayer"; + }; + name = Debug; + }; + FA53AF65286CB0B900A6A309 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C53C6EBBF8EA523B4FEB41FF /* Pods-Study3_MusicPlayerTests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6578S57CDT; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.4; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "Jaehyeoklim.Study3-MusicPlayerTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Study3_MusicPlayer.app/Study3_MusicPlayer"; + }; + name = Release; + }; + FA53AF67286CB0B900A6A309 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 165237BC42C24F5A8B606A98 /* Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6578S57CDT; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "Jaehyeoklim.Study3-MusicPlayerUITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = Study3_MusicPlayer; + }; + name = Debug; + }; + FA53AF68286CB0B900A6A309 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B4BD216EE6FF46B60E1E3BB3 /* Pods-Study3_MusicPlayer-Study3_MusicPlayerUITests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6578S57CDT; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "Jaehyeoklim.Study3-MusicPlayerUITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = Study3_MusicPlayer; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + FA53AF2E286CB0B800A6A309 /* Build configuration list for PBXProject "Study3_MusicPlayer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FA53AF5E286CB0B900A6A309 /* Debug */, + FA53AF5F286CB0B900A6A309 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FA53AF60286CB0B900A6A309 /* Build configuration list for PBXNativeTarget "Study3_MusicPlayer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FA53AF61286CB0B900A6A309 /* Debug */, + FA53AF62286CB0B900A6A309 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FA53AF63286CB0B900A6A309 /* Build configuration list for PBXNativeTarget "Study3_MusicPlayerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FA53AF64286CB0B900A6A309 /* Debug */, + FA53AF65286CB0B900A6A309 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FA53AF66286CB0B900A6A309 /* Build configuration list for PBXNativeTarget "Study3_MusicPlayerUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FA53AF67286CB0B900A6A309 /* Debug */, + FA53AF68286CB0B900A6A309 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCVersionGroup section */ + FA53AF3F286CB0B800A6A309 /* Study3_MusicPlayer.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + FA53AF40286CB0B800A6A309 /* Study3_MusicPlayer.xcdatamodel */, + ); + currentVersion = FA53AF40286CB0B800A6A309 /* Study3_MusicPlayer.xcdatamodel */; + path = Study3_MusicPlayer.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ + }; + rootObject = FA53AF2B286CB0B800A6A309 /* Project object */; +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcworkspace/contents.xcworkspacedata b/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..5f6c673 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/AppDelegate.swift b/JH/Study3_MusicPlayer/Study3_MusicPlayer/AppDelegate.swift new file mode 100644 index 0000000..c9b9338 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/AppDelegate.swift @@ -0,0 +1,81 @@ +// +// AppDelegate.swift +// Study3_MusicPlayer +// +// Created by Jaehyeok Lim on 2022/06/30. +// + +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: "Study3_MusicPlayer") + 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/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/AccentColor.colorset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/AppIcon.appiconset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..9221b9b --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/Still Life.dataset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/Still Life.dataset/Contents.json new file mode 100644 index 0000000..9abcaa3 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/Still Life.dataset/Contents.json @@ -0,0 +1,13 @@ +{ + "data" : [ + { + "filename" : "y2mate.com - BIGBANG 빅뱅 STILL LIFE 봄여름가을겨울 가사 Color Coded Lyrics.mp3", + "idiom" : "universal", + "universal-type-identifier" : "public.mp3" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git "a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/Still Life.dataset/y2mate.com - BIGBANG \353\271\205\353\261\205 STILL LIFE \353\264\204\354\227\254\353\246\204\352\260\200\354\235\204\352\262\250\354\232\270 \352\260\200\354\202\254 Color Coded Lyrics.mp3" "b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/Still Life.dataset/y2mate.com - BIGBANG \353\271\205\353\261\205 STILL LIFE \353\264\204\354\227\254\353\246\204\352\260\200\354\235\204\352\262\250\354\232\270 \352\260\200\354\202\254 Color Coded Lyrics.mp3" new file mode 100644 index 0000000..855b9da Binary files /dev/null and "b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/Still Life.dataset/y2mate.com - BIGBANG \353\271\205\353\261\205 STILL LIFE \353\264\204\354\227\254\353\246\204\352\260\200\354\235\204\352\262\250\354\232\270 \352\260\200\354\202\254 Color Coded Lyrics.mp3" differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/backgroundColor.colorset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/backgroundColor.colorset/Contents.json new file mode 100644 index 0000000..737e910 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/backgroundColor.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.000", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyond Love.dataset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyond Love.dataset/Contents.json new file mode 100644 index 0000000..dcd0430 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyond Love.dataset/Contents.json @@ -0,0 +1,13 @@ +{ + "data" : [ + { + "filename" : "y2mate.com - BIG Naughty 서동현 정이라고 하자 Feat 10CM 정이라고 하자ㅣLyrics가사.mp3", + "idiom" : "universal", + "universal-type-identifier" : "public.mp3" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git "a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyond Love.dataset/y2mate.com - BIG Naughty \354\204\234\353\217\231\355\230\204 \354\240\225\354\235\264\353\235\274\352\263\240 \355\225\230\354\236\220 Feat 10CM \354\240\225\354\235\264\353\235\274\352\263\240 \355\225\230\354\236\220\343\205\243Lyrics\352\260\200\354\202\254.mp3" "b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyond Love.dataset/y2mate.com - BIG Naughty \354\204\234\353\217\231\355\230\204 \354\240\225\354\235\264\353\235\274\352\263\240 \355\225\230\354\236\220 Feat 10CM \354\240\225\354\235\264\353\235\274\352\263\240 \355\225\230\354\236\220\343\205\243Lyrics\352\260\200\354\202\254.mp3" new file mode 100644 index 0000000..525392c Binary files /dev/null and "b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyond Love.dataset/y2mate.com - BIG Naughty \354\204\234\353\217\231\355\230\204 \354\240\225\354\235\264\353\235\274\352\263\240 \355\225\230\354\236\220 Feat 10CM \354\240\225\354\235\264\353\235\274\352\263\240 \355\225\230\354\236\220\343\205\243Lyrics\352\260\200\354\202\254.mp3" differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyondLoveAlbumCover.imageset/4074520-1.jpg b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyondLoveAlbumCover.imageset/4074520-1.jpg new file mode 100644 index 0000000..b5ede90 Binary files /dev/null and b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyondLoveAlbumCover.imageset/4074520-1.jpg differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyondLoveAlbumCover.imageset/4074520-2.jpg b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyondLoveAlbumCover.imageset/4074520-2.jpg new file mode 100644 index 0000000..b5ede90 Binary files /dev/null and b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyondLoveAlbumCover.imageset/4074520-2.jpg differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyondLoveAlbumCover.imageset/4074520.jpg b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyondLoveAlbumCover.imageset/4074520.jpg new file mode 100644 index 0000000..b5ede90 Binary files /dev/null and b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyondLoveAlbumCover.imageset/4074520.jpg differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyondLoveAlbumCover.imageset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyondLoveAlbumCover.imageset/Contents.json new file mode 100644 index 0000000..6a93b0f --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/beyondLoveAlbumCover.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "4074520.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "4074520-1.jpg", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "4074520-2.jpg", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/cellTextColor.colorset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/cellTextColor.colorset/Contents.json new file mode 100644 index 0000000..58f2cbc --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/cellTextColor.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.697", + "green" : "0.697", + "red" : "0.697" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/cellTitleTextColor.colorset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/cellTitleTextColor.colorset/Contents.json new file mode 100644 index 0000000..cadd45e --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/cellTitleTextColor.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.115", + "green" : "0.099", + "red" : "0.102" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/commonTextColor.colorset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/commonTextColor.colorset/Contents.json new file mode 100644 index 0000000..76b961c --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/commonTextColor.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.000", + "red" : "0.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghost.dataset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghost.dataset/Contents.json new file mode 100644 index 0000000..c106726 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghost.dataset/Contents.json @@ -0,0 +1,13 @@ +{ + "data" : [ + { + "filename" : "Zior Park - GHOST (OFFICIAL VIDEO).mp3", + "idiom" : "universal", + "universal-type-identifier" : "public.mp3" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghost.dataset/Zior Park - GHOST (OFFICIAL VIDEO).mp3 b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghost.dataset/Zior Park - GHOST (OFFICIAL VIDEO).mp3 new file mode 100644 index 0000000..98f33f8 Binary files /dev/null and b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghost.dataset/Zior Park - GHOST (OFFICIAL VIDEO).mp3 differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghostAlbumCoverimage.imageset/20400304-2.jpg b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghostAlbumCoverimage.imageset/20400304-2.jpg new file mode 100644 index 0000000..5b372b3 Binary files /dev/null and b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghostAlbumCoverimage.imageset/20400304-2.jpg differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghostAlbumCoverimage.imageset/20400304-3.jpg b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghostAlbumCoverimage.imageset/20400304-3.jpg new file mode 100644 index 0000000..5b372b3 Binary files /dev/null and b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghostAlbumCoverimage.imageset/20400304-3.jpg differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghostAlbumCoverimage.imageset/20400304-4.jpg b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghostAlbumCoverimage.imageset/20400304-4.jpg new file mode 100644 index 0000000..5b372b3 Binary files /dev/null and b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghostAlbumCoverimage.imageset/20400304-4.jpg differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghostAlbumCoverimage.imageset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghostAlbumCoverimage.imageset/Contents.json new file mode 100644 index 0000000..3697b46 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/ghostAlbumCoverimage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "20400304-2.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "20400304-3.jpg", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "20400304-4.jpg", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/lyricsFocusingColor.colorset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/lyricsFocusingColor.colorset/Contents.json new file mode 100644 index 0000000..508cb56 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/lyricsFocusingColor.colorset/Contents.json @@ -0,0 +1,54 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "platform" : "ios", + "reference" : "systemBlueColor" + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "localizable" : true + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starman.dataset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starman.dataset/Contents.json new file mode 100644 index 0000000..46b999c --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starman.dataset/Contents.json @@ -0,0 +1,13 @@ +{ + "data" : [ + { + "filename" : "starman.mp3", + "idiom" : "universal", + "universal-type-identifier" : "public.mp3" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starman.dataset/starman.mp3 b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starman.dataset/starman.mp3 new file mode 100644 index 0000000..b31def6 Binary files /dev/null and b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starman.dataset/starman.mp3 differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starmanAlbumCoverImage.imageset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starmanAlbumCoverImage.imageset/Contents.json new file mode 100644 index 0000000..ccc11aa --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starmanAlbumCoverImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "ziggy-stardust.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "ziggy-stardust-1.jpg", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "ziggy-stardust-2.jpg", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starmanAlbumCoverImage.imageset/ziggy-stardust-1.jpg b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starmanAlbumCoverImage.imageset/ziggy-stardust-1.jpg new file mode 100644 index 0000000..bd2ac13 Binary files /dev/null and b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starmanAlbumCoverImage.imageset/ziggy-stardust-1.jpg differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starmanAlbumCoverImage.imageset/ziggy-stardust-2.jpg b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starmanAlbumCoverImage.imageset/ziggy-stardust-2.jpg new file mode 100644 index 0000000..bd2ac13 Binary files /dev/null and b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starmanAlbumCoverImage.imageset/ziggy-stardust-2.jpg differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starmanAlbumCoverImage.imageset/ziggy-stardust.jpg b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starmanAlbumCoverImage.imageset/ziggy-stardust.jpg new file mode 100644 index 0000000..bd2ac13 Binary files /dev/null and b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/starmanAlbumCoverImage.imageset/ziggy-stardust.jpg differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/stilllifeAlbumCoverImage.imageset/4073653-1.jpg b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/stilllifeAlbumCoverImage.imageset/4073653-1.jpg new file mode 100644 index 0000000..3bfa928 Binary files /dev/null and b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/stilllifeAlbumCoverImage.imageset/4073653-1.jpg differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/stilllifeAlbumCoverImage.imageset/4073653-2.jpg b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/stilllifeAlbumCoverImage.imageset/4073653-2.jpg new file mode 100644 index 0000000..3bfa928 Binary files /dev/null and b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/stilllifeAlbumCoverImage.imageset/4073653-2.jpg differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/stilllifeAlbumCoverImage.imageset/4073653.jpg b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/stilllifeAlbumCoverImage.imageset/4073653.jpg new file mode 100644 index 0000000..3bfa928 Binary files /dev/null and b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/stilllifeAlbumCoverImage.imageset/4073653.jpg differ diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/stilllifeAlbumCoverImage.imageset/Contents.json b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/stilllifeAlbumCoverImage.imageset/Contents.json new file mode 100644 index 0000000..d70482b --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Assets.xcassets/stilllifeAlbumCoverImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "4073653.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "4073653-1.jpg", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "4073653-2.jpg", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Base.lproj/LaunchScreen.storyboard b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..865e932 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Info.plist b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Info.plist new file mode 100644 index 0000000..f8d2401 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Info.plist @@ -0,0 +1,27 @@ + + + + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + + + + + UIBackgroundModes + + audio + + + diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Model/MainCollectionModel.swift b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Model/MainCollectionModel.swift new file mode 100644 index 0000000..d84b716 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Model/MainCollectionModel.swift @@ -0,0 +1,19 @@ +// +// MainModel.swift +// Study3_MusicPlayer +// +// Created by Jaehyeok Lim on 2022/06/30. +// + +import UIKit + +var mainCollectionViewList = [MainCollectionViewData]() + +struct MainCollectionViewData { + + let mainDataTitleImage: UIImage + let mainDataTitleLabel: String + let mainDataSingerLabel: String + let mainDataAlbumLabel: String + let mainDataSongDate: String +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Model/MainTableModel.swift b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Model/MainTableModel.swift new file mode 100644 index 0000000..fb92082 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Model/MainTableModel.swift @@ -0,0 +1,40 @@ +// +// MainTableModel.swift +// Study3_MusicPlayer +// +// Created by Jaehyeok Lim on 2022/07/02. +// + +import UIKit + +var mainTableViewList = [MainTableViewData]() + +var stillLifeLyricsList = ["이듬해질 녘 꽃 피는 봄", "한여름 밤의 꿈 ", "가을 타 겨울 내릴 눈", "일 년 네 번 또다시 봄", "정들었던 내 젊은 날", "이제는 안녕", "아름답던 우리의 봄 여름 가을 겨울", "\"Four seasons with no reason\"", "비 갠 뒤에 비애 대신 a happy end", "비스듬히 씩 비웃듯 칠색 무늬의 무지개", "철없이 철 지나 철들지 못해 still", "철부지에 철 그른지 오래", "Marchin' 비발디", "차이코프스키,", "오늘의 사계를 맞이해", "마침내, 마치 넷이 못내", "저 하늘만 바라보고서", "사계절 잘 지내고 있어, Good-bye", "떠난 사람 또 나타난 사람", "머리 위 저세상", "난 떠나 영감의 amazon", "지난 밤의 트라우마 다 묻고", "목숨 바쳐 달려올", "새 출발 하는 왕복선", "변할래 전보다는 더욱더", "좋은 사람 더욱더", "더 나은 사람 더욱더", "아침 이슬을 맞고", "내 안에 분노 과거에 묻고", "For life", "울었던 웃었던", "소년과 소녀가 그리워 나", "찬란했던 사랑했던", "그 시절만 자꾸 기억나", "계절은 날이 갈수록 속절없이 흘러", "붉게 물들이고", "파랗게 멍들어 가슴을 훑고", "언젠가 다시 올 그날", "그때를 위하여 그대를 위하여", "아름다울 우리의 봄 여름 가을 겨울", "La la la la la la la la la la la", "La la la la la la la la la la la", "La la la la la la la la la la la", "La la la la la la la la la la la", "이듬해 질 녘 꽃 피는 봄", "한여름 밤의 꿈", "가을 타 겨울 내린 눈", "봄 여름 가을 겨울"] + +var beyondLoveLyricsList = ["Back to the day", "갓 10대가 됐을 때", "그때 내가 널 보지 못했다면", "어땠을까 해", "왜인지 외로워지는 밤에 You say", "흐린 추억 속에 네게 안겨 잠드네", "Yeah 친구들과의 술자리", "나는 또 네 얘기를 꺼내", "보고 싶다는 넋두리에", "친구들 답은 뻔해", "10년도 더 된 애를 사랑할 수 있냬", "이제 그만 잊으래", "근데 그게 잘 안돼", "그래 걔 말마따나", "넌 아담의 사과일 수도", "But 난 신을 안 믿으니까", "네 전화 바로 픽업", "지금 주소 찍어", "어디든 상관없어 다 갈 테니까", "그건 사랑이 아냐", "그건 미련이 아냐", "그냥 정이라고 하자", "임마 네가 뭘 알아", "이건 사랑이 맞아", "분명 약속했단 말이야", "I know I’m wrong", "그 자리에 그대로", "두고 온 기억들을", "더듬고 있을 때면", "You say", "그건 사랑이 아냐", "그건 미련이 아냐", "그냥 정리하고 가자", "아메리카노보단 라떼를", "맛있게 내리던 네 집 앞 카페를", "매일 같이 갔었었던 그때를", "내려줄게 쓰지 않아 이제는", "넌 매일 밤 예뻐 예뻐", "해주며 날 재워 재워", "식어버린 널 데워 태워", "꿈에서 날 깨워 줘", "버려진 기억들 속에서", "쓸만한 컷들을 찾고 있어", "이미 내 곁에 더는 없는 너지만", "난 너를 느낄 수 있어", "닿을 듯 안 닿을 듯", "떠나는 뒷모습이", "왜인지 행복해 보여", "너라도 행복해줘", "그건 사랑이 아냐", "그건 미련이 아냐", "그냥 정이라고 하자", "임마 네가 뭘 알아", "이건 사랑이 맞아", "분명 약속했단 말이야", "I know I’m wrong", "그 자리에 그대로", "두고 온 기억들을", "더듬고 있을 때면", "You say", "그건 사랑이 아냐", "그건 미련이 아냐", "그냥 정리하고 가자", "그건 사랑이 아냐", "그건 미련이 아냐", "그냥 정이라고 하자", "임마 네 말이 맞아", "이건 사랑이 아냐", "그냥 정리하고 가자"] + +var ghostLyricsList = ["Party’s over now", "You’re still hovering", "above my eyes", "I’m yellin’ out loud", "There’s isn’t any voice", "any sound", "Did I make u or not", "Am I mad but Im not", "I can see u clearly but they deny", "Your touch still remain", "on my mouth", "I can still hear your sound", "No doubt no doubt", "I’m so awkward with this emotion", "Something bother me", "there’s no options", "I feel like a shaman or mad man", "Illusion standing on", "all the wall like a", "Ghost", "Oh oh I can see you ghost", "Ghost", "Please don’t leave me my ghost", "You don’t need to hide", "I already know this", "Just let me feel you", "all night long", "You make me feel like a chosen one", "If you want I can sell", "my soul for ya", "Ghost ghost ghost ghost", "I’m waiting for you", "in a room no light", "Then I think I can see", "your shape more bright", "At the corner", "there’s some silhouette", "I’m pretty god damn sure", "it is you my ghost", "I’m perfectly sober", "Don’t treat me like a bad tripper", "I’m perfectly normal", "Don’t judge my symptoms", "need no doctor", "Did I swear u or not", "Can’t remember it’s like", "These days hard to focus", "on something", "Did I tell you or not", "Honestly I’m waiting for", "Tonight tonight", "I’m so awkward with this emotion", "Something bother me", "there’s no options", "I feel like a shaman or mad man", "Illusion standing on", "all the wall like a", "Ghost", "Oh oh I can see you ghost", "Ghost", "Please don’t leave me my ghost", "You don’t need to hide", "I already know this", "Just let me feel you", "all night long", "You make me feel like a chosen one", "If you want I can sell", "my soul for ya", "Ghost ghost ghost ghost", "I’m waiting for you", "in a room no light", "Then I think I can see", "your shape more bright", "At the corner", "there’s some silhouette", "I’m pretty god damn sure", "it is you my ghost"] + +var stillLifeLyricsTimeList: [[Int]] = [[0, 1], [0, 5], [0, 9], [0, 13], [0, 17], [0, 22], [0, 26] , [0, 32], [0, 33] , [0, 37], + [0, 41] , [0, 43], [0, 45], [0, 46], [0, 47], [0, 48], [0, 50], [0, 52], [0, 54], [0, 56], [0, 57], [0, 58], + [1, 0], [1, 1], [1, 2], [1, 4], [1, 5], [1, 7], [1, 10] , [1, 14], [1, 21], [1, 25], [1, 29], [1, 34], [1, 39], + [1, 47], [1, 49], [1, 55], [1, 59], [2, 3], [2, 15], [2, 24], [2, 32], [2, 40] , [2, 48], [2, 52], [2, 56], [3, 0]] + +var beyondLoveLyricsTimeList: [[Int]] = [[0, 11], [0, 13], [0, 16], [0, 18], [0, 22], [0, 27], [0, 32], [0, 34], [0, 35], [0, 37], [0, 38], [0, 41], [0, 42], + [0, 43], [0, 45], [0, 47], [0, 49], [0, 51], [0, 52], [1, 0], [1, 2], [1, 3], [1, 6], [1, 7], [1, 8], [1, 11], + [1, 12], [1, 13], [1, 14], [1, 16], [1, 17], [1, 18], [1, 20], [1, 22], [1, 24], [1, 27], [1, 30], [1, 33], [1, 35], + [1, 38], [1, 41], [1, 44], [1, 46], [1, 49], [1, 52], [1, 55], [1, 57], [2, 0], [2, 3], [2, 12], [2, 13], [2, 14], + [2, 17], [2, 18], [2, 20], [2, 22], [2, 23], [2, 24], [2, 26], [2, 27], [2, 28], [2, 29], [2, 31], [2, 55], [2, 57], + [2, 58], [3, 1], [3, 2], [3, 4]] + +var ghostLyricsTimeList: [[Int]] = [[0, 18], [0, 20], [0, 22], [0, 26], [0, 28], [0, 30], [0, 32], [0, 34], [0, 36], [0, 39], [0, 41], [0, 42], [0, 44], [0, 49], + [0, 53], [0, 54], [0, 56], [1, 0], [1, 1], [1, 4], [1, 8], [1, 12], [1, 16], [1, 19], [1, 21], [1, 23], [1, 25], [1, 27], [1, 32], + [1, 33], [1, 36], [1, 51], [1, 52], [1, 55], [1, 56], [1, 59], [2, 0], [2, 3], [2, 4], [2, 6], [2, 8], [2, 13], [2, 16], [2, 18], + [2, 20], [2, 22], [2, 23], [2, 25], [2, 27], [2, 29], [2, 31], [2, 36], [2, 40], [2, 42], [2, 44], [2, 48], [2, 49], [2, 52], [2, 56], + [2, 59], [3, 3], [3, 7], [3, 8], [3, 11], [3, 13], [3, 15], [3, 19], [3, 21], [3, 23], [4, 10], [4, 11], [4, 13], [4, 14], [4, 17], + [4, 18], [4, 21], [4, 22]] + +struct MainTableViewData { + let lyrics: String + var state: Int +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/SceneDelegate.swift b/JH/Study3_MusicPlayer/Study3_MusicPlayer/SceneDelegate.swift new file mode 100644 index 0000000..37167ec --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/SceneDelegate.swift @@ -0,0 +1,55 @@ +// +// SceneDelegate.swift +// Study3_MusicPlayer +// +// Created by Jaehyeok Lim on 2022/06/30. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + guard let windowScene = (scene as? UIWindowScene) else { return } + window = UIWindow(windowScene: windowScene) + window?.rootViewController = MainViewController() + window?.makeKeyAndVisible() + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // 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() + } + + +} + diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Study3_MusicPlayer.xcdatamodeld/.xccurrentversion b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Study3_MusicPlayer.xcdatamodeld/.xccurrentversion new file mode 100644 index 0000000..f3f46bc --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Study3_MusicPlayer.xcdatamodeld/.xccurrentversion @@ -0,0 +1,8 @@ + + + + + _XCCurrentVersionName + Study3_MusicPlayer.xcdatamodel + + diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/Study3_MusicPlayer.xcdatamodeld/Study3_MusicPlayer.xcdatamodel/contents b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Study3_MusicPlayer.xcdatamodeld/Study3_MusicPlayer.xcdatamodel/contents new file mode 100644 index 0000000..50d2514 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/Study3_MusicPlayer.xcdatamodeld/Study3_MusicPlayer.xcdatamodel/contents @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/View/MainViewCollectionCell.swift b/JH/Study3_MusicPlayer/Study3_MusicPlayer/View/MainViewCollectionCell.swift new file mode 100644 index 0000000..db748bf --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/View/MainViewCollectionCell.swift @@ -0,0 +1,134 @@ +// +// MainViewCollectionCell.swift +// Study3_MusicPlayer +// +// Created by Jaehyeok Lim on 2022/06/30. +// + +import UIKit +import SnapKit + +class MainViewCollectionCell: UICollectionViewCell { + static let identifier = "MainViewCollectionCell" + + lazy var item: UIImageView = { + let item = UIImageView() + + return item + }() + + lazy var mainCellTitleImage: UIButton = { + let mainCellTitleImage = UIButton() + + return mainCellTitleImage + }() + + lazy var mainCellTitleLabel: UILabel = { + let mainCellTitleLabel = UILabel() + + mainCellTitleLabel.textColor = UIColor.cellTitleTextColor + mainCellTitleLabel.font = UIFont.boldSystemFont(ofSize: 30) + mainCellTitleLabel.textAlignment = .center + + return mainCellTitleLabel + }() + + lazy var mainCellSingerLabel: UILabel = { + let mainCellSingerLabel = UILabel() + + mainCellSingerLabel.textColor = UIColor.cellTextColor + mainCellSingerLabel.font = UIFont.boldSystemFont(ofSize: 15) + mainCellSingerLabel.textAlignment = .center + + return mainCellSingerLabel + }() + + lazy var mainCellAlbumLabel: UILabel = { + let mainCellAlbumLabel = UILabel() + + mainCellAlbumLabel.textColor = UIColor.white + mainCellAlbumLabel.font = UIFont.boldSystemFont(ofSize: 11) + mainCellAlbumLabel.textAlignment = .center + + return mainCellAlbumLabel + }() + + lazy var mainCellSongDate: UILabel = { + let mainCellSongDate = UILabel() + + mainCellSongDate.textColor = UIColor.cellTextColor + mainCellSongDate.font = UIFont.boldSystemFont(ofSize: 11) + mainCellSongDate.textAlignment = .center + + return mainCellSongDate + }() + + func setConstraint() { + + contentView.backgroundColor = .blue + let viewList: [UIView] = [item, mainCellTitleLabel, mainCellSingerLabel, mainCellTitleImage, mainCellAlbumLabel, mainCellSongDate] + + for view in viewList { + addSubview(view) + } + + item.snp.makeConstraints { make in + make.top.leading.trailing.bottom.equalTo(contentView) + } + + mainCellTitleImage.snp.makeConstraints { make in + make.center.equalTo(item) + make.size.equalTo(CGSize(width: 200, height: 200)) + } + + mainCellTitleLabel.snp.makeConstraints { make in + make.top.equalTo(contentView).offset(40) + make.leading.right.equalTo(0) + make.width.equalTo(contentView) + } + + mainCellSingerLabel.snp.makeConstraints { make in + make.top.equalTo(mainCellTitleLabel).offset(37) + make.leading.right.equalTo(0) + make.width.equalTo(contentView) + } + + mainCellAlbumLabel.snp.makeConstraints { make in + make.top.equalTo(mainCellTitleLabel).offset(300) + make.leading.right.equalTo(0) + make.width.equalTo(contentView) + } + + mainCellSongDate.snp.makeConstraints { make in + make.top.equalTo(mainCellAlbumLabel).offset(-20) + make.leading.right.equalTo(0) + make.width.equalTo(contentView) + } + + let blurEffect = UIBlurEffect(style: .regular) + let visualEffectView = UIVisualEffectView(effect: blurEffect) + visualEffectView.frame = self.contentView.frame + self.item.addSubview(visualEffectView) + + mainCellTitleImage.addTarget(MainViewController().mainCellTitleImageAction(_:), action: #selector(MainViewController().mainCellTitleImageAction(_:)), for: .touchUpInside) + } + + func transportDataToCell(titleImage: UIImage, titleText: String, singerText: String, albumText: String, dateText: String) { + item.image = titleImage +// mainCellTitleImage.imageView?.image = titleImage + mainCellTitleImage.setImage(titleImage, for: .normal) + mainCellTitleLabel.text = titleText + mainCellSingerLabel.text = singerText + mainCellAlbumLabel.text = "[" + albumText + "]" + mainCellSongDate.text = "BORN:" + dateText + } + + override init(frame: CGRect) { + super.init(frame: frame) + setConstraint() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/View/MainViewTableCell.swift b/JH/Study3_MusicPlayer/Study3_MusicPlayer/View/MainViewTableCell.swift new file mode 100644 index 0000000..5515e73 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/View/MainViewTableCell.swift @@ -0,0 +1,50 @@ +// +// MainViewTableCell.swift +// Study3_MusicPlayer +// +// Created by Jaehyeok Lim on 2022/07/02. +// + +import UIKit +import SnapKit + +class MainViewTableCell: UITableViewCell { + let identifier = "MainViewTableCell" + + lazy var lyricsLabel: UILabel = { + let lyricsLabel = UILabel() + + lyricsLabel.textColor = .systemGray + lyricsLabel.font = UIFont.systemFont(ofSize: 15) + lyricsLabel.textAlignment = .center + + return lyricsLabel + }() + + func setConstraint() { + addSubview(lyricsLabel) + + lyricsLabel.snp.makeConstraints { make in + make.top.equalToSuperview() + make.bottom.equalToSuperview() + make.width.equalTo(contentView) + } + } + + func transportDataToCell(lyricsText: String, index: Int) { + lyricsLabel.text = lyricsText + + if index == 1 { + lyricsLabel.textColor = UIColor.lyricsColor + } else { lyricsLabel.textColor = .darkGray } + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setConstraint() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayer/ViewController/MainViewController.swift b/JH/Study3_MusicPlayer/Study3_MusicPlayer/ViewController/MainViewController.swift new file mode 100644 index 0000000..8687073 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayer/ViewController/MainViewController.swift @@ -0,0 +1,592 @@ +// +// ViewController.swift +// Study3_MusicPlayer +// +// Created by Jaehyeok Lim on 2022/06/30. +// + +import UIKit +import SnapKit +import AVFoundation +import MediaPlayer + +public extension UIColor { + static let textColor = UIColor(named: "commonTextColor") + static let backgroundColor = UIColor(named: "backgroundColor") + static let cellTextColor = UIColor(named: "cellTextColor") + static let cellTitleTextColor = UIColor(named: "cellTitleTextColor") + static let lyricsColor = UIColor(named: "lyricsFocusingColor") + +} + +class MainViewController: UIViewController, AVAudioPlayerDelegate { + + var musicPlayer = AVAudioPlayer() + var timer = Timer() + let currentTimeLabel = UILabel() + let currentSongMaxTimeLabel = UILabel() + let center = MPRemoteCommandCenter.shared() + var currentTime: Double = 0 + var currentSongIndexPath: Int = -1 + var repeatButtonStateNumber: Int = .zero + var currentVolumeStateNumber = 0 + var lyricsSyncIndex = 0 + + let collectionView: UICollectionView = { + let flowLayout = UICollectionViewFlowLayout() + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout) + + collectionView.register(MainViewCollectionCell.self, forCellWithReuseIdentifier: "MainViewCollectionCell") + collectionView.backgroundColor = UIColor.backgroundColor + collectionView.isPagingEnabled = true + collectionView.showsHorizontalScrollIndicator = false + + flowLayout.minimumLineSpacing = 0 + flowLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) + flowLayout.scrollDirection = .horizontal + + return collectionView + }() + + let tableView: UITableView = { + let tableView = UITableView() + + tableView.register(MainViewTableCell.self, forCellReuseIdentifier: "MainViewTableCell") + tableView.backgroundColor = UIColor.backgroundColor + + return tableView + }() + + let musicPlayOrStopButton: UIButton = { + let musicPlayOrStopButton = UIButton() + + musicPlayOrStopButton.setImage(UIImage(systemName: "play.fill"), for: .normal) + musicPlayOrStopButton.contentHorizontalAlignment = .fill + musicPlayOrStopButton.contentVerticalAlignment = .fill + musicPlayOrStopButton.tintColor = UIColor.textColor + + return musicPlayOrStopButton + }() + + let playSlider: UISlider = { + let playSlider = UISlider() + + playSlider.setThumbImage(UIImage(), for: .normal) + + return playSlider + }() + + let repeatButton: UIButton = { + let repeatButton = UIButton() + + repeatButton.setImage(UIImage(systemName: "repeat"), for: .normal) + repeatButton.contentHorizontalAlignment = .fill + repeatButton.contentVerticalAlignment = .fill + repeatButton.tintColor = UIColor.systemGray + + return repeatButton + }() + + let backgroud: UIView = { + let background = UIView() + + background.backgroundColor = UIColor.clear + + return background + }() + + let volumeButton: UIButton = { + let lyricsEnlargeButton = UIButton() + + lyricsEnlargeButton.setImage(UIImage(systemName: "speaker.wave.3.fill"), for: .normal) + lyricsEnlargeButton.contentHorizontalAlignment = .fill + lyricsEnlargeButton.contentVerticalAlignment = .fill + + return lyricsEnlargeButton + }() + + override func viewDidLoad() { + super.viewDidLoad() + initList() + configureLayout() + MPRemoteCommandCenterAddTarget() + tableView.rowHeight = 25; + tableView.separatorStyle = .none + tableView.showsVerticalScrollIndicator = false + } + + override func viewWillAppear(_ animated: Bool) { + collectionView.reloadData() + } + + func configureLayout() { + view.backgroundColor = UIColor.backgroundColor + + let mainViewTitleLabel = UILabel() + let forwardEndButton = UIButton() + let backwardEndButton = UIButton() + let categoryButton = UIButton() + + let viewList: [UIView] = [collectionView, tableView,mainViewTitleLabel, musicPlayOrStopButton, forwardEndButton, backwardEndButton, playSlider, repeatButton, currentTimeLabel, currentSongMaxTimeLabel, volumeButton, categoryButton] + + for view in viewList { + self.view.addSubview(view) + } + + collectionView.delegate = self + collectionView.dataSource = self + + collectionView.snp.makeConstraints { make in + make.top.equalTo(view).offset(140) + make.bottom.equalTo(view).offset(-290) + make.leading.equalTo(view) + make.trailing.equalTo(view) + } + + tableView.delegate = self + tableView.dataSource = self + + tableView.snp.makeConstraints { make in + make.top.equalTo(currentTimeLabel).offset(15) + make.bottom.equalTo(musicPlayOrStopButton).offset(-60) + make.leading.trailing.equalToSuperview() + } + + mainViewTitleLabel.text = "MUZiK!" + mainViewTitleLabel.textColor = UIColor.textColor + mainViewTitleLabel.font = UIFont.boldSystemFont(ofSize: 40) + mainViewTitleLabel.layer.borderColor = UIColor.red.cgColor + mainViewTitleLabel.textAlignment = .center + + mainViewTitleLabel.snp.makeConstraints { make in + make.top.equalTo(view).offset(70) + make.width.equalTo(view) + } + + musicPlayOrStopButton.snp.makeConstraints { make in + make.bottom.equalTo(view).offset(-60) + make.leading.equalTo(175) + make.size.equalTo(CGSize(width: 40, height: 40)) + } + + forwardEndButton.setImage(UIImage(systemName: "forward.end.fill"), for: .normal) + forwardEndButton.contentHorizontalAlignment = .fill + forwardEndButton.contentVerticalAlignment = .fill + forwardEndButton.tintColor = UIColor.textColor + + forwardEndButton.snp.makeConstraints { make in + make.bottom.equalTo(musicPlayOrStopButton).offset(-5) + make.leading.equalTo(musicPlayOrStopButton).offset(100) + make.size.equalTo(CGSize(width: 30, height: 30)) + } + + backwardEndButton.setImage(UIImage(systemName: "backward.end.fill"), for: .normal) + backwardEndButton.contentHorizontalAlignment = .fill + backwardEndButton.contentVerticalAlignment = .fill + backwardEndButton.tintColor = UIColor.textColor + + backwardEndButton.snp.makeConstraints { make in + make.bottom.equalTo(musicPlayOrStopButton).offset(-5) + make.trailing.equalTo(musicPlayOrStopButton).offset(-100) + make.size.equalTo(CGSize(width: 30, height: 30)) + } + + playSlider.snp.makeConstraints { make in +// make.top.equalToSuperview().offset(510) + make.top.equalToSuperview().offset(555) + make.height.equalTo(10) + make.width.equalTo(view) + } + + repeatButton.snp.makeConstraints { make in + make.bottom.equalTo(backwardEndButton) + make.trailing.equalTo(backwardEndButton).offset(-58) + make.size.equalTo(CGSize(width: 35, height: 28)) + } + + currentTimeLabel.text = "" + currentTimeLabel.textColor = UIColor.systemBlue + currentTimeLabel.font = UIFont.boldSystemFont(ofSize: 13) + + currentTimeLabel.snp.makeConstraints { make in + make.top.equalTo(playSlider).offset(10) + make.leading.equalTo(2) + } + + currentSongMaxTimeLabel.text = "" + currentSongMaxTimeLabel.textColor = UIColor.darkGray + currentSongMaxTimeLabel.font = UIFont.boldSystemFont(ofSize: 13) + + currentSongMaxTimeLabel.snp.makeConstraints { make in + make.top.equalTo(playSlider).offset(10) + make.trailing.equalTo(-2) + } + + volumeButton.snp.makeConstraints { make in + make.bottom.equalTo(backwardEndButton).offset(-2.5) + make.trailing.equalTo(forwardEndButton).offset(61) + make.size.equalTo(CGSize(width: 35, height: 25)) + } + + categoryButton.setImage(UIImage(systemName: "text.justify"), for: .normal) + categoryButton.contentHorizontalAlignment = .fill + categoryButton.contentVerticalAlignment = .fill + categoryButton.tintColor = UIColor.darkGray + + categoryButton.snp.makeConstraints { make in + make.top.equalTo(mainViewTitleLabel).offset(8.2) + make.trailing.equalTo(view).offset(-12) + make.size.equalTo(CGSize(width: 30, height: 30)) + } + + musicPlayOrStopButton.addTarget(self, action: #selector(musicPlayOrStopButtonAction(_:)), for: .touchUpInside) + backwardEndButton.addTarget(self, action: #selector(backwardEndButtonAction(_:)), for: .touchUpInside) + forwardEndButton.addTarget(self, action: #selector(forwardEndButtonAction(_:)), for: .touchUpInside) + playSlider.addTarget(self, action: #selector(sliderValueControl), for: .touchUpInside) + repeatButton.addTarget(self, action: #selector(repeatButtonAction(_:)), for: .touchUpInside) + volumeButton.addTarget(self, action: #selector(volumeButtonAction(_:)), for: .touchUpInside) + } + + func MPRemoteCommandCenterAddTarget() { + + center.playCommand.addTarget { (_) -> MPRemoteCommandHandlerStatus in + self.startOrStopFunction() + return .success + } + + center.pauseCommand.addTarget { (_) -> MPRemoteCommandHandlerStatus in + self.startOrStopFunction() + return .success + } + + center.nextTrackCommand.addTarget { (_) -> MPRemoteCommandHandlerStatus in + self.forwardEndFunction() + return .success + } + + center.previousTrackCommand.addTarget { (_) -> MPRemoteCommandHandlerStatus in + self.backwardEndFunction() + return .success + } + } + + @objc func mainCellTitleImageAction(_ sender: UIButton) { + let point = sender.convert(CGPoint.zero, to: collectionView) + guard let indexPath = collectionView.indexPathForItem(at: point) else { return } + + initPlayer(songName: mainCollectionViewList[indexPath.row].mainDataTitleLabel, index: indexPath.row) + + makeAndFireTimer() + musicPlayOrStopButton.setImage(UIImage(systemName: "pause.fill"), for: .normal) + } + + @objc func musicPlayOrStopButtonAction(_ sender: UIButton) { + startOrStopFunction() + } + + @objc func backwardEndButtonAction(_ sender: UIButton) { + backwardEndFunction() + } + + @objc func forwardEndButtonAction(_ sender: UIButton) { + forwardEndFunction() + } + + @objc func repeatButtonAction(_ sender: UIButton) { + + if repeatButtonStateNumber == 2 { + repeatButtonStateNumber = 0 + + repeatButton.tintColor = UIColor.systemGray + repeatButton.setImage(UIImage(systemName: "repeat"), for: .normal) + + } else { + repeatButtonStateNumber += 1 + + if repeatButtonStateNumber == 2 { + repeatButton.setImage(UIImage(systemName: "repeat.1"), for: .normal) + } + + repeatButton.tintColor = UIColor.systemBlue + } + } + + @objc func sliderValueControl(_ sender: UISlider) { + updateTimeLabelText(currentTime: TimeInterval(sender.value)) + + if sender.isTracking { return } + musicPlayer.currentTime = TimeInterval(sender.value); + } + + @objc func volumeButtonAction(_ sender: UISlider) { + if currentVolumeStateNumber == 0 { + currentVolumeStateNumber = 1 + volumeButton.setImage(UIImage(systemName: "speaker.slash.fill"), for: .normal) + volumeButton.tintColor = UIColor.systemGray + + } else { + currentVolumeStateNumber = 0 + volumeButton.setImage(UIImage(systemName: "speaker.wave.3.fill"), for: .normal) + volumeButton.tintColor = UIColor.systemBlue + } + + musicPlayer.volume = abs(Float(currentVolumeStateNumber - 1)) + } + + func initList() { + let item: MainCollectionViewData = MainCollectionViewData(mainDataTitleImage: UIImage(named: "stillLifeAlbumCoverImage")!, mainDataTitleLabel: "Still Life", mainDataSingerLabel: "BIGBANG", mainDataAlbumLabel: "STILL LIFE", mainDataSongDate: "2022") + + let itemTwo: MainCollectionViewData = MainCollectionViewData(mainDataTitleImage: UIImage(named: "BeyondLoveAlbumCover")!, mainDataTitleLabel: "Beyond Love", mainDataSingerLabel: "BIG Naughty (서동현)", mainDataAlbumLabel: "Beyond", mainDataSongDate: "2022") + + let itemThree: MainCollectionViewData = MainCollectionViewData(mainDataTitleImage: UIImage(named: "GhostAlbumCoverImage")!, mainDataTitleLabel: "Ghost", mainDataSingerLabel: "Zior Park", mainDataAlbumLabel: "SYNDROMEZ", mainDataSongDate: "2021") + + let itemList: [MainCollectionViewData] = [item, itemTwo, itemThree] + + for items in itemList { + mainCollectionViewList.append(items) + } + } + + func initPlayer(songName: String, index: Int) { + // Audio Session 설정 + let audioSession = AVAudioSession.sharedInstance() + + do { + try audioSession.setCategory(.playback, mode: .default, options: []) + } catch let error as NSError { + print("audioSession 설정 오류 : \(error.localizedDescription)") + } + + // 음악 파일 가져오기 + guard let soundAsset: NSDataAsset = NSDataAsset(name: songName) else { + print("음악 파일이 없습니다.") + return + } + + // audio player를 초기화합니다. + do { + try musicPlayer = AVAudioPlayer(data: soundAsset.data) + musicPlayer.delegate = self + currentSongIndexPath = index + remoteCommandInfoCenterSetting() + initLyrics(index: currentSongIndexPath) + musicPlayer.volume = 1 + self.lyricsSyncIndex = 0 + tableView.reloadData() + musicPlayer.play() + + } catch let error as NSError { + print("플레이어 초기화 오류 발생 : \(error.localizedDescription)") + } + + playSlider.maximumValue = Float(musicPlayer.duration); + playSlider.minimumValue = 0; + playSlider.value = Float(musicPlayer.currentTime); + } + + func initLyrics (index: Int) { + mainTableViewList.removeAll() + + if index == 0 { + for lyrics in stillLifeLyricsList { + let item: MainTableViewData = MainTableViewData(lyrics: lyrics, state: 0) + mainTableViewList.append(item) + } + + } else if index == 1 { + + for lyrics in beyondLoveLyricsList { + let item: MainTableViewData = MainTableViewData(lyrics: lyrics, state: 0) + mainTableViewList.append(item) + } + + } else if index == 2 { + + for lyrics in ghostLyricsList { + let item: MainTableViewData = MainTableViewData(lyrics: lyrics, state: 0) + mainTableViewList.append(item) + } + } + } + + func startOrStopFunction() { + if musicPlayOrStopButton.imageView?.image == UIImage(systemName: "play.fill") { + musicPlayer.play() + + musicPlayOrStopButton.setImage(UIImage(systemName: "pause.fill"), for: .normal) + + } else { + currentTime = musicPlayer.currentTime + musicPlayer.pause() + musicPlayOrStopButton.setImage(UIImage(systemName: "play.fill"), for: .normal) + } + } + + func backwardEndFunction() { + if currentSongIndexPath == 0 { + initPlayer(songName: mainCollectionViewList[mainCollectionViewList.count - 1].mainDataTitleLabel, index: mainCollectionViewList.count - 1) + + } else if currentSongIndexPath == -1 { + return + + } else { + initPlayer(songName: mainCollectionViewList[currentSongIndexPath - 1].mainDataTitleLabel, index: currentSongIndexPath - 1) + } + + collectionView.scrollToItem(at: IndexPath(item: currentSongIndexPath, section: 0), at: .init(rawValue: 0), animated: true) + } + + func forwardEndFunction() { + if currentSongIndexPath == (mainCollectionViewList.count - 1) { + initPlayer(songName: mainCollectionViewList[0].mainDataTitleLabel, index: 0) + + } else if currentSongIndexPath == -1 { + return + + } else { + initPlayer(songName: mainCollectionViewList[currentSongIndexPath + 1].mainDataTitleLabel, index: currentSongIndexPath + 1) + } + + collectionView.scrollToItem(at: IndexPath(item: currentSongIndexPath, section: 0), at: .init(rawValue: 0), animated: true) + } + + func oneSongRepeatFunction() { + initPlayer(songName: mainCollectionViewList[currentSongIndexPath].mainDataTitleLabel, index: currentSongIndexPath) + } + + func makeAndFireTimer(){ + timer = Timer.scheduledTimer(withTimeInterval : 0.01, repeats: true, block : { [unowned self] (timer : Timer) in + if playSlider.isTracking { return }; + updateTimeLabelText(currentTime: musicPlayer.currentTime); + playSlider.value = Float(musicPlayer.currentTime); + }) + + timer.fire(); + } + + func updateTimeLabelText(currentTime:TimeInterval){ + let currentTimeMinute : Int = Int(currentTime / 60) + let currentTimeSecond : Int = Int(currentTime.truncatingRemainder(dividingBy: 60)) + + let durationTimeMinute : Int = Int(musicPlayer.duration / 60) + let durationTimeSecond : Int = Int(musicPlayer.duration.truncatingRemainder(dividingBy: 60)) + + let currentTimeText : String = String(format : "%02ld:%02ld", currentTimeMinute, currentTimeSecond); + let durationTimeText : String = String(format : "%02ld:%02ld", durationTimeMinute, durationTimeSecond); + + lyricsFocusing(minute: currentTimeMinute, second: currentTimeSecond) + currentTimeLabel.text = currentTimeText + currentSongMaxTimeLabel.text = durationTimeText + } + + func lyricsFocusing(minute: Int, second: Int) { + + if currentSongIndexPath == 0 { + for index in lyricsSyncIndex...stillLifeLyricsTimeList.count - 1 { + if minute == stillLifeLyricsTimeList[index][0] && second == stillLifeLyricsTimeList[index][1] { + if index % 6 == 0 { tableView.scrollToRow(at: [0, index], at: .top, animated: false) } + mainTableViewList[index].state = 1 + if lyricsSyncIndex != 0 { mainTableViewList[index-1].state = 0 } + self.lyricsSyncIndex = index + tableView.reloadData() + } + } + + } else if currentSongIndexPath == 1 { + for index in lyricsSyncIndex...beyondLoveLyricsTimeList.count - 1 { + if minute == beyondLoveLyricsTimeList[index][0] && second == beyondLoveLyricsTimeList[index][1] { + if index % 6 == 0 { tableView.scrollToRow(at: [0, index], at: .top, animated: false) } + mainTableViewList[index].state = 1 + if lyricsSyncIndex != 0 { mainTableViewList[index-1].state = 0 } + self.lyricsSyncIndex = index + tableView.reloadData() + print(lyricsSyncIndex) + } + } + } else if currentSongIndexPath == 2 { + for index in lyricsSyncIndex...ghostLyricsTimeList.count - 1 { + if minute == ghostLyricsTimeList[index][0] && second == ghostLyricsTimeList[index][1] { + if index % 6 == 0 { tableView.scrollToRow(at: [0, index], at: .top, animated: false) } + mainTableViewList[index].state = 1 + if lyricsSyncIndex != 0 { mainTableViewList[index-1].state = 0 } + self.lyricsSyncIndex = index + tableView.reloadData() + print(lyricsSyncIndex) + } + } + } + } + + func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { + if repeatButtonStateNumber == 1 { + forwardEndFunction() + + } else if repeatButtonStateNumber == 2 { + oneSongRepeatFunction() + + } else { + musicPlayOrStopButton.setImage(UIImage(systemName: "play.fill"), for: .normal) + } + } + + func remoteCommandInfoCenterSetting() { + UIApplication.shared.beginReceivingRemoteControlEvents() + let center = MPNowPlayingInfoCenter.default() + var nowPlayingInfo = center.nowPlayingInfo ?? [String: Any]() + let image: UIImage = mainCollectionViewList[currentSongIndexPath].mainDataTitleImage + + nowPlayingInfo[MPMediaItemPropertyTitle] = mainCollectionViewList[currentSongIndexPath].mainDataTitleLabel + nowPlayingInfo[MPMediaItemPropertyArtist] = mainCollectionViewList[currentSongIndexPath].mainDataSingerLabel + + nowPlayingInfo[MPMediaItemPropertyArtwork] = MPMediaItemArtwork(boundsSize: image.size, requestHandler: { + size in return image + }) + + nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = musicPlayer.duration + nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = musicPlayer.rate + nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = musicPlayer.currentTime + + center.nowPlayingInfo = nowPlayingInfo + } +} + +extension MainViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + + return mainCollectionViewList.count + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainViewCollectionCell", for: indexPath) as? MainViewCollectionCell else { return UICollectionViewCell() } + let mainListData = mainCollectionViewList[indexPath.row] + + cell.transportDataToCell(titleImage: mainListData.mainDataTitleImage, titleText: mainListData.mainDataTitleLabel, singerText: mainListData.mainDataSingerLabel, albumText: mainListData.mainDataAlbumLabel, dateText: mainListData.mainDataSongDate) + + return cell + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + return CGSize(width: view.frame.width, height: view.frame.height - 430) + } + +// func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { +// + // Save start time view at indexPath. +// } +} + +extension MainViewController: UITableViewDelegate, UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return mainTableViewList.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let cell = tableView.dequeueReusableCell(withIdentifier: "MainViewTableCell", for: indexPath) as? MainViewTableCell else { return UITableViewCell() } + let mainListData = mainTableViewList[indexPath.row] + + cell.transportDataToCell(lyricsText: mainListData.lyrics, index: mainListData.state) + cell.selectedBackgroundView = backgroud + + return cell + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayerTests/Study3_MusicPlayerTests.swift b/JH/Study3_MusicPlayer/Study3_MusicPlayerTests/Study3_MusicPlayerTests.swift new file mode 100644 index 0000000..e5198ac --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayerTests/Study3_MusicPlayerTests.swift @@ -0,0 +1,36 @@ +// +// Study3_MusicPlayerTests.swift +// Study3_MusicPlayerTests +// +// Created by Jaehyeok Lim on 2022/06/30. +// + +import XCTest +@testable import Study3_MusicPlayer + +class Study3_MusicPlayerTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayerUITests/Study3_MusicPlayerUITests.swift b/JH/Study3_MusicPlayer/Study3_MusicPlayerUITests/Study3_MusicPlayerUITests.swift new file mode 100644 index 0000000..3717afe --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayerUITests/Study3_MusicPlayerUITests.swift @@ -0,0 +1,41 @@ +// +// Study3_MusicPlayerUITests.swift +// Study3_MusicPlayerUITests +// +// Created by Jaehyeok Lim on 2022/06/30. +// + +import XCTest + +class Study3_MusicPlayerUITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } +} diff --git a/JH/Study3_MusicPlayer/Study3_MusicPlayerUITests/Study3_MusicPlayerUITestsLaunchTests.swift b/JH/Study3_MusicPlayer/Study3_MusicPlayerUITests/Study3_MusicPlayerUITestsLaunchTests.swift new file mode 100644 index 0000000..7ea6646 --- /dev/null +++ b/JH/Study3_MusicPlayer/Study3_MusicPlayerUITests/Study3_MusicPlayerUITestsLaunchTests.swift @@ -0,0 +1,32 @@ +// +// Study3_MusicPlayerUITestsLaunchTests.swift +// Study3_MusicPlayerUITests +// +// Created by Jaehyeok Lim on 2022/06/30. +// + +import XCTest + +class Study3_MusicPlayerUITestsLaunchTests: XCTestCase { + + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } + + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +}