├── .gitignore ├── README.md ├── final ├── GitHubSearch │ ├── APIError.swift │ ├── LoadingState.swift │ ├── Resources │ │ ├── Assets.xcassets │ │ │ ├── Contents.json │ │ │ ├── AccentColor.colorset │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ └── Preview Content │ │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── GitHubSearchApp.swift │ └── Repository │ │ ├── RepositoryModel.swift │ │ ├── RepoSearchView.swift │ │ ├── RepoSearchClient.swift │ │ └── RepoSearch.swift ├── GitHubSearch-final.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── swiftpm │ │ │ └── Package.resolved │ └── project.pbxproj └── GitHubSearchTests │ └── RepositoryTests.swift ├── starter ├── GitHubSearch │ ├── APIError.swift │ ├── Resources │ │ ├── Assets.xcassets │ │ │ ├── Contents.json │ │ │ ├── AccentColor.colorset │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ └── Preview Content │ │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── GitHubSearchApp.swift │ └── Repository │ │ ├── RepoSearch.swift │ │ ├── RepositoryModel.swift │ │ ├── RepoSearchView.swift │ │ └── RepoSearchClient.swift ├── GitHubSearch.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── swiftpm │ │ │ └── Package.resolved │ └── project.pbxproj └── GitHubSearchTests │ └── RepositoryTests.swift └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | xcuserdata/ 2 | .build/ 3 | .DS_Store 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LetsGitHubSearch 2 | 3 | 발표자료 4 | https://www.slideshare.net/ssuser3d03b2/swiftui-tca-github-search 5 | -------------------------------------------------------------------------------- /final/GitHubSearch/APIError.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | enum APIError: Error { 4 | case invalidURL 5 | } 6 | -------------------------------------------------------------------------------- /starter/GitHubSearch/APIError.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | enum APIError: Error { 4 | case invalidURL 5 | } 6 | -------------------------------------------------------------------------------- /final/GitHubSearch/LoadingState.swift: -------------------------------------------------------------------------------- 1 | enum LoadingState { 2 | case initial 3 | case loading 4 | case loaded 5 | case failed 6 | } 7 | -------------------------------------------------------------------------------- /final/GitHubSearch/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /starter/GitHubSearch/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /final/GitHubSearch/Resources/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /starter/GitHubSearch/Resources/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /starter/GitHubSearch/GitHubSearchApp.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | @main 4 | struct GitHubSearchApp: App { 5 | var body: some Scene { 6 | WindowGroup { 7 | RepoSearchView() 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /starter/GitHubSearch.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /final/GitHubSearch-final.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /final/GitHubSearch/Resources/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 | -------------------------------------------------------------------------------- /starter/GitHubSearch/Resources/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 | -------------------------------------------------------------------------------- /final/GitHubSearch/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /starter/GitHubSearch/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /starter/GitHubSearch.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /final/GitHubSearch-final.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /final/GitHubSearch/GitHubSearchApp.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | import ComposableArchitecture 4 | 5 | @main 6 | struct GitHubSearchApp: App { 7 | var body: some Scene { 8 | WindowGroup { 9 | RepoSearchView( 10 | store: Store( 11 | initialState: RepoSearch.State(), 12 | reducer: RepoSearch()._printChanges() 13 | ) 14 | ) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /starter/GitHubSearchTests/RepositoryTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import ComposableArchitecture 4 | 5 | @testable import GitHubSearch 6 | 7 | @MainActor 8 | final class RepositoryTests: XCTestCase { 9 | func test_user_get_repoSearchResults_when_search() async { 10 | // Arrange 11 | // TestStore를 생성합니다. 12 | 13 | // Act & Assert 14 | // 1. "Swift"를 입력했을 때, state.keyword가 "Swift"인지 테스트합니다. 15 | // 2. 검색을 했을 때, 예상하는 검색 결과가 나오는지를 테스트합니다. 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /starter/GitHubSearch/Repository/RepoSearch.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | import ComposableArchitecture 4 | 5 | struct RepoSearch: ReducerProtocol { 6 | struct State: Equatable { 7 | // TODO: 지금 앱은 어떤 상태들로 정의되는가? 8 | // keyword와 searchResults 상태 추가하기 9 | } 10 | 11 | enum Action: Equatable { 12 | // TODO: 상태들을 변화시키는 사용자의 액션은 무엇인가? 13 | // keywordChanged, search 액션 추가하기 14 | } 15 | 16 | func reduce(into state: inout State, action: Action) -> EffectTask { 17 | // TODO: 각각의 Action이 발생했을 때 상태는 어떻게 변화해야 하는가? 18 | // switch action { 19 | // case let .keywordChanged(keyword): 20 | // case .search: 21 | // } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /starter/GitHubSearch/Repository/RepositoryModel.swift: -------------------------------------------------------------------------------- 1 | struct RepositoryModel: Decodable, Equatable, Sendable { 2 | var items: [Result] 3 | 4 | struct Result: Decodable, Equatable, Sendable { 5 | var name: String 6 | 7 | enum CodingKeys: String, CodingKey { 8 | case name = "full_name" 9 | } 10 | } 11 | } 12 | 13 | // MARK: - Mock data 14 | 15 | extension RepositoryModel { 16 | static let mock = Self( 17 | items: [ 18 | RepositoryModel.Result(name: "Swift"), 19 | RepositoryModel.Result(name: "SwiftyJSON"), 20 | RepositoryModel.Result(name: "SwiftGuide"), 21 | RepositoryModel.Result(name: "SwiftterSwift") 22 | ] 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /final/GitHubSearch/Repository/RepositoryModel.swift: -------------------------------------------------------------------------------- 1 | struct RepositoryModel: Decodable, Equatable, Sendable { 2 | var items: [Result] 3 | 4 | struct Result: Decodable, Equatable, Sendable { 5 | var name: String 6 | 7 | enum CodingKeys: String, CodingKey { 8 | case name = "full_name" 9 | } 10 | } 11 | } 12 | 13 | // MARK: - Mock data 14 | 15 | extension RepositoryModel { 16 | static let mock = Self( 17 | items: [ 18 | RepositoryModel.Result(name: "Swift"), 19 | RepositoryModel.Result(name: "SwiftyJSON"), 20 | RepositoryModel.Result(name: "SwiftGuide"), 21 | RepositoryModel.Result(name: "SwiftterSwift") 22 | ] 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /final/GitHubSearch/Repository/RepoSearchView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | import ComposableArchitecture 4 | 5 | struct RepoSearchView: View { 6 | let store: StoreOf 7 | 8 | var body: some View { 9 | WithViewStore(self.store) { viewStore in 10 | NavigationView { 11 | Group { 12 | Text("\(viewStore.requestCount)") 13 | Spacer() 14 | 15 | if(viewStore.isLoading) { 16 | ProgressView() 17 | } else { 18 | List { 19 | ForEach(viewStore.searchResults, id: \.self) { repo in 20 | Text(repo) 21 | } 22 | } 23 | } 24 | Spacer() 25 | } 26 | .searchable(text: viewStore.binding(\.$keyword)) 27 | .navigationTitle("Github Search") 28 | } 29 | } 30 | } 31 | } 32 | 33 | struct RepoSearchView_Previews: PreviewProvider { 34 | static var previews: some View { 35 | RepoSearchView( 36 | store: Store( 37 | initialState: RepoSearch.State(), 38 | reducer: RepoSearch() 39 | ) 40 | ) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /starter/GitHubSearch/Repository/RepoSearchView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | struct RepoSearchView: View { 4 | @State private var keyword = "" 5 | @State private var searchResults: [String] = [] 6 | 7 | private let sampleRepoLists = [ 8 | "Swift", 9 | "SwiftyJSON", 10 | "SwiftGuide", 11 | "SwiftterSwift", 12 | ] 13 | 14 | var body: some View { 15 | NavigationView { 16 | VStack { 17 | HStack { 18 | TextField("Search repo", text: self.$keyword) 19 | .textFieldStyle(.roundedBorder) 20 | 21 | Button("Search") { 22 | self.searchResults = self.sampleRepoLists.filter { 23 | $0.contains(self.keyword) 24 | } 25 | } 26 | .buttonStyle(.borderedProminent) 27 | } 28 | .padding() 29 | 30 | List { 31 | ForEach(self.searchResults, id: \.self) { Text($0) } 32 | } 33 | } 34 | .navigationTitle("Github Search") 35 | } 36 | } 37 | } 38 | 39 | struct RepoSearchView_Previews: PreviewProvider { 40 | static var previews: some View { 41 | RepoSearchView() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 TheComposers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /final/GitHubSearchTests/RepositoryTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import ComposableArchitecture 4 | 5 | @testable import GitHubSearch_final 6 | 7 | @MainActor 8 | final class RepositoryTests: XCTestCase { 9 | func test_user_get_repo_search_results_when_search() async { 10 | let store = TestStore( 11 | initialState: RepoSearch.State(), 12 | reducer: RepoSearch() 13 | ) 14 | 15 | store.dependencies.repoSearchClient.search = { _ in .mock } 16 | store.dependencies.continuousClock = ImmediateClock() 17 | 18 | await store.send(.set(\.$keyword, "Swift")) { 19 | $0.keyword = "Swift" 20 | } 21 | 22 | await store.receive(.search) { 23 | $0.isLoading = true 24 | $0.requestCount = 1 25 | } 26 | 27 | await store.receive(.dataLoaded(.success(.mock))) { 28 | $0.isLoading = false 29 | $0.searchResults = [ 30 | "Swift", 31 | "SwiftyJSON", 32 | "SwiftGuide", 33 | "SwiftterSwift", 34 | ] 35 | } 36 | } 37 | 38 | func test_request_count_not_changed_when_keyword_cleared_within_debounce_time() async { 39 | let store = TestStore( 40 | initialState: RepoSearch.State(), 41 | reducer: RepoSearch() 42 | ) 43 | 44 | store.dependencies.repoSearchClient.search = { _ in .mock } 45 | 46 | let clock = TestClock() 47 | store.dependencies.continuousClock = clock 48 | 49 | await store.send(.set(\.$keyword, "Swift")) { 50 | $0.keyword = "Swift" 51 | } 52 | 53 | 54 | await clock.advance(by: .seconds(0.3)) 55 | 56 | await store.send(.set(\.$keyword, "")) { 57 | $0.keyword = "" 58 | $0.requestCount = 0 59 | $0.isLoading = false 60 | $0.searchResults = [] 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /starter/GitHubSearch/Repository/RepoSearchClient.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | import ComposableArchitecture 4 | import XCTestDynamicOverlay 5 | 6 | struct RepoSearchClient { 7 | var search: @Sendable (String) async throws -> RepositoryModel 8 | } 9 | 10 | extension DependencyValues { 11 | var repoSearchClient: RepoSearchClient { 12 | get { self[RepoSearchClient.self] } 13 | set { self[RepoSearchClient.self] = newValue } 14 | } 15 | } 16 | 17 | // MARK: - Live API implementation 18 | 19 | extension RepoSearchClient: DependencyKey { 20 | static let liveValue = RepoSearchClient( 21 | search: { keyword in 22 | guard let url = URL(string: "https://api.github.com/search/repositories?q=\(keyword)") else { 23 | throw APIError.invalidURL 24 | } 25 | let (data, _) = try await URLSession.shared.data(from: url) 26 | return try JSONDecoder().decode(RepositoryModel.self, from: data) 27 | } 28 | ) 29 | } 30 | 31 | extension RepoSearchClient: TestDependencyKey { 32 | static let previewValue = Self( 33 | search: { _ in .mock } 34 | ) 35 | 36 | static let testValue = Self( 37 | search: unimplemented("\(Self.self).search") 38 | ) 39 | } 40 | 41 | // Workshop 진행 중에 임시로 활용할 코드 42 | // 43 | //func sampleSearchRequest(keyword: String, send: Send) async throws { 44 | // guard let url = URL(string: "https://api.github.com/search/repositories?q=\(keyword)") else { 45 | // await send(RepoSearch.Action.dataLoaded(.failure(APIError.invalidURL))) 46 | // return 47 | // } 48 | // let (data, _) = try await URLSession.shared.data(from: url) 49 | // let result = await TaskResult { try JSONDecoder().decode(RepositoryModel.self, from: data) } 50 | // 51 | // await send(RepoSearch.Action.dataLoaded(result)) 52 | //} 53 | -------------------------------------------------------------------------------- /final/GitHubSearch/Repository/RepoSearchClient.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | import ComposableArchitecture 4 | import XCTestDynamicOverlay 5 | 6 | struct RepoSearchClient { 7 | var search: @Sendable (String) async throws -> RepositoryModel 8 | } 9 | 10 | extension DependencyValues { 11 | var repoSearchClient: RepoSearchClient { 12 | get { self[RepoSearchClient.self] } 13 | set { self[RepoSearchClient.self] = newValue } 14 | } 15 | } 16 | 17 | // MARK: - Live API implementation 18 | 19 | extension RepoSearchClient: DependencyKey { 20 | static let liveValue = RepoSearchClient( 21 | search: { keyword in 22 | guard let url = URL(string: "https://api.github.com/search/repositories?q=\(keyword)") else { 23 | throw APIError.invalidURL 24 | } 25 | let (data, _) = try await URLSession.shared.data(from: url) 26 | return try JSONDecoder().decode(RepositoryModel.self, from: data) 27 | } 28 | ) 29 | } 30 | 31 | extension RepoSearchClient: TestDependencyKey { 32 | static let previewValue = Self( 33 | search: { _ in .mock } 34 | ) 35 | 36 | static let testValue = Self( 37 | search: unimplemented("\(Self.self).search") 38 | ) 39 | } 40 | 41 | // Workshop 진행 중에 임시로 활용할 코드 42 | // 43 | //func sampleSearchRequest(keyword: String, send: Send) async throws { 44 | // guard let url = URL(string: "https://api.github.com/search/repositories?q=\(keyword)") else { 45 | // await send(RepoSearch.Action.dataLoaded(.failure(APIError.invalidUrlError))) 46 | // return 47 | // } 48 | // let (data, _) = try await URLSession.shared.data(from: url) 49 | // let result = await TaskResult { try JSONDecoder().decode(RepositoryModel.self, from: data) } 50 | // 51 | // await send(RepoSearch.Action.dataLoaded(result)) 52 | //} 53 | -------------------------------------------------------------------------------- /final/GitHubSearch/Repository/RepoSearch.swift: -------------------------------------------------------------------------------- 1 | import ComposableArchitecture 2 | 3 | struct RepoSearch: ReducerProtocol { 4 | struct State: Equatable { 5 | @BindingState var keyword = "" 6 | var searchResults = [String]() 7 | var isLoading = false 8 | var requestCount = 0 9 | } 10 | 11 | enum Action: Equatable, BindableAction { 12 | case binding(BindingAction) 13 | case search 14 | case dataLoaded(TaskResult) 15 | } 16 | 17 | @Dependency(\.repoSearchClient) var repoSearchClient 18 | @Dependency(\.continuousClock) var clock 19 | 20 | private enum SearchDebounceId {} 21 | var body: some ReducerProtocol { 22 | BindingReducer() 23 | Reduce { state, action in 24 | switch action { 25 | case .binding(\.$keyword): 26 | if state.keyword == "" { 27 | state.isLoading = false 28 | state.searchResults = [] 29 | return .cancel(id: SearchDebounceId.self) 30 | } 31 | 32 | return .run { send in 33 | try await self.clock.sleep(for: .seconds(0.5)) 34 | await send(.search) 35 | } 36 | .cancellable(id: SearchDebounceId.self, cancelInFlight: true) 37 | 38 | case .search: 39 | state.isLoading = true 40 | state.requestCount += 1 41 | return EffectTask.run { [keyword = state.keyword] send in 42 | let result = await TaskResult { try await repoSearchClient.search(keyword) } 43 | await send(.dataLoaded(result)) 44 | } 45 | 46 | case let .dataLoaded(.success(repositoryModel)): 47 | state.isLoading = false 48 | state.searchResults = repositoryModel.items.map { $0.name } 49 | return .none 50 | 51 | case .dataLoaded(.failure): 52 | state.isLoading = false 53 | state.searchResults = [] 54 | return .none 55 | 56 | case .binding: 57 | return .none 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /starter/GitHubSearch.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "pins" : [ 3 | { 4 | "identity" : "combine-schedulers", 5 | "kind" : "remoteSourceControl", 6 | "location" : "https://github.com/pointfreeco/combine-schedulers", 7 | "state" : { 8 | "revision" : "882ac01eb7ef9e36d4467eb4b1151e74fcef85ab", 9 | "version" : "0.9.1" 10 | } 11 | }, 12 | { 13 | "identity" : "swift-case-paths", 14 | "kind" : "remoteSourceControl", 15 | "location" : "https://github.com/pointfreeco/swift-case-paths", 16 | "state" : { 17 | "revision" : "bb436421f57269fbcfe7360735985321585a86e5", 18 | "version" : "0.10.1" 19 | } 20 | }, 21 | { 22 | "identity" : "swift-clocks", 23 | "kind" : "remoteSourceControl", 24 | "location" : "https://github.com/pointfreeco/swift-clocks", 25 | "state" : { 26 | "revision" : "20b25ca0dd88ebfb9111ec937814ddc5a8880172", 27 | "version" : "0.2.0" 28 | } 29 | }, 30 | { 31 | "identity" : "swift-collections", 32 | "kind" : "remoteSourceControl", 33 | "location" : "https://github.com/apple/swift-collections", 34 | "state" : { 35 | "revision" : "f504716c27d2e5d4144fa4794b12129301d17729", 36 | "version" : "1.0.3" 37 | } 38 | }, 39 | { 40 | "identity" : "swift-composable-architecture", 41 | "kind" : "remoteSourceControl", 42 | "location" : "https://github.com/pointfreeco/swift-composable-architecture", 43 | "state" : { 44 | "revision" : "52dca7e5edd6ec9e0b529380843a8cb13f57d7d7", 45 | "version" : "0.46.0" 46 | } 47 | }, 48 | { 49 | "identity" : "swift-custom-dump", 50 | "kind" : "remoteSourceControl", 51 | "location" : "https://github.com/pointfreeco/swift-custom-dump", 52 | "state" : { 53 | "revision" : "ead7d30cc224c3642c150b546f4f1080d1c411a8", 54 | "version" : "0.6.1" 55 | } 56 | }, 57 | { 58 | "identity" : "swift-identified-collections", 59 | "kind" : "remoteSourceControl", 60 | "location" : "https://github.com/pointfreeco/swift-identified-collections", 61 | "state" : { 62 | "revision" : "a08887de589e3829d488e0b4b707b2ca804b1060", 63 | "version" : "0.5.0" 64 | } 65 | }, 66 | { 67 | "identity" : "xctest-dynamic-overlay", 68 | "kind" : "remoteSourceControl", 69 | "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", 70 | "state" : { 71 | "revision" : "5a5457a744239896e9b0b03a8e1a5069c3e7b91f", 72 | "version" : "0.6.0" 73 | } 74 | } 75 | ], 76 | "version" : 2 77 | } 78 | -------------------------------------------------------------------------------- /final/GitHubSearch-final.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "pins" : [ 3 | { 4 | "identity" : "combine-schedulers", 5 | "kind" : "remoteSourceControl", 6 | "location" : "https://github.com/pointfreeco/combine-schedulers", 7 | "state" : { 8 | "revision" : "882ac01eb7ef9e36d4467eb4b1151e74fcef85ab", 9 | "version" : "0.9.1" 10 | } 11 | }, 12 | { 13 | "identity" : "swift-case-paths", 14 | "kind" : "remoteSourceControl", 15 | "location" : "https://github.com/pointfreeco/swift-case-paths", 16 | "state" : { 17 | "revision" : "fc45e7b2cfece9dd80b5a45e6469ffe67fe67984", 18 | "version" : "0.14.1" 19 | } 20 | }, 21 | { 22 | "identity" : "swift-clocks", 23 | "kind" : "remoteSourceControl", 24 | "location" : "https://github.com/pointfreeco/swift-clocks", 25 | "state" : { 26 | "revision" : "20b25ca0dd88ebfb9111ec937814ddc5a8880172", 27 | "version" : "0.2.0" 28 | } 29 | }, 30 | { 31 | "identity" : "swift-collections", 32 | "kind" : "remoteSourceControl", 33 | "location" : "https://github.com/apple/swift-collections", 34 | "state" : { 35 | "revision" : "937e904258d22af6e447a0b72c0bc67583ef64a2", 36 | "version" : "1.0.4" 37 | } 38 | }, 39 | { 40 | "identity" : "swift-composable-architecture", 41 | "kind" : "remoteSourceControl", 42 | "location" : "https://github.com/pointfreeco/swift-composable-architecture", 43 | "state" : { 44 | "revision" : "3e8eee1efe99d06e99426d421733b858b332186b", 45 | "version" : "0.52.0" 46 | } 47 | }, 48 | { 49 | "identity" : "swift-custom-dump", 50 | "kind" : "remoteSourceControl", 51 | "location" : "https://github.com/pointfreeco/swift-custom-dump", 52 | "state" : { 53 | "revision" : "84b30e1af72e0ffe6dfbfe39d53b8173caacf224", 54 | "version" : "0.10.2" 55 | } 56 | }, 57 | { 58 | "identity" : "swift-dependencies", 59 | "kind" : "remoteSourceControl", 60 | "location" : "https://github.com/pointfreeco/swift-dependencies", 61 | "state" : { 62 | "revision" : "98650d886ec950b587d671261f06d6b59dec4052", 63 | "version" : "0.4.1" 64 | } 65 | }, 66 | { 67 | "identity" : "swift-identified-collections", 68 | "kind" : "remoteSourceControl", 69 | "location" : "https://github.com/pointfreeco/swift-identified-collections", 70 | "state" : { 71 | "revision" : "f52eee28bdc6065aa2f8424067e6f04c74bda6e6", 72 | "version" : "0.7.1" 73 | } 74 | }, 75 | { 76 | "identity" : "swiftui-navigation", 77 | "kind" : "remoteSourceControl", 78 | "location" : "https://github.com/pointfreeco/swiftui-navigation", 79 | "state" : { 80 | "revision" : "47dd574b900ba5ba679f56ea00d4d282fc7305a6", 81 | "version" : "0.7.1" 82 | } 83 | }, 84 | { 85 | "identity" : "xctest-dynamic-overlay", 86 | "kind" : "remoteSourceControl", 87 | "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", 88 | "state" : { 89 | "revision" : "ab8c9f45843694dd16be4297e6d44c0634fd9913", 90 | "version" : "0.8.4" 91 | } 92 | } 93 | ], 94 | "version" : 2 95 | } 96 | -------------------------------------------------------------------------------- /starter/GitHubSearch.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | EC4BC239293463F4001B2F91 /* APIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC4BC238293463F4001B2F91 /* APIError.swift */; }; 11 | ECC8142829334ADF0038A09F /* GitHubSearchApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC8142729334ADF0038A09F /* GitHubSearchApp.swift */; }; 12 | ECC8142C29334AE00038A09F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ECC8142B29334AE00038A09F /* Assets.xcassets */; }; 13 | ECC8142F29334AE00038A09F /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ECC8142E29334AE00038A09F /* Preview Assets.xcassets */; }; 14 | ECC8143929334AE00038A09F /* RepositoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC8143829334AE00038A09F /* RepositoryTests.swift */; }; 15 | ECC8145429334C590038A09F /* ComposableArchitecture in Frameworks */ = {isa = PBXBuildFile; productRef = ECC8145329334C590038A09F /* ComposableArchitecture */; }; 16 | ECC8145629334C590038A09F /* Dependencies in Frameworks */ = {isa = PBXBuildFile; productRef = ECC8145529334C590038A09F /* Dependencies */; }; 17 | ECC8145C29334CB70038A09F /* RepoSearchClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC8145829334CB70038A09F /* RepoSearchClient.swift */; }; 18 | ECC8145D29334CB70038A09F /* RepoSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC8145929334CB70038A09F /* RepoSearch.swift */; }; 19 | ECC8145E29334CB70038A09F /* RepositoryModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC8145A29334CB70038A09F /* RepositoryModel.swift */; }; 20 | ECC8145F29334CB70038A09F /* RepoSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC8145B29334CB70038A09F /* RepoSearchView.swift */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | ECC8143529334AE00038A09F /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = ECC8141C29334ADF0038A09F /* Project object */; 27 | proxyType = 1; 28 | remoteGlobalIDString = ECC8142329334ADF0038A09F; 29 | remoteInfo = GitHubSearch; 30 | }; 31 | /* End PBXContainerItemProxy section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | EC4BC238293463F4001B2F91 /* APIError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIError.swift; sourceTree = ""; }; 35 | ECC8142429334ADF0038A09F /* GitHubSearch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GitHubSearch.app; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | ECC8142729334ADF0038A09F /* GitHubSearchApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GitHubSearchApp.swift; sourceTree = ""; }; 37 | ECC8142B29334AE00038A09F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 38 | ECC8142E29334AE00038A09F /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 39 | ECC8143429334AE00038A09F /* GitHubSearchTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GitHubSearchTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | ECC8143829334AE00038A09F /* RepositoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepositoryTests.swift; sourceTree = ""; }; 41 | ECC8145829334CB70038A09F /* RepoSearchClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepoSearchClient.swift; sourceTree = ""; }; 42 | ECC8145929334CB70038A09F /* RepoSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepoSearch.swift; sourceTree = ""; }; 43 | ECC8145A29334CB70038A09F /* RepositoryModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepositoryModel.swift; sourceTree = ""; }; 44 | ECC8145B29334CB70038A09F /* RepoSearchView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepoSearchView.swift; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | ECC8142129334ADF0038A09F /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | ECC8145429334C590038A09F /* ComposableArchitecture in Frameworks */, 53 | ECC8145629334C590038A09F /* Dependencies in Frameworks */, 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | ECC8143129334AE00038A09F /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | ); 62 | runOnlyForDeploymentPostprocessing = 0; 63 | }; 64 | /* End PBXFrameworksBuildPhase section */ 65 | 66 | /* Begin PBXGroup section */ 67 | ECC8141B29334ADF0038A09F = { 68 | isa = PBXGroup; 69 | children = ( 70 | ECC8142629334ADF0038A09F /* GitHubSearch */, 71 | ECC8143729334AE00038A09F /* GitHubSearchTests */, 72 | ECC8142529334ADF0038A09F /* Products */, 73 | ); 74 | sourceTree = ""; 75 | }; 76 | ECC8142529334ADF0038A09F /* Products */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | ECC8142429334ADF0038A09F /* GitHubSearch.app */, 80 | ECC8143429334AE00038A09F /* GitHubSearchTests.xctest */, 81 | ); 82 | name = Products; 83 | sourceTree = ""; 84 | }; 85 | ECC8142629334ADF0038A09F /* GitHubSearch */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | ECC8142729334ADF0038A09F /* GitHubSearchApp.swift */, 89 | EC4BC238293463F4001B2F91 /* APIError.swift */, 90 | ECC8145729334C6B0038A09F /* Repository */, 91 | ECC8145129334AFC0038A09F /* Resources */, 92 | ); 93 | path = GitHubSearch; 94 | sourceTree = ""; 95 | }; 96 | ECC8142D29334AE00038A09F /* Preview Content */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | ECC8142E29334AE00038A09F /* Preview Assets.xcassets */, 100 | ); 101 | path = "Preview Content"; 102 | sourceTree = ""; 103 | }; 104 | ECC8143729334AE00038A09F /* GitHubSearchTests */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | ECC8143829334AE00038A09F /* RepositoryTests.swift */, 108 | ); 109 | path = GitHubSearchTests; 110 | sourceTree = ""; 111 | }; 112 | ECC8145129334AFC0038A09F /* Resources */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | ECC8142D29334AE00038A09F /* Preview Content */, 116 | ECC8142B29334AE00038A09F /* Assets.xcassets */, 117 | ); 118 | path = Resources; 119 | sourceTree = ""; 120 | }; 121 | ECC8145729334C6B0038A09F /* Repository */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | ECC8145B29334CB70038A09F /* RepoSearchView.swift */, 125 | ECC8145929334CB70038A09F /* RepoSearch.swift */, 126 | ECC8145829334CB70038A09F /* RepoSearchClient.swift */, 127 | ECC8145A29334CB70038A09F /* RepositoryModel.swift */, 128 | ); 129 | path = Repository; 130 | sourceTree = ""; 131 | }; 132 | /* End PBXGroup section */ 133 | 134 | /* Begin PBXNativeTarget section */ 135 | ECC8142329334ADF0038A09F /* GitHubSearch */ = { 136 | isa = PBXNativeTarget; 137 | buildConfigurationList = ECC8144829334AE00038A09F /* Build configuration list for PBXNativeTarget "GitHubSearch" */; 138 | buildPhases = ( 139 | ECC8142029334ADF0038A09F /* Sources */, 140 | ECC8142129334ADF0038A09F /* Frameworks */, 141 | ECC8142229334ADF0038A09F /* Resources */, 142 | ); 143 | buildRules = ( 144 | ); 145 | dependencies = ( 146 | ); 147 | name = GitHubSearch; 148 | packageProductDependencies = ( 149 | ECC8145329334C590038A09F /* ComposableArchitecture */, 150 | ECC8145529334C590038A09F /* Dependencies */, 151 | ); 152 | productName = GitHubSearch; 153 | productReference = ECC8142429334ADF0038A09F /* GitHubSearch.app */; 154 | productType = "com.apple.product-type.application"; 155 | }; 156 | ECC8143329334AE00038A09F /* GitHubSearchTests */ = { 157 | isa = PBXNativeTarget; 158 | buildConfigurationList = ECC8144B29334AE00038A09F /* Build configuration list for PBXNativeTarget "GitHubSearchTests" */; 159 | buildPhases = ( 160 | ECC8143029334AE00038A09F /* Sources */, 161 | ECC8143129334AE00038A09F /* Frameworks */, 162 | ECC8143229334AE00038A09F /* Resources */, 163 | ); 164 | buildRules = ( 165 | ); 166 | dependencies = ( 167 | ECC8143629334AE00038A09F /* PBXTargetDependency */, 168 | ); 169 | name = GitHubSearchTests; 170 | productName = GitHubSearchTests; 171 | productReference = ECC8143429334AE00038A09F /* GitHubSearchTests.xctest */; 172 | productType = "com.apple.product-type.bundle.unit-test"; 173 | }; 174 | /* End PBXNativeTarget section */ 175 | 176 | /* Begin PBXProject section */ 177 | ECC8141C29334ADF0038A09F /* Project object */ = { 178 | isa = PBXProject; 179 | attributes = { 180 | BuildIndependentTargetsInParallel = 1; 181 | LastSwiftUpdateCheck = 1410; 182 | LastUpgradeCheck = 1410; 183 | TargetAttributes = { 184 | ECC8142329334ADF0038A09F = { 185 | CreatedOnToolsVersion = 14.1; 186 | }; 187 | ECC8143329334AE00038A09F = { 188 | CreatedOnToolsVersion = 14.1; 189 | TestTargetID = ECC8142329334ADF0038A09F; 190 | }; 191 | }; 192 | }; 193 | buildConfigurationList = ECC8141F29334ADF0038A09F /* Build configuration list for PBXProject "GitHubSearch" */; 194 | compatibilityVersion = "Xcode 14.0"; 195 | developmentRegion = en; 196 | hasScannedForEncodings = 0; 197 | knownRegions = ( 198 | en, 199 | Base, 200 | ); 201 | mainGroup = ECC8141B29334ADF0038A09F; 202 | packageReferences = ( 203 | ECC8145229334C590038A09F /* XCRemoteSwiftPackageReference "swift-composable-architecture" */, 204 | ); 205 | productRefGroup = ECC8142529334ADF0038A09F /* Products */; 206 | projectDirPath = ""; 207 | projectRoot = ""; 208 | targets = ( 209 | ECC8142329334ADF0038A09F /* GitHubSearch */, 210 | ECC8143329334AE00038A09F /* GitHubSearchTests */, 211 | ); 212 | }; 213 | /* End PBXProject section */ 214 | 215 | /* Begin PBXResourcesBuildPhase section */ 216 | ECC8142229334ADF0038A09F /* Resources */ = { 217 | isa = PBXResourcesBuildPhase; 218 | buildActionMask = 2147483647; 219 | files = ( 220 | ECC8142F29334AE00038A09F /* Preview Assets.xcassets in Resources */, 221 | ECC8142C29334AE00038A09F /* Assets.xcassets in Resources */, 222 | ); 223 | runOnlyForDeploymentPostprocessing = 0; 224 | }; 225 | ECC8143229334AE00038A09F /* Resources */ = { 226 | isa = PBXResourcesBuildPhase; 227 | buildActionMask = 2147483647; 228 | files = ( 229 | ); 230 | runOnlyForDeploymentPostprocessing = 0; 231 | }; 232 | /* End PBXResourcesBuildPhase section */ 233 | 234 | /* Begin PBXSourcesBuildPhase section */ 235 | ECC8142029334ADF0038A09F /* Sources */ = { 236 | isa = PBXSourcesBuildPhase; 237 | buildActionMask = 2147483647; 238 | files = ( 239 | ECC8145C29334CB70038A09F /* RepoSearchClient.swift in Sources */, 240 | ECC8145E29334CB70038A09F /* RepositoryModel.swift in Sources */, 241 | ECC8142829334ADF0038A09F /* GitHubSearchApp.swift in Sources */, 242 | ECC8145F29334CB70038A09F /* RepoSearchView.swift in Sources */, 243 | ECC8145D29334CB70038A09F /* RepoSearch.swift in Sources */, 244 | EC4BC239293463F4001B2F91 /* APIError.swift in Sources */, 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | }; 248 | ECC8143029334AE00038A09F /* Sources */ = { 249 | isa = PBXSourcesBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | ECC8143929334AE00038A09F /* RepositoryTests.swift in Sources */, 253 | ); 254 | runOnlyForDeploymentPostprocessing = 0; 255 | }; 256 | /* End PBXSourcesBuildPhase section */ 257 | 258 | /* Begin PBXTargetDependency section */ 259 | ECC8143629334AE00038A09F /* PBXTargetDependency */ = { 260 | isa = PBXTargetDependency; 261 | target = ECC8142329334ADF0038A09F /* GitHubSearch */; 262 | targetProxy = ECC8143529334AE00038A09F /* PBXContainerItemProxy */; 263 | }; 264 | /* End PBXTargetDependency section */ 265 | 266 | /* Begin XCBuildConfiguration section */ 267 | ECC8144629334AE00038A09F /* Debug */ = { 268 | isa = XCBuildConfiguration; 269 | buildSettings = { 270 | ALWAYS_SEARCH_USER_PATHS = NO; 271 | CLANG_ANALYZER_NONNULL = YES; 272 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 273 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 274 | CLANG_ENABLE_MODULES = YES; 275 | CLANG_ENABLE_OBJC_ARC = YES; 276 | CLANG_ENABLE_OBJC_WEAK = YES; 277 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 278 | CLANG_WARN_BOOL_CONVERSION = YES; 279 | CLANG_WARN_COMMA = YES; 280 | CLANG_WARN_CONSTANT_CONVERSION = YES; 281 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 282 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 283 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 284 | CLANG_WARN_EMPTY_BODY = YES; 285 | CLANG_WARN_ENUM_CONVERSION = YES; 286 | CLANG_WARN_INFINITE_RECURSION = YES; 287 | CLANG_WARN_INT_CONVERSION = YES; 288 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 289 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 290 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 291 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 292 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 293 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 294 | CLANG_WARN_STRICT_PROTOTYPES = YES; 295 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 296 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 297 | CLANG_WARN_UNREACHABLE_CODE = YES; 298 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 299 | COPY_PHASE_STRIP = NO; 300 | DEBUG_INFORMATION_FORMAT = dwarf; 301 | ENABLE_STRICT_OBJC_MSGSEND = YES; 302 | ENABLE_TESTABILITY = YES; 303 | GCC_C_LANGUAGE_STANDARD = gnu11; 304 | GCC_DYNAMIC_NO_PIC = NO; 305 | GCC_NO_COMMON_BLOCKS = YES; 306 | GCC_OPTIMIZATION_LEVEL = 0; 307 | GCC_PREPROCESSOR_DEFINITIONS = ( 308 | "DEBUG=1", 309 | "$(inherited)", 310 | ); 311 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 312 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 313 | GCC_WARN_UNDECLARED_SELECTOR = YES; 314 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 315 | GCC_WARN_UNUSED_FUNCTION = YES; 316 | GCC_WARN_UNUSED_VARIABLE = YES; 317 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 318 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 319 | MTL_FAST_MATH = YES; 320 | ONLY_ACTIVE_ARCH = YES; 321 | SDKROOT = iphoneos; 322 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 323 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 324 | }; 325 | name = Debug; 326 | }; 327 | ECC8144729334AE00038A09F /* Release */ = { 328 | isa = XCBuildConfiguration; 329 | buildSettings = { 330 | ALWAYS_SEARCH_USER_PATHS = NO; 331 | CLANG_ANALYZER_NONNULL = YES; 332 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 333 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 334 | CLANG_ENABLE_MODULES = YES; 335 | CLANG_ENABLE_OBJC_ARC = YES; 336 | CLANG_ENABLE_OBJC_WEAK = YES; 337 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 338 | CLANG_WARN_BOOL_CONVERSION = YES; 339 | CLANG_WARN_COMMA = YES; 340 | CLANG_WARN_CONSTANT_CONVERSION = YES; 341 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 342 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 343 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 344 | CLANG_WARN_EMPTY_BODY = YES; 345 | CLANG_WARN_ENUM_CONVERSION = YES; 346 | CLANG_WARN_INFINITE_RECURSION = YES; 347 | CLANG_WARN_INT_CONVERSION = YES; 348 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 349 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 350 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 351 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 352 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 353 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 354 | CLANG_WARN_STRICT_PROTOTYPES = YES; 355 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 356 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 357 | CLANG_WARN_UNREACHABLE_CODE = YES; 358 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 359 | COPY_PHASE_STRIP = NO; 360 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 361 | ENABLE_NS_ASSERTIONS = NO; 362 | ENABLE_STRICT_OBJC_MSGSEND = YES; 363 | GCC_C_LANGUAGE_STANDARD = gnu11; 364 | GCC_NO_COMMON_BLOCKS = YES; 365 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 366 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 367 | GCC_WARN_UNDECLARED_SELECTOR = YES; 368 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 369 | GCC_WARN_UNUSED_FUNCTION = YES; 370 | GCC_WARN_UNUSED_VARIABLE = YES; 371 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 372 | MTL_ENABLE_DEBUG_INFO = NO; 373 | MTL_FAST_MATH = YES; 374 | SDKROOT = iphoneos; 375 | SWIFT_COMPILATION_MODE = wholemodule; 376 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 377 | VALIDATE_PRODUCT = YES; 378 | }; 379 | name = Release; 380 | }; 381 | ECC8144929334AE00038A09F /* Debug */ = { 382 | isa = XCBuildConfiguration; 383 | buildSettings = { 384 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 385 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 386 | CODE_SIGN_STYLE = Automatic; 387 | CURRENT_PROJECT_VERSION = 1; 388 | DEVELOPMENT_ASSET_PATHS = "\"GitHubSearch/Resources/Preview Content\""; 389 | DEVELOPMENT_TEAM = 8B27K52UU7; 390 | ENABLE_PREVIEWS = YES; 391 | GENERATE_INFOPLIST_FILE = YES; 392 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 393 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 394 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 395 | INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; 396 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; 397 | LD_RUNPATH_SEARCH_PATHS = ( 398 | "$(inherited)", 399 | "@executable_path/Frameworks", 400 | ); 401 | MARKETING_VERSION = 1.0; 402 | PRODUCT_BUNDLE_IDENTIFIER = "com.dy-kim.GitHubSearch"; 403 | PRODUCT_NAME = "$(TARGET_NAME)"; 404 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; 405 | SUPPORTS_MACCATALYST = NO; 406 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 407 | SWIFT_EMIT_LOC_STRINGS = YES; 408 | SWIFT_VERSION = 5.0; 409 | TARGETED_DEVICE_FAMILY = 1; 410 | }; 411 | name = Debug; 412 | }; 413 | ECC8144A29334AE00038A09F /* Release */ = { 414 | isa = XCBuildConfiguration; 415 | buildSettings = { 416 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 417 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 418 | CODE_SIGN_STYLE = Automatic; 419 | CURRENT_PROJECT_VERSION = 1; 420 | DEVELOPMENT_ASSET_PATHS = "\"GitHubSearch/Resources/Preview Content\""; 421 | DEVELOPMENT_TEAM = 8B27K52UU7; 422 | ENABLE_PREVIEWS = YES; 423 | GENERATE_INFOPLIST_FILE = YES; 424 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 425 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 426 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 427 | INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; 428 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; 429 | LD_RUNPATH_SEARCH_PATHS = ( 430 | "$(inherited)", 431 | "@executable_path/Frameworks", 432 | ); 433 | MARKETING_VERSION = 1.0; 434 | PRODUCT_BUNDLE_IDENTIFIER = "com.dy-kim.GitHubSearch"; 435 | PRODUCT_NAME = "$(TARGET_NAME)"; 436 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; 437 | SUPPORTS_MACCATALYST = NO; 438 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 439 | SWIFT_EMIT_LOC_STRINGS = YES; 440 | SWIFT_VERSION = 5.0; 441 | TARGETED_DEVICE_FAMILY = 1; 442 | }; 443 | name = Release; 444 | }; 445 | ECC8144C29334AE00038A09F /* Debug */ = { 446 | isa = XCBuildConfiguration; 447 | buildSettings = { 448 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 449 | BUNDLE_LOADER = "$(TEST_HOST)"; 450 | CODE_SIGN_STYLE = Automatic; 451 | CURRENT_PROJECT_VERSION = 1; 452 | DEVELOPMENT_TEAM = 8B27K52UU7; 453 | GENERATE_INFOPLIST_FILE = YES; 454 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 455 | MARKETING_VERSION = 1.0; 456 | PRODUCT_BUNDLE_IDENTIFIER = "com.dy-kim.GitHubSearchTests"; 457 | PRODUCT_NAME = "$(TARGET_NAME)"; 458 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; 459 | SUPPORTS_MACCATALYST = NO; 460 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 461 | SWIFT_EMIT_LOC_STRINGS = NO; 462 | SWIFT_VERSION = 5.0; 463 | TARGETED_DEVICE_FAMILY = 1; 464 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GitHubSearch.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/GitHubSearch"; 465 | }; 466 | name = Debug; 467 | }; 468 | ECC8144D29334AE00038A09F /* Release */ = { 469 | isa = XCBuildConfiguration; 470 | buildSettings = { 471 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 472 | BUNDLE_LOADER = "$(TEST_HOST)"; 473 | CODE_SIGN_STYLE = Automatic; 474 | CURRENT_PROJECT_VERSION = 1; 475 | DEVELOPMENT_TEAM = 8B27K52UU7; 476 | GENERATE_INFOPLIST_FILE = YES; 477 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 478 | MARKETING_VERSION = 1.0; 479 | PRODUCT_BUNDLE_IDENTIFIER = "com.dy-kim.GitHubSearchTests"; 480 | PRODUCT_NAME = "$(TARGET_NAME)"; 481 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; 482 | SUPPORTS_MACCATALYST = NO; 483 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 484 | SWIFT_EMIT_LOC_STRINGS = NO; 485 | SWIFT_VERSION = 5.0; 486 | TARGETED_DEVICE_FAMILY = 1; 487 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GitHubSearch.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/GitHubSearch"; 488 | }; 489 | name = Release; 490 | }; 491 | /* End XCBuildConfiguration section */ 492 | 493 | /* Begin XCConfigurationList section */ 494 | ECC8141F29334ADF0038A09F /* Build configuration list for PBXProject "GitHubSearch" */ = { 495 | isa = XCConfigurationList; 496 | buildConfigurations = ( 497 | ECC8144629334AE00038A09F /* Debug */, 498 | ECC8144729334AE00038A09F /* Release */, 499 | ); 500 | defaultConfigurationIsVisible = 0; 501 | defaultConfigurationName = Release; 502 | }; 503 | ECC8144829334AE00038A09F /* Build configuration list for PBXNativeTarget "GitHubSearch" */ = { 504 | isa = XCConfigurationList; 505 | buildConfigurations = ( 506 | ECC8144929334AE00038A09F /* Debug */, 507 | ECC8144A29334AE00038A09F /* Release */, 508 | ); 509 | defaultConfigurationIsVisible = 0; 510 | defaultConfigurationName = Release; 511 | }; 512 | ECC8144B29334AE00038A09F /* Build configuration list for PBXNativeTarget "GitHubSearchTests" */ = { 513 | isa = XCConfigurationList; 514 | buildConfigurations = ( 515 | ECC8144C29334AE00038A09F /* Debug */, 516 | ECC8144D29334AE00038A09F /* Release */, 517 | ); 518 | defaultConfigurationIsVisible = 0; 519 | defaultConfigurationName = Release; 520 | }; 521 | /* End XCConfigurationList section */ 522 | 523 | /* Begin XCRemoteSwiftPackageReference section */ 524 | ECC8145229334C590038A09F /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = { 525 | isa = XCRemoteSwiftPackageReference; 526 | repositoryURL = "https://github.com/pointfreeco/swift-composable-architecture"; 527 | requirement = { 528 | kind = exactVersion; 529 | version = 0.46.0; 530 | }; 531 | }; 532 | /* End XCRemoteSwiftPackageReference section */ 533 | 534 | /* Begin XCSwiftPackageProductDependency section */ 535 | ECC8145329334C590038A09F /* ComposableArchitecture */ = { 536 | isa = XCSwiftPackageProductDependency; 537 | package = ECC8145229334C590038A09F /* XCRemoteSwiftPackageReference "swift-composable-architecture" */; 538 | productName = ComposableArchitecture; 539 | }; 540 | ECC8145529334C590038A09F /* Dependencies */ = { 541 | isa = XCSwiftPackageProductDependency; 542 | package = ECC8145229334C590038A09F /* XCRemoteSwiftPackageReference "swift-composable-architecture" */; 543 | productName = Dependencies; 544 | }; 545 | /* End XCSwiftPackageProductDependency section */ 546 | }; 547 | rootObject = ECC8141C29334ADF0038A09F /* Project object */; 548 | } 549 | -------------------------------------------------------------------------------- /final/GitHubSearch-final.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | EC4BC239293463F4001B2F91 /* APIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC4BC238293463F4001B2F91 /* APIError.swift */; }; 11 | ECC8142829334ADF0038A09F /* GitHubSearchApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC8142729334ADF0038A09F /* GitHubSearchApp.swift */; }; 12 | ECC8142C29334AE00038A09F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ECC8142B29334AE00038A09F /* Assets.xcassets */; }; 13 | ECC8142F29334AE00038A09F /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ECC8142E29334AE00038A09F /* Preview Assets.xcassets */; }; 14 | ECC8143929334AE00038A09F /* RepositoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC8143829334AE00038A09F /* RepositoryTests.swift */; }; 15 | ECC8145429334C590038A09F /* ComposableArchitecture in Frameworks */ = {isa = PBXBuildFile; productRef = ECC8145329334C590038A09F /* ComposableArchitecture */; }; 16 | ECC8145629334C590038A09F /* Dependencies in Frameworks */ = {isa = PBXBuildFile; productRef = ECC8145529334C590038A09F /* Dependencies */; }; 17 | ECC8145C29334CB70038A09F /* RepoSearchClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC8145829334CB70038A09F /* RepoSearchClient.swift */; }; 18 | ECC8145D29334CB70038A09F /* RepoSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC8145929334CB70038A09F /* RepoSearch.swift */; }; 19 | ECC8145E29334CB70038A09F /* RepositoryModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC8145A29334CB70038A09F /* RepositoryModel.swift */; }; 20 | ECC8145F29334CB70038A09F /* RepoSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC8145B29334CB70038A09F /* RepoSearchView.swift */; }; 21 | FFFF0B4B29ED3F49005830E8 /* LoadingState.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFFF0B4A29ED3F49005830E8 /* LoadingState.swift */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | ECC8143529334AE00038A09F /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = ECC8141C29334ADF0038A09F /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = ECC8142329334ADF0038A09F; 30 | remoteInfo = GitHubSearch; 31 | }; 32 | /* End PBXContainerItemProxy section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | EC4BC238293463F4001B2F91 /* APIError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIError.swift; sourceTree = ""; }; 36 | ECC8142429334ADF0038A09F /* GitHubSearch-final.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "GitHubSearch-final.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | ECC8142729334ADF0038A09F /* GitHubSearchApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GitHubSearchApp.swift; sourceTree = ""; }; 38 | ECC8142B29334AE00038A09F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 39 | ECC8142E29334AE00038A09F /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 40 | ECC8143429334AE00038A09F /* GitHubSearch-finalTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "GitHubSearch-finalTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | ECC8143829334AE00038A09F /* RepositoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepositoryTests.swift; sourceTree = ""; }; 42 | ECC8145829334CB70038A09F /* RepoSearchClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepoSearchClient.swift; sourceTree = ""; }; 43 | ECC8145929334CB70038A09F /* RepoSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepoSearch.swift; sourceTree = ""; }; 44 | ECC8145A29334CB70038A09F /* RepositoryModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepositoryModel.swift; sourceTree = ""; }; 45 | ECC8145B29334CB70038A09F /* RepoSearchView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepoSearchView.swift; sourceTree = ""; }; 46 | FFFF0B4A29ED3F49005830E8 /* LoadingState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingState.swift; sourceTree = ""; }; 47 | /* End PBXFileReference section */ 48 | 49 | /* Begin PBXFrameworksBuildPhase section */ 50 | ECC8142129334ADF0038A09F /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | ECC8145429334C590038A09F /* ComposableArchitecture in Frameworks */, 55 | ECC8145629334C590038A09F /* Dependencies in Frameworks */, 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | ECC8143129334AE00038A09F /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | ECC8141B29334ADF0038A09F = { 70 | isa = PBXGroup; 71 | children = ( 72 | ECC8142629334ADF0038A09F /* GitHubSearch */, 73 | ECC8143729334AE00038A09F /* GitHubSearchTests */, 74 | ECC8142529334ADF0038A09F /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | ECC8142529334ADF0038A09F /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | ECC8142429334ADF0038A09F /* GitHubSearch-final.app */, 82 | ECC8143429334AE00038A09F /* GitHubSearch-finalTests.xctest */, 83 | ); 84 | name = Products; 85 | sourceTree = ""; 86 | }; 87 | ECC8142629334ADF0038A09F /* GitHubSearch */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | ECC8142729334ADF0038A09F /* GitHubSearchApp.swift */, 91 | EC4BC238293463F4001B2F91 /* APIError.swift */, 92 | FFFF0B4A29ED3F49005830E8 /* LoadingState.swift */, 93 | ECC8145729334C6B0038A09F /* Repository */, 94 | ECC8145129334AFC0038A09F /* Resources */, 95 | ); 96 | path = GitHubSearch; 97 | sourceTree = ""; 98 | }; 99 | ECC8142D29334AE00038A09F /* Preview Content */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | ECC8142E29334AE00038A09F /* Preview Assets.xcassets */, 103 | ); 104 | path = "Preview Content"; 105 | sourceTree = ""; 106 | }; 107 | ECC8143729334AE00038A09F /* GitHubSearchTests */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | ECC8143829334AE00038A09F /* RepositoryTests.swift */, 111 | ); 112 | path = GitHubSearchTests; 113 | sourceTree = ""; 114 | }; 115 | ECC8145129334AFC0038A09F /* Resources */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | ECC8142D29334AE00038A09F /* Preview Content */, 119 | ECC8142B29334AE00038A09F /* Assets.xcassets */, 120 | ); 121 | path = Resources; 122 | sourceTree = ""; 123 | }; 124 | ECC8145729334C6B0038A09F /* Repository */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | ECC8145B29334CB70038A09F /* RepoSearchView.swift */, 128 | ECC8145929334CB70038A09F /* RepoSearch.swift */, 129 | ECC8145829334CB70038A09F /* RepoSearchClient.swift */, 130 | ECC8145A29334CB70038A09F /* RepositoryModel.swift */, 131 | ); 132 | path = Repository; 133 | sourceTree = ""; 134 | }; 135 | /* End PBXGroup section */ 136 | 137 | /* Begin PBXNativeTarget section */ 138 | ECC8142329334ADF0038A09F /* GitHubSearch-final */ = { 139 | isa = PBXNativeTarget; 140 | buildConfigurationList = ECC8144829334AE00038A09F /* Build configuration list for PBXNativeTarget "GitHubSearch-final" */; 141 | buildPhases = ( 142 | ECC8142029334ADF0038A09F /* Sources */, 143 | ECC8142129334ADF0038A09F /* Frameworks */, 144 | ECC8142229334ADF0038A09F /* Resources */, 145 | ); 146 | buildRules = ( 147 | ); 148 | dependencies = ( 149 | ); 150 | name = "GitHubSearch-final"; 151 | packageProductDependencies = ( 152 | ECC8145329334C590038A09F /* ComposableArchitecture */, 153 | ECC8145529334C590038A09F /* Dependencies */, 154 | ); 155 | productName = GitHubSearch; 156 | productReference = ECC8142429334ADF0038A09F /* GitHubSearch-final.app */; 157 | productType = "com.apple.product-type.application"; 158 | }; 159 | ECC8143329334AE00038A09F /* GitHubSearch-finalTests */ = { 160 | isa = PBXNativeTarget; 161 | buildConfigurationList = ECC8144B29334AE00038A09F /* Build configuration list for PBXNativeTarget "GitHubSearch-finalTests" */; 162 | buildPhases = ( 163 | ECC8143029334AE00038A09F /* Sources */, 164 | ECC8143129334AE00038A09F /* Frameworks */, 165 | ECC8143229334AE00038A09F /* Resources */, 166 | ); 167 | buildRules = ( 168 | ); 169 | dependencies = ( 170 | ECC8143629334AE00038A09F /* PBXTargetDependency */, 171 | ); 172 | name = "GitHubSearch-finalTests"; 173 | productName = GitHubSearchTests; 174 | productReference = ECC8143429334AE00038A09F /* GitHubSearch-finalTests.xctest */; 175 | productType = "com.apple.product-type.bundle.unit-test"; 176 | }; 177 | /* End PBXNativeTarget section */ 178 | 179 | /* Begin PBXProject section */ 180 | ECC8141C29334ADF0038A09F /* Project object */ = { 181 | isa = PBXProject; 182 | attributes = { 183 | BuildIndependentTargetsInParallel = 1; 184 | LastSwiftUpdateCheck = 1410; 185 | LastUpgradeCheck = 1410; 186 | TargetAttributes = { 187 | ECC8142329334ADF0038A09F = { 188 | CreatedOnToolsVersion = 14.1; 189 | }; 190 | ECC8143329334AE00038A09F = { 191 | CreatedOnToolsVersion = 14.1; 192 | TestTargetID = ECC8142329334ADF0038A09F; 193 | }; 194 | }; 195 | }; 196 | buildConfigurationList = ECC8141F29334ADF0038A09F /* Build configuration list for PBXProject "GitHubSearch-final" */; 197 | compatibilityVersion = "Xcode 14.0"; 198 | developmentRegion = en; 199 | hasScannedForEncodings = 0; 200 | knownRegions = ( 201 | en, 202 | Base, 203 | ); 204 | mainGroup = ECC8141B29334ADF0038A09F; 205 | packageReferences = ( 206 | ECC8145229334C590038A09F /* XCRemoteSwiftPackageReference "swift-composable-architecture" */, 207 | ); 208 | productRefGroup = ECC8142529334ADF0038A09F /* Products */; 209 | projectDirPath = ""; 210 | projectRoot = ""; 211 | targets = ( 212 | ECC8142329334ADF0038A09F /* GitHubSearch-final */, 213 | ECC8143329334AE00038A09F /* GitHubSearch-finalTests */, 214 | ); 215 | }; 216 | /* End PBXProject section */ 217 | 218 | /* Begin PBXResourcesBuildPhase section */ 219 | ECC8142229334ADF0038A09F /* Resources */ = { 220 | isa = PBXResourcesBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | ECC8142F29334AE00038A09F /* Preview Assets.xcassets in Resources */, 224 | ECC8142C29334AE00038A09F /* Assets.xcassets in Resources */, 225 | ); 226 | runOnlyForDeploymentPostprocessing = 0; 227 | }; 228 | ECC8143229334AE00038A09F /* Resources */ = { 229 | isa = PBXResourcesBuildPhase; 230 | buildActionMask = 2147483647; 231 | files = ( 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | /* End PBXResourcesBuildPhase section */ 236 | 237 | /* Begin PBXSourcesBuildPhase section */ 238 | ECC8142029334ADF0038A09F /* Sources */ = { 239 | isa = PBXSourcesBuildPhase; 240 | buildActionMask = 2147483647; 241 | files = ( 242 | ECC8145C29334CB70038A09F /* RepoSearchClient.swift in Sources */, 243 | FFFF0B4B29ED3F49005830E8 /* LoadingState.swift in Sources */, 244 | ECC8145E29334CB70038A09F /* RepositoryModel.swift in Sources */, 245 | ECC8142829334ADF0038A09F /* GitHubSearchApp.swift in Sources */, 246 | ECC8145F29334CB70038A09F /* RepoSearchView.swift in Sources */, 247 | ECC8145D29334CB70038A09F /* RepoSearch.swift in Sources */, 248 | EC4BC239293463F4001B2F91 /* APIError.swift in Sources */, 249 | ); 250 | runOnlyForDeploymentPostprocessing = 0; 251 | }; 252 | ECC8143029334AE00038A09F /* Sources */ = { 253 | isa = PBXSourcesBuildPhase; 254 | buildActionMask = 2147483647; 255 | files = ( 256 | ECC8143929334AE00038A09F /* RepositoryTests.swift in Sources */, 257 | ); 258 | runOnlyForDeploymentPostprocessing = 0; 259 | }; 260 | /* End PBXSourcesBuildPhase section */ 261 | 262 | /* Begin PBXTargetDependency section */ 263 | ECC8143629334AE00038A09F /* PBXTargetDependency */ = { 264 | isa = PBXTargetDependency; 265 | target = ECC8142329334ADF0038A09F /* GitHubSearch-final */; 266 | targetProxy = ECC8143529334AE00038A09F /* PBXContainerItemProxy */; 267 | }; 268 | /* End PBXTargetDependency section */ 269 | 270 | /* Begin XCBuildConfiguration section */ 271 | ECC8144629334AE00038A09F /* Debug */ = { 272 | isa = XCBuildConfiguration; 273 | buildSettings = { 274 | ALWAYS_SEARCH_USER_PATHS = NO; 275 | CLANG_ANALYZER_NONNULL = YES; 276 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 277 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 278 | CLANG_ENABLE_MODULES = YES; 279 | CLANG_ENABLE_OBJC_ARC = YES; 280 | CLANG_ENABLE_OBJC_WEAK = YES; 281 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 282 | CLANG_WARN_BOOL_CONVERSION = YES; 283 | CLANG_WARN_COMMA = YES; 284 | CLANG_WARN_CONSTANT_CONVERSION = YES; 285 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 286 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 287 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 288 | CLANG_WARN_EMPTY_BODY = YES; 289 | CLANG_WARN_ENUM_CONVERSION = YES; 290 | CLANG_WARN_INFINITE_RECURSION = YES; 291 | CLANG_WARN_INT_CONVERSION = YES; 292 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 293 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 294 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 295 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 296 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 297 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 298 | CLANG_WARN_STRICT_PROTOTYPES = YES; 299 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 300 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 301 | CLANG_WARN_UNREACHABLE_CODE = YES; 302 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 303 | COPY_PHASE_STRIP = NO; 304 | DEBUG_INFORMATION_FORMAT = dwarf; 305 | ENABLE_STRICT_OBJC_MSGSEND = YES; 306 | ENABLE_TESTABILITY = YES; 307 | GCC_C_LANGUAGE_STANDARD = gnu11; 308 | GCC_DYNAMIC_NO_PIC = NO; 309 | GCC_NO_COMMON_BLOCKS = YES; 310 | GCC_OPTIMIZATION_LEVEL = 0; 311 | GCC_PREPROCESSOR_DEFINITIONS = ( 312 | "DEBUG=1", 313 | "$(inherited)", 314 | ); 315 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 316 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 317 | GCC_WARN_UNDECLARED_SELECTOR = YES; 318 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 319 | GCC_WARN_UNUSED_FUNCTION = YES; 320 | GCC_WARN_UNUSED_VARIABLE = YES; 321 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 322 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 323 | MTL_FAST_MATH = YES; 324 | ONLY_ACTIVE_ARCH = YES; 325 | SDKROOT = iphoneos; 326 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 327 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 328 | }; 329 | name = Debug; 330 | }; 331 | ECC8144729334AE00038A09F /* Release */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | ALWAYS_SEARCH_USER_PATHS = NO; 335 | CLANG_ANALYZER_NONNULL = YES; 336 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 337 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 338 | CLANG_ENABLE_MODULES = YES; 339 | CLANG_ENABLE_OBJC_ARC = YES; 340 | CLANG_ENABLE_OBJC_WEAK = YES; 341 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 342 | CLANG_WARN_BOOL_CONVERSION = YES; 343 | CLANG_WARN_COMMA = YES; 344 | CLANG_WARN_CONSTANT_CONVERSION = YES; 345 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 346 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 347 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 348 | CLANG_WARN_EMPTY_BODY = YES; 349 | CLANG_WARN_ENUM_CONVERSION = YES; 350 | CLANG_WARN_INFINITE_RECURSION = YES; 351 | CLANG_WARN_INT_CONVERSION = YES; 352 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 353 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 354 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 355 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 356 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 357 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 358 | CLANG_WARN_STRICT_PROTOTYPES = YES; 359 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 360 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 361 | CLANG_WARN_UNREACHABLE_CODE = YES; 362 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 363 | COPY_PHASE_STRIP = NO; 364 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 365 | ENABLE_NS_ASSERTIONS = NO; 366 | ENABLE_STRICT_OBJC_MSGSEND = YES; 367 | GCC_C_LANGUAGE_STANDARD = gnu11; 368 | GCC_NO_COMMON_BLOCKS = YES; 369 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 370 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 371 | GCC_WARN_UNDECLARED_SELECTOR = YES; 372 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 373 | GCC_WARN_UNUSED_FUNCTION = YES; 374 | GCC_WARN_UNUSED_VARIABLE = YES; 375 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 376 | MTL_ENABLE_DEBUG_INFO = NO; 377 | MTL_FAST_MATH = YES; 378 | SDKROOT = iphoneos; 379 | SWIFT_COMPILATION_MODE = wholemodule; 380 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 381 | VALIDATE_PRODUCT = YES; 382 | }; 383 | name = Release; 384 | }; 385 | ECC8144929334AE00038A09F /* Debug */ = { 386 | isa = XCBuildConfiguration; 387 | buildSettings = { 388 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 389 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 390 | CODE_SIGN_STYLE = Automatic; 391 | CURRENT_PROJECT_VERSION = 1; 392 | DEVELOPMENT_ASSET_PATHS = "\"GitHubSearch/Resources/Preview Content\""; 393 | DEVELOPMENT_TEAM = 8B27K52UU7; 394 | ENABLE_PREVIEWS = YES; 395 | GENERATE_INFOPLIST_FILE = YES; 396 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 397 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 398 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 399 | INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; 400 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; 401 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 402 | LD_RUNPATH_SEARCH_PATHS = ( 403 | "$(inherited)", 404 | "@executable_path/Frameworks", 405 | ); 406 | MARKETING_VERSION = 1.0; 407 | PRODUCT_BUNDLE_IDENTIFIER = "com.dy-kim.GitHubSearch"; 408 | PRODUCT_NAME = "$(TARGET_NAME)"; 409 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; 410 | SUPPORTS_MACCATALYST = NO; 411 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 412 | SWIFT_EMIT_LOC_STRINGS = YES; 413 | SWIFT_VERSION = 5.0; 414 | TARGETED_DEVICE_FAMILY = 1; 415 | }; 416 | name = Debug; 417 | }; 418 | ECC8144A29334AE00038A09F /* Release */ = { 419 | isa = XCBuildConfiguration; 420 | buildSettings = { 421 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 422 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 423 | CODE_SIGN_STYLE = Automatic; 424 | CURRENT_PROJECT_VERSION = 1; 425 | DEVELOPMENT_ASSET_PATHS = "\"GitHubSearch/Resources/Preview Content\""; 426 | DEVELOPMENT_TEAM = 8B27K52UU7; 427 | ENABLE_PREVIEWS = YES; 428 | GENERATE_INFOPLIST_FILE = YES; 429 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 430 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 431 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 432 | INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; 433 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; 434 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 435 | LD_RUNPATH_SEARCH_PATHS = ( 436 | "$(inherited)", 437 | "@executable_path/Frameworks", 438 | ); 439 | MARKETING_VERSION = 1.0; 440 | PRODUCT_BUNDLE_IDENTIFIER = "com.dy-kim.GitHubSearch"; 441 | PRODUCT_NAME = "$(TARGET_NAME)"; 442 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; 443 | SUPPORTS_MACCATALYST = NO; 444 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 445 | SWIFT_EMIT_LOC_STRINGS = YES; 446 | SWIFT_VERSION = 5.0; 447 | TARGETED_DEVICE_FAMILY = 1; 448 | }; 449 | name = Release; 450 | }; 451 | ECC8144C29334AE00038A09F /* Debug */ = { 452 | isa = XCBuildConfiguration; 453 | buildSettings = { 454 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 455 | BUNDLE_LOADER = "$(TEST_HOST)"; 456 | CODE_SIGN_STYLE = Automatic; 457 | CURRENT_PROJECT_VERSION = 1; 458 | DEVELOPMENT_TEAM = 8B27K52UU7; 459 | GENERATE_INFOPLIST_FILE = YES; 460 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 461 | MARKETING_VERSION = 1.0; 462 | PRODUCT_BUNDLE_IDENTIFIER = "com.dy-kim.GitHubSearchTests"; 463 | PRODUCT_NAME = "$(TARGET_NAME)"; 464 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; 465 | SUPPORTS_MACCATALYST = NO; 466 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 467 | SWIFT_EMIT_LOC_STRINGS = NO; 468 | SWIFT_VERSION = 5.0; 469 | TARGETED_DEVICE_FAMILY = 1; 470 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GitHubSearch-final.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/GitHubSearch-final"; 471 | }; 472 | name = Debug; 473 | }; 474 | ECC8144D29334AE00038A09F /* Release */ = { 475 | isa = XCBuildConfiguration; 476 | buildSettings = { 477 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 478 | BUNDLE_LOADER = "$(TEST_HOST)"; 479 | CODE_SIGN_STYLE = Automatic; 480 | CURRENT_PROJECT_VERSION = 1; 481 | DEVELOPMENT_TEAM = 8B27K52UU7; 482 | GENERATE_INFOPLIST_FILE = YES; 483 | IPHONEOS_DEPLOYMENT_TARGET = 16.0; 484 | MARKETING_VERSION = 1.0; 485 | PRODUCT_BUNDLE_IDENTIFIER = "com.dy-kim.GitHubSearchTests"; 486 | PRODUCT_NAME = "$(TARGET_NAME)"; 487 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; 488 | SUPPORTS_MACCATALYST = NO; 489 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 490 | SWIFT_EMIT_LOC_STRINGS = NO; 491 | SWIFT_VERSION = 5.0; 492 | TARGETED_DEVICE_FAMILY = 1; 493 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GitHubSearch-final.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/GitHubSearch-final"; 494 | }; 495 | name = Release; 496 | }; 497 | /* End XCBuildConfiguration section */ 498 | 499 | /* Begin XCConfigurationList section */ 500 | ECC8141F29334ADF0038A09F /* Build configuration list for PBXProject "GitHubSearch-final" */ = { 501 | isa = XCConfigurationList; 502 | buildConfigurations = ( 503 | ECC8144629334AE00038A09F /* Debug */, 504 | ECC8144729334AE00038A09F /* Release */, 505 | ); 506 | defaultConfigurationIsVisible = 0; 507 | defaultConfigurationName = Release; 508 | }; 509 | ECC8144829334AE00038A09F /* Build configuration list for PBXNativeTarget "GitHubSearch-final" */ = { 510 | isa = XCConfigurationList; 511 | buildConfigurations = ( 512 | ECC8144929334AE00038A09F /* Debug */, 513 | ECC8144A29334AE00038A09F /* Release */, 514 | ); 515 | defaultConfigurationIsVisible = 0; 516 | defaultConfigurationName = Release; 517 | }; 518 | ECC8144B29334AE00038A09F /* Build configuration list for PBXNativeTarget "GitHubSearch-finalTests" */ = { 519 | isa = XCConfigurationList; 520 | buildConfigurations = ( 521 | ECC8144C29334AE00038A09F /* Debug */, 522 | ECC8144D29334AE00038A09F /* Release */, 523 | ); 524 | defaultConfigurationIsVisible = 0; 525 | defaultConfigurationName = Release; 526 | }; 527 | /* End XCConfigurationList section */ 528 | 529 | /* Begin XCRemoteSwiftPackageReference section */ 530 | ECC8145229334C590038A09F /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = { 531 | isa = XCRemoteSwiftPackageReference; 532 | repositoryURL = "https://github.com/pointfreeco/swift-composable-architecture"; 533 | requirement = { 534 | kind = exactVersion; 535 | version = 0.52.0; 536 | }; 537 | }; 538 | /* End XCRemoteSwiftPackageReference section */ 539 | 540 | /* Begin XCSwiftPackageProductDependency section */ 541 | ECC8145329334C590038A09F /* ComposableArchitecture */ = { 542 | isa = XCSwiftPackageProductDependency; 543 | package = ECC8145229334C590038A09F /* XCRemoteSwiftPackageReference "swift-composable-architecture" */; 544 | productName = ComposableArchitecture; 545 | }; 546 | ECC8145529334C590038A09F /* Dependencies */ = { 547 | isa = XCSwiftPackageProductDependency; 548 | package = ECC8145229334C590038A09F /* XCRemoteSwiftPackageReference "swift-composable-architecture" */; 549 | productName = Dependencies; 550 | }; 551 | /* End XCSwiftPackageProductDependency section */ 552 | }; 553 | rootObject = ECC8141C29334ADF0038A09F /* Project object */; 554 | } 555 | --------------------------------------------------------------------------------