diff --git a/AsyncImageView/AsyncSwiftUIImageView.swift b/AsyncImageView/AsyncSwiftUIImageView.swift index 4f17e2b..6d47202 100644 --- a/AsyncImageView/AsyncSwiftUIImageView.swift +++ b/AsyncImageView/AsyncSwiftUIImageView.swift @@ -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() @@ -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, diff --git a/AsyncImageViewTests/AsyncSwiftUIImageViewSpec.swift b/AsyncImageViewTests/AsyncSwiftUIImageViewSpec.swift new file mode 100644 index 0000000..bfbe47c --- /dev/null +++ b/AsyncImageViewTests/AsyncSwiftUIImageViewSpec.swift @@ -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 { + TestRenderer.rendererForSize(CGSize(width: 100, height: 100), scale: 1) + .asyncRenderer(ImmediateScheduler()) + .renderImageWithData(data) + .on(started: { + self.renderedImages.modify { $0.append(data) } + }) + } +}