Skip to content
Merged
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
32 changes: 5 additions & 27 deletions AsyncImageView/AsyncSwiftUIImageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,11 @@ Renderer.RenderResult == PlaceholderRenderer.RenderResult {
public var body: some View {
ZStack {
self.imageView

Color.clear
.modifier(SizeModifier())
.onPreferenceChange(ImageSizePreferenceKey.self) { imageSize in
self.size = imageSize
}
}
.onGeometryChange(for: CGSize.self) { geometry in
geometry.size
} action: { imageSize in
self.size = imageSize
}
.onAppear {
self.viewModel.start()
Expand Down Expand Up @@ -110,27 +109,6 @@ public extension AsyncSwiftUIImageView {
}
}

private struct ImageSizePreferenceKey: PreferenceKey {
typealias Value = CGSize

static var defaultValue: CGSize = .zero

static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
value = nextValue()
}
}

private struct SizeModifier: ViewModifier {
func body(content: Content) -> some View {
content.background(
GeometryReader { geometry in
Color.clear
.preference(key: ImageSizePreferenceKey.self, value: geometry.size)
}
)
}
}

@Observable
private final class AsyncSwiftUIImageViewModel<
Data: RenderDataType,
Expand Down
59 changes: 59 additions & 0 deletions AsyncImageViewTests/AsyncSwiftUIImageViewSpec.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import Quick
import Nimble
import SwiftUI
import UIKit

import ReactiveSwift

import AsyncImageView

class AsyncSwiftUIImageViewSpec: QuickSpec {
override class func spec() {
describe("AsyncSwiftUIImageView") {
it("requests the full proposed size") {
let renderer = SquareImageRenderer()
typealias ViewType = AsyncSwiftUIImageView<
TestRenderData,
TestData,
SquareImageRenderer,
SquareImageRenderer
>
let view = ViewType(
renderer: renderer,
placeholderRenderer: nil,
uiScheduler: ImmediateScheduler(),
imageCreationScheduler: ImmediateScheduler()
)
.data(.a)
.frame(width: 300, height: 100)
let viewController = UIHostingController(rootView: view)
let window = UIWindow(frame: CGRect(origin: .zero, size: CGSize(width: 300, height: 100)))
window.rootViewController = viewController
window.makeKeyAndVisible()
viewController.view.frame = window.bounds
viewController.view.layoutIfNeeded()

let expectedRequest = TestRenderData(data: .a, size: window.bounds.size)
expect(renderer.renderedImages.value).toEventually(equal([expectedRequest]))

RunLoop.current.run(until: Date(timeIntervalSinceNow: 0.1))
viewController.view.layoutIfNeeded()

expect(renderer.renderedImages.value) == [expectedRequest]
}
}
}
}

private final class SquareImageRenderer: RendererType {
let renderedImages = Atomic<[TestRenderData]>([])

func renderImageWithData(_ data: TestRenderData) -> SignalProducer<UIImage, Never> {
TestRenderer.rendererForSize(CGSize(width: 100, height: 100), scale: 1)
.asyncRenderer(ImmediateScheduler())
.renderImageWithData(data)
.on(started: {
self.renderedImages.modify { $0.append(data) }
})
}
}
Loading