Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions Example/Pigeon/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

21 changes: 13 additions & 8 deletions Example/Pigeon/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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>())
}
}
)

Expand Down
4 changes: 2 additions & 2 deletions Example/Pigeon/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ class ViewController: UIHostingController<ContentView> {
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")
}

}
3 changes: 1 addition & 2 deletions Example/Tests/Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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.
}
}

}
2 changes: 1 addition & 1 deletion Pigeon/Classes/Cache/QueryCacheType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
27 changes: 16 additions & 11 deletions Pigeon/Classes/PaginatedQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import Foundation
import Combine

public final class PaginatedQuery<Request, PageIdentifier: PaginatedQueryKey, Response: Codable & Sequence>: ObservableObject, QueryType, QueryInvalidationListener {
public final class PaginatedQuery< Request,
PageIdentifier: PaginatedQueryKey,
Response: Codable & Sequence>: ObservableObject, QueryType, QueryInvalidationListener {

public enum FetchingBehavior {
case startWhenRequested
Expand All @@ -18,21 +20,17 @@ public final class PaginatedQuery<Request, PageIdentifier: PaginatedQueryKey, Re
public typealias State = QueryState<Response>
public typealias QueryFetcher = (Request, PageIdentifier) -> AnyPublisher<Response, Error>

@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<Response, Never> {
$internalState
.map { $0.value }
.filter({ $0 != nil })
.map { $0! }
.compactMap { $0.value }
.eraseToAnyPublisher()
}
public var valuePublisher: AnyPublisher<Response, Never> {
statePublisher
.map { $0.value }
.filter({ $0 != nil })
.map { $0! }
.compactMap { $0.value }
.eraseToAnyPublisher()
}
public var state: QueryState<Response> {
Expand All @@ -44,7 +42,11 @@ public final class PaginatedQuery<Request, PageIdentifier: PaginatedQueryKey, Re
case let .failed(error):
return .failed(error)
case .succeed:
return .succeed(items as! Response)
if let items = items as? Response {
return .succeed(items)
} else {
return .failed(ItemError.castFail)
}
}
}
public var statePublisher: AnyPublisher<QueryState<Response>, Never> {
Expand Down Expand Up @@ -112,7 +114,6 @@ public final class PaginatedQuery<Request, PageIdentifier: PaginatedQueryKey, Re
internalState = .succeed(cachedResponse)
}
}
break
case let .startImmediately(request):
refetchPage(request: request, page: currentPage)
}
Expand Down Expand Up @@ -203,3 +204,7 @@ public final class PaginatedQuery<Request, PageIdentifier: PaginatedQueryKey, Re
.store(in: &cancellables)
}
}

enum ItemError: Error {
case castFail
}
7 changes: 2 additions & 5 deletions Pigeon/Classes/Query.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,13 @@ public final class Query<Request, Response: Codable>: ObservableObject, QueryTyp
public typealias State = QueryState<Response>
public typealias QueryFetcher = (Request) -> AnyPublisher<Response, Error>

@Published private(set) public var state = State.idle
@Published public private(set) var state = State.idle
public var statePublisher: AnyPublisher<QueryState<Response>, Never> {
return $state.eraseToAnyPublisher()
}
public var valuePublisher: AnyPublisher<Response, Never> {
$state
.map { $0.value }
.filter({ $0 != nil })
.map { $0! }
.compactMap { $0.value }
.eraseToAnyPublisher()
}
private let key: QueryKey
Expand Down Expand Up @@ -102,7 +100,6 @@ public final class Query<Request, Response: Codable>: ObservableObject, QueryTyp
state = .succeed(cachedResponse)
}
}
break
case let .startImmediately(request):
refetch(request: request)
}
Expand Down
5 changes: 1 addition & 4 deletions Pigeon/Classes/QueryConsumer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import Combine

extension Query {
public final class Consumer: ObservableObject, QueryType {
public typealias State = QueryState<Response>
private let key: QueryKey
private let query: AnyQuery<Request, Response>
public var state: State { query.state }
Expand All @@ -20,9 +19,7 @@ extension Query {
}
public var valuePublisher: AnyPublisher<Response, Never> {
query.statePublisher
.map { $0.value }
.filter({ $0 != nil })
.map { $0! }
.compactMap { $0.value }
.eraseToAnyPublisher()
}
private var cancellables = Set<AnyCancellable>()
Expand Down
2 changes: 1 addition & 1 deletion Pigeon/Classes/Utils/QueryCacheConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
7 changes: 3 additions & 4 deletions Pigeon/Classes/Utils/QueryInvalidationListener.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ public extension QueryInvalidationListener {
func listenQueryInvalidation(for key: QueryKey) -> AnyPublisher<QueryInvalidator.TypedParameters<Request>, 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()
}
}
12 changes: 11 additions & 1 deletion Pigeon/Classes/Utils/QueryRegistry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import Foundation
import Combine

final class QueryRegistry {
private var queries: [QueryKey: Any] = [:]
Expand All @@ -25,6 +26,15 @@ final class QueryRegistry {
}

func resolve<Request, Response>(for key: QueryKey) -> AnyQuery<Request, Response> {
return queries[key] as! AnyQuery<Request, Response>
//let queries: AnyQuery<Request, Response>
if let queries = queries[key] as? AnyQuery<Request, Response> {
return queries
}
//todo fix stateGetter context
return AnyQuery<Request, Response>(stateGetter: { QueryState.loading },
statePublisherGetter: {
AnyPublisher<QueryState<Response>, Never>(
Empty<QueryState<Response>, Never>())
})
}
}