diff --git a/Example/Pigeon/AppDelegate.swift b/Example/Pigeon/AppDelegate.swift index 03a40b1..4f4d1b4 100644 --- a/Example/Pigeon/AppDelegate.swift +++ b/Example/Pigeon/AppDelegate.swift @@ -14,14 +14,15 @@ import Pigeon class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + + func application(_ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let controller = ViewController() window = UIWindow(frame: UIScreen.main.bounds) - window!.rootViewController = controller - window!.makeKeyAndVisible() - + if let window = window { + window.rootViewController = controller + window.makeKeyAndVisible() + } return true } } - diff --git a/Example/Pigeon/ContentView.swift b/Example/Pigeon/ContentView.swift index 38e2823..8ee5b1f 100644 --- a/Example/Pigeon/ContentView.swift +++ b/Example/Pigeon/ContentView.swift @@ -19,7 +19,7 @@ struct ContentView: View { invalidationPolicy: .expiresAfter(1000), usagePolicy: .useInsteadOfFetching ), - fetcher: { request, page in + fetcher: { _, page in print("Fetching page no. \(page)") return GetCardsRequest() .execute() @@ -43,13 +43,18 @@ struct UsersList: View { }, behavior: .startImmediately(1), cache: UserDefaultsQueryCache.shared, - fetcher: { id in - URLSession.shared - .dataTaskPublisher(for: URL(string: "https://jsonplaceholder.typicode.com/users/")!) - .map(\.data) - .decode(type: [User].self, decoder: JSONDecoder()) - .receive(on: DispatchQueue.main) - .eraseToAnyPublisher() + fetcher: { _ in + let url = URL(string: "https://jsonplaceholder.typicode.com/users/") + if let url = url { + return URLSession.shared + .dataTaskPublisher(for: url) + .map(\.data) + .decode(type: [User].self, decoder: JSONDecoder()) + .receive(on: DispatchQueue.main) + .eraseToAnyPublisher() + } else { + return AnyPublisher<[User], Error>(Empty<[User], Error>()) + } } ) diff --git a/Example/Pigeon/ViewController.swift b/Example/Pigeon/ViewController.swift index 316260e..283ceb2 100644 --- a/Example/Pigeon/ViewController.swift +++ b/Example/Pigeon/ViewController.swift @@ -18,8 +18,8 @@ class ViewController: UIHostingController { super.init(rootView: ContentView()) } - @objc required dynamic init?(coder aDecoder: NSCoder) { + @objc + dynamic required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - } diff --git a/Example/Tests/Tests.swift b/Example/Tests/Tests.swift index 6e740e4..840e3c1 100644 --- a/Example/Tests/Tests.swift +++ b/Example/Tests/Tests.swift @@ -20,9 +20,8 @@ class Tests: XCTestCase { func testPerformanceExample() { // This is an example of a performance test case. - self.measure() { + self.measure { // Put the code you want to measure the time of here. } } - } diff --git a/Pigeon/Classes/Cache/QueryCacheType.swift b/Pigeon/Classes/Cache/QueryCacheType.swift index fa517fc..6241f9f 100644 --- a/Pigeon/Classes/Cache/QueryCacheType.swift +++ b/Pigeon/Classes/Cache/QueryCacheType.swift @@ -26,7 +26,7 @@ public struct QueryCache { self.wrappedCache = wrappedCache } - private(set) public static var global: QueryCacheType = inMemory.wrappedCache + public private(set) static var global: QueryCacheType = inMemory.wrappedCache public static func setGlobal(_ wrapper: QueryCache) { QueryCache.global = wrapper.wrappedCache } diff --git a/Pigeon/Classes/PaginatedQuery.swift b/Pigeon/Classes/PaginatedQuery.swift index ed4f04c..30c6228 100644 --- a/Pigeon/Classes/PaginatedQuery.swift +++ b/Pigeon/Classes/PaginatedQuery.swift @@ -9,7 +9,9 @@ import Foundation import Combine -public final class PaginatedQuery: ObservableObject, QueryType, QueryInvalidationListener { +public final class PaginatedQuery< Request, + PageIdentifier: PaginatedQueryKey, + Response: Codable & Sequence>: ObservableObject, QueryType, QueryInvalidationListener { public enum FetchingBehavior { case startWhenRequested @@ -18,21 +20,17 @@ public final class PaginatedQuery public typealias QueryFetcher = (Request, PageIdentifier) -> AnyPublisher - @Published private(set) public var items: [Response.Element] = [] + @Published public private(set) var items: [Response.Element] = [] @Published private var internalState = State.idle - @Published private(set) public var currentPage: PageIdentifier + @Published public private(set) var currentPage: PageIdentifier private var internalValuePublisher: AnyPublisher { $internalState - .map { $0.value } - .filter({ $0 != nil }) - .map { $0! } + .compactMap { $0.value } .eraseToAnyPublisher() } public var valuePublisher: AnyPublisher { statePublisher - .map { $0.value } - .filter({ $0 != nil }) - .map { $0! } + .compactMap { $0.value } .eraseToAnyPublisher() } public var state: QueryState { @@ -44,7 +42,11 @@ public final class PaginatedQuery, Never> { @@ -112,7 +114,6 @@ public final class PaginatedQuery: ObservableObject, QueryTyp public typealias State = QueryState public typealias QueryFetcher = (Request) -> AnyPublisher - @Published private(set) public var state = State.idle + @Published public private(set) var state = State.idle public var statePublisher: AnyPublisher, Never> { return $state.eraseToAnyPublisher() } public var valuePublisher: AnyPublisher { $state - .map { $0.value } - .filter({ $0 != nil }) - .map { $0! } + .compactMap { $0.value } .eraseToAnyPublisher() } private let key: QueryKey @@ -102,7 +100,6 @@ public final class Query: ObservableObject, QueryTyp state = .succeed(cachedResponse) } } - break case let .startImmediately(request): refetch(request: request) } diff --git a/Pigeon/Classes/QueryConsumer.swift b/Pigeon/Classes/QueryConsumer.swift index 4130b4c..0339731 100644 --- a/Pigeon/Classes/QueryConsumer.swift +++ b/Pigeon/Classes/QueryConsumer.swift @@ -11,7 +11,6 @@ import Combine extension Query { public final class Consumer: ObservableObject, QueryType { - public typealias State = QueryState private let key: QueryKey private let query: AnyQuery public var state: State { query.state } @@ -20,9 +19,7 @@ extension Query { } public var valuePublisher: AnyPublisher { query.statePublisher - .map { $0.value } - .filter({ $0 != nil }) - .map { $0! } + .compactMap { $0.value } .eraseToAnyPublisher() } private var cancellables = Set() diff --git a/Pigeon/Classes/Utils/QueryCacheConfig.swift b/Pigeon/Classes/Utils/QueryCacheConfig.swift index ecccd08..4d28d2f 100644 --- a/Pigeon/Classes/Utils/QueryCacheConfig.swift +++ b/Pigeon/Classes/Utils/QueryCacheConfig.swift @@ -29,7 +29,7 @@ public struct QueryCacheConfig { self.usagePolicy = usagePolicy } - private(set) public static var global: QueryCacheConfig = .init() + public private(set) static var global: QueryCacheConfig = .init() public static func setGlobal(_ config: QueryCacheConfig) { QueryCacheConfig.global = config } diff --git a/Pigeon/Classes/Utils/QueryInvalidationListener.swift b/Pigeon/Classes/Utils/QueryInvalidationListener.swift index 1c6cba9..cda367c 100644 --- a/Pigeon/Classes/Utils/QueryInvalidationListener.swift +++ b/Pigeon/Classes/Utils/QueryInvalidationListener.swift @@ -17,10 +17,9 @@ public extension QueryInvalidationListener { func listenQueryInvalidation(for key: QueryKey) -> AnyPublisher, Never> { NotificationCenter.default.publisher(for: key.invalidationNotificationName) .map(\.object) - .map { ($0 as? QueryInvalidator.Parameters)? - .toTypedParameters(of: Request.self) } - .filter({ $0 != nil }) - .map { $0! } + .compactMap { ($0 as? QueryInvalidator.Parameters)? + .toTypedParameters(of: Request.self) + } .eraseToAnyPublisher() } } diff --git a/Pigeon/Classes/Utils/QueryRegistry.swift b/Pigeon/Classes/Utils/QueryRegistry.swift index 9bcabe9..8a9a267 100644 --- a/Pigeon/Classes/Utils/QueryRegistry.swift +++ b/Pigeon/Classes/Utils/QueryRegistry.swift @@ -6,6 +6,7 @@ // import Foundation +import Combine final class QueryRegistry { private var queries: [QueryKey: Any] = [:] @@ -25,6 +26,15 @@ final class QueryRegistry { } func resolve(for key: QueryKey) -> AnyQuery { - return queries[key] as! AnyQuery + //let queries: AnyQuery + if let queries = queries[key] as? AnyQuery { + return queries + } + //todo fix stateGetter context + return AnyQuery(stateGetter: { QueryState.loading }, + statePublisherGetter: { + AnyPublisher, Never>( + Empty, Never>()) + }) } }