├── Screenshots └── ShazamClone.gif ├── ShazamClone ├── Assets.xcassets │ ├── Contents.json │ ├── AccentColor.colorset │ │ └── Contents.json │ └── AppIcon.appiconset │ │ └── Contents.json ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json ├── ShazamCloneApp.swift ├── Presentation │ ├── Model │ │ └── Song.swift │ └── Shazam │ │ └── ShazamViewModel.swift ├── ContentView.swift ├── UI │ ├── NoResult │ │ └── NoResultView.swift │ ├── SongDetail │ │ └── SongDetailView.swift │ └── Shazam │ │ └── ShazamView.swift └── Info.plist ├── ShazamClone.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcuserdata │ └── emmanuelkehinde.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── project.pbxproj └── README.md /Screenshots/ShazamClone.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emmanuelkehinde/ShazamClone/HEAD/Screenshots/ShazamClone.gif -------------------------------------------------------------------------------- /ShazamClone/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ShazamClone/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ShazamClone.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ShazamClone/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ShazamClone.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ShazamClone/ShazamCloneApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShazamCloneApp.swift 3 | // ShazamClone 4 | // 5 | // Created by Emmanuel Kehinde on 03/07/2021. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct ShazamCloneApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ShazamClone/Presentation/Model/Song.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Song.swift 3 | // ShazamClone 4 | // 5 | // Created by Emmanuel Kehinde on 03/07/2021. 6 | // 7 | 8 | import Foundation 9 | 10 | struct Song { 11 | let title: String 12 | let artist: String 13 | let genres: [String] 14 | let artworkUrl: URL? 15 | let appleMusicUrl: URL? 16 | } 17 | -------------------------------------------------------------------------------- /ShazamClone/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ShazamClone 4 | // 5 | // Created by Emmanuel Kehinde on 03/07/2021. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | ShazamView().environmentObject(ShazamViewModel()) 13 | } 14 | } 15 | 16 | struct ContentView_Previews: PreviewProvider { 17 | static var previews: some View { 18 | ContentView() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ShazamClone.xcodeproj/xcuserdata/emmanuelkehinde.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ShazamClone.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ShazamClone 2 | A simple Shazam clone using ShazamKit, built with SwiftUI. 3 | 4 | 5 | 6 | 11 | 12 |
7 | 8 | 9 | 10 |
13 | 14 | ### Requirements 15 | - iOS 15 16 | - Xcode 13 17 | - Mac OS 11.3 or higher 18 | 19 | ### Tools 20 | - [ShazamKit](https://developer.apple.com/shazamkit/): Lets you enrich your app experience with audio recognition 21 | - [SwiftUI](https://developer.apple.com/xcode/swiftui/): UI Toolkit for building user interfaces in a declarative way. 22 | 23 | ### Blog Post 24 | https://emmanuelkehinde.io/swiftui-building-a-simple-shazam-clone-using-shazamkit/ 25 | -------------------------------------------------------------------------------- /ShazamClone/UI/NoResult/NoResultView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NoResultView.swift 3 | // ShazamClone 4 | // 5 | // Created by Emmanuel Kehinde on 03/07/2021. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct NoResultView: View { 11 | var buttonAction: () -> Void 12 | 13 | var body: some View { 14 | VStack(alignment: .center, spacing: 12) { 15 | Image(systemName: "headphones.circle") 16 | .font(.system(size: 40, weight: .light)) 17 | .foregroundColor(Color.black.opacity(0.8)) 18 | 19 | Text("No Result Found") 20 | .font(.headline) 21 | .foregroundColor(Color.black.opacity(0.8)) 22 | 23 | Button(action: { 24 | buttonAction() 25 | }, label: { 26 | Text("Try Again") 27 | .font(.system(size: 14, weight: .bold, design: .default)) 28 | .foregroundColor(.white) 29 | .frame(width: 200, height: 48, alignment: .center) 30 | .background( 31 | RoundedRectangle(cornerRadius: 24).fill(Color.blue) 32 | .shadow(radius: 1) 33 | ) 34 | }) 35 | } 36 | } 37 | } 38 | 39 | struct NoResultView_Previews: PreviewProvider { 40 | static var previews: some View { 41 | NoResultView(buttonAction: {}) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ShazamClone/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | NSMicrophoneUsageDescription 24 | Allow Shazam Clone access to your microphone to listen to music around you 25 | UIApplicationSceneManifest 26 | 27 | UIApplicationSupportsMultipleScenes 28 | 29 | 30 | UIApplicationSupportsIndirectInputEvents 31 | 32 | UILaunchScreen 33 | 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UIStatusBarStyle 39 | UIStatusBarStyleDarkContent 40 | UISupportedInterfaceOrientations 41 | 42 | UIInterfaceOrientationPortrait 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | UIViewControllerBasedStatusBarAppearance 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /ShazamClone/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /ShazamClone/UI/SongDetail/SongDetailView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SongDetailView.swift 3 | // ShazamClone 4 | // 5 | // Created by Emmanuel Kehinde on 03/07/2021. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SongDetailView: View { 11 | var song: Song 12 | 13 | var body: some View { 14 | ZStack { 15 | GeometryReader { geometry in 16 | VStack { 17 | AsyncImage(url: song.artworkUrl) { phase in 18 | if let image = phase.image { 19 | image.resizable() 20 | .aspectRatio(contentMode: .fill) 21 | .frame(maxHeight: 200) 22 | .clipped() 23 | } else if phase.error != nil { 24 | Color.blue 25 | } else { 26 | ProgressView() 27 | } 28 | } 29 | .frame(height: 200, alignment: .center) 30 | 31 | VStack(alignment: .leading) { 32 | Text(song.title) 33 | .font(.headline) 34 | .foregroundColor(Color.black) 35 | 36 | Text(song.artist) 37 | .font(.subheadline) 38 | .foregroundColor(Color.black) 39 | 40 | ScrollView(.horizontal, showsIndicators: false, content: { 41 | HStack { 42 | ForEach(0.. = [] 19 | @EnvironmentObject private var shazamViewModel: ShazamViewModel 20 | 21 | var body: some View { 22 | ZStack { 23 | Color.white 24 | 25 | ZStack { 26 | VStack(spacing: 20) { 27 | if shouldShowRippleView { 28 | RippleView( 29 | style: .solid, 30 | rippleCount: 5, 31 | tintColor: Color.blue, 32 | timeIntervalBetweenRipples: 0.18 33 | ) 34 | .padding(.horizontal, 48) 35 | } 36 | 37 | if shouldShowNoResultView { 38 | NoResultView { 39 | onRecordButtonTapped() 40 | } 41 | } 42 | 43 | if shouldShowRecordButton { 44 | recordButton 45 | .alert(isPresented: $shouldShowRecordPermissionAlert, content: { 46 | permissionAlert 47 | }) 48 | } 49 | 50 | if foundSong != nil { 51 | VStack { 52 | withAnimation(.easeInOut) { 53 | SongDetailView(song: foundSong) 54 | } 55 | Spacer() 56 | recordButton 57 | } 58 | .padding(.vertical, 64) 59 | } 60 | 61 | } 62 | 63 | VStack { 64 | HStack { 65 | Spacer() 66 | infoButton 67 | .alert(isPresented: $shouldShowInfoAlert, content: { 68 | infoAlert 69 | }) 70 | } 71 | .padding(EdgeInsets(top: 16, leading: 0, bottom: 0, trailing: 32)) 72 | 73 | Spacer() 74 | } 75 | 76 | VStack { 77 | Spacer() 78 | footerText.padding(.bottom, 16) 79 | } 80 | } 81 | .padding(EdgeInsets(top: Constants.topInset, leading: 0, bottom: Constants.bottomInset, trailing: 0)) 82 | } 83 | .onAppear(perform: { 84 | bindViewModel() 85 | }) 86 | .onDisappear(perform: { 87 | shazamViewModel.stopListening() 88 | }) 89 | .ignoresSafeArea() 90 | } 91 | 92 | private var infoAlert: Alert { 93 | Alert( 94 | title: Text("Shazam Clone"), 95 | message: Text("Tap the record button to listen to music around you"), 96 | dismissButton: .default(Text("OK")) 97 | ) 98 | } 99 | 100 | private var permissionAlert: Alert { 101 | Alert( 102 | title: Text("Microphone access not allowed"), 103 | message: Text("Turn on microphone access to listen to music around you"), 104 | primaryButton: .default( 105 | Text("Go to Setting"), 106 | action: { 107 | goToPermissionSettings() 108 | } 109 | ), 110 | secondaryButton: .cancel(Text("Close")) 111 | ) 112 | } 113 | 114 | @ViewBuilder 115 | private var infoButton: some View { 116 | Button(action: { 117 | shazamViewModel.showInfo() 118 | }, label: { 119 | Image(systemName: "info.circle") 120 | .resizable() 121 | .frame(width: 20, height: 20, alignment: .center) 122 | .scaledToFit() 123 | .foregroundColor(Color.black.opacity(0.7)) 124 | }) 125 | 126 | } 127 | 128 | @ViewBuilder 129 | private var recordButton: some View { 130 | Button(action: { 131 | onRecordButtonTapped() 132 | }, label: { 133 | Image(systemName: "mic") 134 | .font(.system(size: 24, weight: .bold)) 135 | .foregroundColor(.white) 136 | .frame(width: 100, height: 100, alignment: .center) 137 | .background( 138 | Circle().fill(Color.blue) 139 | .shadow(radius: 1) 140 | ) 141 | }) 142 | 143 | } 144 | 145 | @ViewBuilder 146 | private var footerText: some View { 147 | Text("Shazam Clone") 148 | .font(.footnote) 149 | .foregroundColor(Color.black.opacity(0.7)) 150 | } 151 | 152 | private func bindViewModel() { 153 | shazamViewModel.$viewState.sink { viewState in 154 | switch viewState { 155 | case .initial: 156 | shouldShowRippleView = false 157 | shouldShowRecordButton = true 158 | shouldShowNoResultView = false 159 | case .recordingInProgress: 160 | shouldShowRecordButton = false 161 | shouldShowRippleView = true 162 | shouldShowNoResultView = false 163 | foundSong = nil 164 | case .infoAlert: 165 | shouldShowInfoAlert = true 166 | case .recordPermissionSettingsAlert: 167 | shouldShowRecordPermissionAlert = true 168 | case .noResult: 169 | shouldShowRippleView = false 170 | shouldShowNoResultView = true 171 | foundSong = nil 172 | case .result(let song): 173 | withAnimation { 174 | foundSong = song 175 | } 176 | shouldShowRippleView = false 177 | } 178 | }.store(in: &cancellables) 179 | } 180 | 181 | private func onRecordButtonTapped() { 182 | shazamViewModel.startListening() 183 | } 184 | 185 | private func goToPermissionSettings() { 186 | if let bundleId = Bundle.main.bundleIdentifier, 187 | let url = URL(string: "\(UIApplication.openSettingsURLString)&path=LOCATION/\(bundleId)") { 188 | UIApplication.shared.open(url, options: [:], completionHandler: nil) 189 | } 190 | } 191 | 192 | enum Constants { 193 | // Temporary hack for the iOS 15 weird top and bottom inset 194 | static let topInset: CGFloat = UIApplication.shared.keyWindow?.safeAreaInsets.top ?? UIApplication.shared.statusBarFrame.size.height 195 | static let bottomInset: CGFloat = UIApplication.shared.keyWindow?.safeAreaInsets.bottom ?? 20 196 | } 197 | } 198 | 199 | struct ShazamView_Previews: PreviewProvider { 200 | static var previews: some View { 201 | ShazamView() 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /ShazamClone.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 514A626B26978E3B008ABBDF /* RippleView in Frameworks */ = {isa = PBXBuildFile; productRef = 514A626A26978E3B008ABBDF /* RippleView */; }; 11 | 51B7BFFB2690CFB200DA2E87 /* ShazamCloneApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B7BFFA2690CFB200DA2E87 /* ShazamCloneApp.swift */; }; 12 | 51B7BFFD2690CFB200DA2E87 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B7BFFC2690CFB200DA2E87 /* ContentView.swift */; }; 13 | 51B7BFFF2690CFB200DA2E87 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 51B7BFFE2690CFB200DA2E87 /* Assets.xcassets */; }; 14 | 51B7C0022690CFB200DA2E87 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 51B7C0012690CFB200DA2E87 /* Preview Assets.xcassets */; }; 15 | 51B7C00F2690DA2700DA2E87 /* NoResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B7C00E2690DA2700DA2E87 /* NoResultView.swift */; }; 16 | 51B7C0122690F0F000DA2E87 /* ShazamView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B7C0112690F0F000DA2E87 /* ShazamView.swift */; }; 17 | 51B7C01B2690F16500DA2E87 /* ShazamViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B7C01A2690F16500DA2E87 /* ShazamViewModel.swift */; }; 18 | 51D043192690FB3500B2DA1F /* Song.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51D043182690FB3500B2DA1F /* Song.swift */; }; 19 | 51D04321269109DE00B2DA1F /* SongDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51D04320269109DE00B2DA1F /* SongDetailView.swift */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 51B7BFF72690CFB200DA2E87 /* ShazamClone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ShazamClone.app; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | 51B7BFFA2690CFB200DA2E87 /* ShazamCloneApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShazamCloneApp.swift; sourceTree = ""; }; 25 | 51B7BFFC2690CFB200DA2E87 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 26 | 51B7BFFE2690CFB200DA2E87 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 27 | 51B7C0012690CFB200DA2E87 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 28 | 51B7C0032690CFB200DA2E87 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29 | 51B7C00E2690DA2700DA2E87 /* NoResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoResultView.swift; sourceTree = ""; }; 30 | 51B7C0112690F0F000DA2E87 /* ShazamView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShazamView.swift; sourceTree = ""; }; 31 | 51B7C01A2690F16500DA2E87 /* ShazamViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShazamViewModel.swift; sourceTree = ""; }; 32 | 51D043182690FB3500B2DA1F /* Song.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Song.swift; sourceTree = ""; }; 33 | 51D04320269109DE00B2DA1F /* SongDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SongDetailView.swift; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | 51B7BFF42690CFB200DA2E87 /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | 514A626B26978E3B008ABBDF /* RippleView in Frameworks */, 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | 5192A6CA2693C26300809316 /* UI */ = { 49 | isa = PBXGroup; 50 | children = ( 51 | 51B7C0182690F13A00DA2E87 /* NoResult */, 52 | 51B7C0142690F12200DA2E87 /* Shazam */, 53 | 51D0432326910D5300B2DA1F /* SongDetail */, 54 | ); 55 | path = UI; 56 | sourceTree = ""; 57 | }; 58 | 5192A6CB2693C26D00809316 /* Presentation */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 51D043172690FB2600B2DA1F /* Model */, 62 | 5192A6CC2693C27E00809316 /* Shazam */, 63 | ); 64 | path = Presentation; 65 | sourceTree = ""; 66 | }; 67 | 5192A6CC2693C27E00809316 /* Shazam */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 51B7C01A2690F16500DA2E87 /* ShazamViewModel.swift */, 71 | ); 72 | path = Shazam; 73 | sourceTree = ""; 74 | }; 75 | 51B7BFEE2690CFB200DA2E87 = { 76 | isa = PBXGroup; 77 | children = ( 78 | 51B7BFF92690CFB200DA2E87 /* ShazamClone */, 79 | 51B7BFF82690CFB200DA2E87 /* Products */, 80 | ); 81 | sourceTree = ""; 82 | }; 83 | 51B7BFF82690CFB200DA2E87 /* Products */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | 51B7BFF72690CFB200DA2E87 /* ShazamClone.app */, 87 | ); 88 | name = Products; 89 | sourceTree = ""; 90 | }; 91 | 51B7BFF92690CFB200DA2E87 /* ShazamClone */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 51B7BFFA2690CFB200DA2E87 /* ShazamCloneApp.swift */, 95 | 51B7BFFC2690CFB200DA2E87 /* ContentView.swift */, 96 | 51B7BFFE2690CFB200DA2E87 /* Assets.xcassets */, 97 | 51B7C0032690CFB200DA2E87 /* Info.plist */, 98 | 51B7C0002690CFB200DA2E87 /* Preview Content */, 99 | 5192A6CB2693C26D00809316 /* Presentation */, 100 | 5192A6CA2693C26300809316 /* UI */, 101 | ); 102 | path = ShazamClone; 103 | sourceTree = ""; 104 | }; 105 | 51B7C0002690CFB200DA2E87 /* Preview Content */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 51B7C0012690CFB200DA2E87 /* Preview Assets.xcassets */, 109 | ); 110 | path = "Preview Content"; 111 | sourceTree = ""; 112 | }; 113 | 51B7C0142690F12200DA2E87 /* Shazam */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | 51B7C0112690F0F000DA2E87 /* ShazamView.swift */, 117 | ); 118 | path = Shazam; 119 | sourceTree = ""; 120 | }; 121 | 51B7C0182690F13A00DA2E87 /* NoResult */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 51B7C00E2690DA2700DA2E87 /* NoResultView.swift */, 125 | ); 126 | path = NoResult; 127 | sourceTree = ""; 128 | }; 129 | 51D043172690FB2600B2DA1F /* Model */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | 51D043182690FB3500B2DA1F /* Song.swift */, 133 | ); 134 | path = Model; 135 | sourceTree = ""; 136 | }; 137 | 51D0432326910D5300B2DA1F /* SongDetail */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | 51D04320269109DE00B2DA1F /* SongDetailView.swift */, 141 | ); 142 | path = SongDetail; 143 | sourceTree = ""; 144 | }; 145 | /* End PBXGroup section */ 146 | 147 | /* Begin PBXNativeTarget section */ 148 | 51B7BFF62690CFB200DA2E87 /* ShazamClone */ = { 149 | isa = PBXNativeTarget; 150 | buildConfigurationList = 51B7C0062690CFB200DA2E87 /* Build configuration list for PBXNativeTarget "ShazamClone" */; 151 | buildPhases = ( 152 | 51B7BFF32690CFB200DA2E87 /* Sources */, 153 | 51B7BFF42690CFB200DA2E87 /* Frameworks */, 154 | 51B7BFF52690CFB200DA2E87 /* Resources */, 155 | ); 156 | buildRules = ( 157 | ); 158 | dependencies = ( 159 | ); 160 | name = ShazamClone; 161 | packageProductDependencies = ( 162 | 514A626A26978E3B008ABBDF /* RippleView */, 163 | ); 164 | productName = ShazamClone; 165 | productReference = 51B7BFF72690CFB200DA2E87 /* ShazamClone.app */; 166 | productType = "com.apple.product-type.application"; 167 | }; 168 | /* End PBXNativeTarget section */ 169 | 170 | /* Begin PBXProject section */ 171 | 51B7BFEF2690CFB200DA2E87 /* Project object */ = { 172 | isa = PBXProject; 173 | attributes = { 174 | LastSwiftUpdateCheck = 1240; 175 | LastUpgradeCheck = 1240; 176 | TargetAttributes = { 177 | 51B7BFF62690CFB200DA2E87 = { 178 | CreatedOnToolsVersion = 12.4; 179 | }; 180 | }; 181 | }; 182 | buildConfigurationList = 51B7BFF22690CFB200DA2E87 /* Build configuration list for PBXProject "ShazamClone" */; 183 | compatibilityVersion = "Xcode 9.3"; 184 | developmentRegion = en; 185 | hasScannedForEncodings = 0; 186 | knownRegions = ( 187 | en, 188 | Base, 189 | ); 190 | mainGroup = 51B7BFEE2690CFB200DA2E87; 191 | packageReferences = ( 192 | 514A626926978E3B008ABBDF /* XCRemoteSwiftPackageReference "RippleView" */, 193 | ); 194 | productRefGroup = 51B7BFF82690CFB200DA2E87 /* Products */; 195 | projectDirPath = ""; 196 | projectRoot = ""; 197 | targets = ( 198 | 51B7BFF62690CFB200DA2E87 /* ShazamClone */, 199 | ); 200 | }; 201 | /* End PBXProject section */ 202 | 203 | /* Begin PBXResourcesBuildPhase section */ 204 | 51B7BFF52690CFB200DA2E87 /* Resources */ = { 205 | isa = PBXResourcesBuildPhase; 206 | buildActionMask = 2147483647; 207 | files = ( 208 | 51B7C0022690CFB200DA2E87 /* Preview Assets.xcassets in Resources */, 209 | 51B7BFFF2690CFB200DA2E87 /* Assets.xcassets in Resources */, 210 | ); 211 | runOnlyForDeploymentPostprocessing = 0; 212 | }; 213 | /* End PBXResourcesBuildPhase section */ 214 | 215 | /* Begin PBXSourcesBuildPhase section */ 216 | 51B7BFF32690CFB200DA2E87 /* Sources */ = { 217 | isa = PBXSourcesBuildPhase; 218 | buildActionMask = 2147483647; 219 | files = ( 220 | 51D043192690FB3500B2DA1F /* Song.swift in Sources */, 221 | 51B7C0122690F0F000DA2E87 /* ShazamView.swift in Sources */, 222 | 51B7C00F2690DA2700DA2E87 /* NoResultView.swift in Sources */, 223 | 51D04321269109DE00B2DA1F /* SongDetailView.swift in Sources */, 224 | 51B7BFFD2690CFB200DA2E87 /* ContentView.swift in Sources */, 225 | 51B7C01B2690F16500DA2E87 /* ShazamViewModel.swift in Sources */, 226 | 51B7BFFB2690CFB200DA2E87 /* ShazamCloneApp.swift in Sources */, 227 | ); 228 | runOnlyForDeploymentPostprocessing = 0; 229 | }; 230 | /* End PBXSourcesBuildPhase section */ 231 | 232 | /* Begin XCBuildConfiguration section */ 233 | 51B7C0042690CFB200DA2E87 /* Debug */ = { 234 | isa = XCBuildConfiguration; 235 | buildSettings = { 236 | ALWAYS_SEARCH_USER_PATHS = NO; 237 | CLANG_ANALYZER_NONNULL = YES; 238 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 240 | CLANG_CXX_LIBRARY = "libc++"; 241 | CLANG_ENABLE_MODULES = YES; 242 | CLANG_ENABLE_OBJC_ARC = YES; 243 | CLANG_ENABLE_OBJC_WEAK = YES; 244 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 245 | CLANG_WARN_BOOL_CONVERSION = YES; 246 | CLANG_WARN_COMMA = YES; 247 | CLANG_WARN_CONSTANT_CONVERSION = YES; 248 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 249 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 250 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 251 | CLANG_WARN_EMPTY_BODY = YES; 252 | CLANG_WARN_ENUM_CONVERSION = YES; 253 | CLANG_WARN_INFINITE_RECURSION = YES; 254 | CLANG_WARN_INT_CONVERSION = YES; 255 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 256 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 257 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 258 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 259 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 260 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 261 | CLANG_WARN_STRICT_PROTOTYPES = YES; 262 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 263 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 264 | CLANG_WARN_UNREACHABLE_CODE = YES; 265 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 266 | COPY_PHASE_STRIP = NO; 267 | DEBUG_INFORMATION_FORMAT = dwarf; 268 | ENABLE_STRICT_OBJC_MSGSEND = YES; 269 | ENABLE_TESTABILITY = YES; 270 | GCC_C_LANGUAGE_STANDARD = gnu11; 271 | GCC_DYNAMIC_NO_PIC = NO; 272 | GCC_NO_COMMON_BLOCKS = YES; 273 | GCC_OPTIMIZATION_LEVEL = 0; 274 | GCC_PREPROCESSOR_DEFINITIONS = ( 275 | "DEBUG=1", 276 | "$(inherited)", 277 | ); 278 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 279 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 280 | GCC_WARN_UNDECLARED_SELECTOR = YES; 281 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 282 | GCC_WARN_UNUSED_FUNCTION = YES; 283 | GCC_WARN_UNUSED_VARIABLE = YES; 284 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 285 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 286 | MTL_FAST_MATH = YES; 287 | ONLY_ACTIVE_ARCH = YES; 288 | SDKROOT = iphoneos; 289 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 290 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 291 | }; 292 | name = Debug; 293 | }; 294 | 51B7C0052690CFB200DA2E87 /* Release */ = { 295 | isa = XCBuildConfiguration; 296 | buildSettings = { 297 | ALWAYS_SEARCH_USER_PATHS = NO; 298 | CLANG_ANALYZER_NONNULL = YES; 299 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 300 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 301 | CLANG_CXX_LIBRARY = "libc++"; 302 | CLANG_ENABLE_MODULES = YES; 303 | CLANG_ENABLE_OBJC_ARC = YES; 304 | CLANG_ENABLE_OBJC_WEAK = YES; 305 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 306 | CLANG_WARN_BOOL_CONVERSION = YES; 307 | CLANG_WARN_COMMA = YES; 308 | CLANG_WARN_CONSTANT_CONVERSION = YES; 309 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 310 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 311 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 312 | CLANG_WARN_EMPTY_BODY = YES; 313 | CLANG_WARN_ENUM_CONVERSION = YES; 314 | CLANG_WARN_INFINITE_RECURSION = YES; 315 | CLANG_WARN_INT_CONVERSION = YES; 316 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 317 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 318 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 319 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 320 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 321 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 322 | CLANG_WARN_STRICT_PROTOTYPES = YES; 323 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 324 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 325 | CLANG_WARN_UNREACHABLE_CODE = YES; 326 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 327 | COPY_PHASE_STRIP = NO; 328 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 329 | ENABLE_NS_ASSERTIONS = NO; 330 | ENABLE_STRICT_OBJC_MSGSEND = YES; 331 | GCC_C_LANGUAGE_STANDARD = gnu11; 332 | GCC_NO_COMMON_BLOCKS = YES; 333 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 334 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 335 | GCC_WARN_UNDECLARED_SELECTOR = YES; 336 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 337 | GCC_WARN_UNUSED_FUNCTION = YES; 338 | GCC_WARN_UNUSED_VARIABLE = YES; 339 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 340 | MTL_ENABLE_DEBUG_INFO = NO; 341 | MTL_FAST_MATH = YES; 342 | SDKROOT = iphoneos; 343 | SWIFT_COMPILATION_MODE = wholemodule; 344 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 345 | VALIDATE_PRODUCT = YES; 346 | }; 347 | name = Release; 348 | }; 349 | 51B7C0072690CFB200DA2E87 /* Debug */ = { 350 | isa = XCBuildConfiguration; 351 | buildSettings = { 352 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 353 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 354 | CODE_SIGN_STYLE = Automatic; 355 | DEVELOPMENT_ASSET_PATHS = "\"ShazamClone/Preview Content\""; 356 | DEVELOPMENT_TEAM = UXB3TMTR3F; 357 | ENABLE_PREVIEWS = YES; 358 | INFOPLIST_FILE = ShazamClone/Info.plist; 359 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 360 | LD_RUNPATH_SEARCH_PATHS = ( 361 | "$(inherited)", 362 | "@executable_path/Frameworks", 363 | ); 364 | PRODUCT_BUNDLE_IDENTIFIER = com.emmanuelkehinde.ShazamClone; 365 | PRODUCT_NAME = "$(TARGET_NAME)"; 366 | SWIFT_VERSION = 5.0; 367 | TARGETED_DEVICE_FAMILY = "1,2"; 368 | }; 369 | name = Debug; 370 | }; 371 | 51B7C0082690CFB200DA2E87 /* Release */ = { 372 | isa = XCBuildConfiguration; 373 | buildSettings = { 374 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 375 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 376 | CODE_SIGN_STYLE = Automatic; 377 | DEVELOPMENT_ASSET_PATHS = "\"ShazamClone/Preview Content\""; 378 | DEVELOPMENT_TEAM = UXB3TMTR3F; 379 | ENABLE_PREVIEWS = YES; 380 | INFOPLIST_FILE = ShazamClone/Info.plist; 381 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 382 | LD_RUNPATH_SEARCH_PATHS = ( 383 | "$(inherited)", 384 | "@executable_path/Frameworks", 385 | ); 386 | PRODUCT_BUNDLE_IDENTIFIER = com.emmanuelkehinde.ShazamClone; 387 | PRODUCT_NAME = "$(TARGET_NAME)"; 388 | SWIFT_VERSION = 5.0; 389 | TARGETED_DEVICE_FAMILY = "1,2"; 390 | }; 391 | name = Release; 392 | }; 393 | /* End XCBuildConfiguration section */ 394 | 395 | /* Begin XCConfigurationList section */ 396 | 51B7BFF22690CFB200DA2E87 /* Build configuration list for PBXProject "ShazamClone" */ = { 397 | isa = XCConfigurationList; 398 | buildConfigurations = ( 399 | 51B7C0042690CFB200DA2E87 /* Debug */, 400 | 51B7C0052690CFB200DA2E87 /* Release */, 401 | ); 402 | defaultConfigurationIsVisible = 0; 403 | defaultConfigurationName = Release; 404 | }; 405 | 51B7C0062690CFB200DA2E87 /* Build configuration list for PBXNativeTarget "ShazamClone" */ = { 406 | isa = XCConfigurationList; 407 | buildConfigurations = ( 408 | 51B7C0072690CFB200DA2E87 /* Debug */, 409 | 51B7C0082690CFB200DA2E87 /* Release */, 410 | ); 411 | defaultConfigurationIsVisible = 0; 412 | defaultConfigurationName = Release; 413 | }; 414 | /* End XCConfigurationList section */ 415 | 416 | /* Begin XCRemoteSwiftPackageReference section */ 417 | 514A626926978E3B008ABBDF /* XCRemoteSwiftPackageReference "RippleView" */ = { 418 | isa = XCRemoteSwiftPackageReference; 419 | repositoryURL = "https://github.com/emmanuelkehinde/RippleView.git"; 420 | requirement = { 421 | kind = upToNextMajorVersion; 422 | minimumVersion = 1.0.2; 423 | }; 424 | }; 425 | /* End XCRemoteSwiftPackageReference section */ 426 | 427 | /* Begin XCSwiftPackageProductDependency section */ 428 | 514A626A26978E3B008ABBDF /* RippleView */ = { 429 | isa = XCSwiftPackageProductDependency; 430 | package = 514A626926978E3B008ABBDF /* XCRemoteSwiftPackageReference "RippleView" */; 431 | productName = RippleView; 432 | }; 433 | /* End XCSwiftPackageProductDependency section */ 434 | }; 435 | rootObject = 51B7BFEF2690CFB200DA2E87 /* Project object */; 436 | } 437 | --------------------------------------------------------------------------------