Sunday, November 8, 2026
HomeiOS Developmentios - UIRefreshControl clean house at high of UIScrollView as UIViewRepresentable in...

ios – UIRefreshControl clean house at high of UIScrollView as UIViewRepresentable in SwiftUI

[ad_1]

I’m utilizing UIKit’s RefreshControl in my SwiftUI venture however it creates a clean house on the very high of the the UIScrollView between the navigation bar and the content material.

This was not an issue once I was utilizing a traditional SwiftUI ScrollView however was launched when utilizing UIKIt’s RefreshControl.

The pull to refresh works…

I could make it go away by including the next to the RefreshableScrollView…

.navigationBartitle("Title") 
.navigationBarTitleDisplayMode(.inline)

however then the pull to refresh does not present or work in any respect, it acts like a traditional ScrollView…?

How can I make this bizarre spacing go away??

I used to be fascinated by programmatically altering the UIScrollView’s place on initialization as a result of if I scroll up the house goes away however it looks as if a foul implementation…

enter image description here

enter image description here

SWIFTUI VIEW

struct NewsFeed2: View {
    @EnvironmentObject var session : SessionStore
    @StateObject var newsfeedVM = NewsFeedViewModel()

    @State personal var showInbox: Bool = false
    @State personal var presentLiveView: Bool = false
   

    var physique: some View {
        NavigationView {
           RefreshableScrollView (
                content material: {
                    VStack {
                         ForEach(newsfeedVM.posts, id: .id) { submit in
                             PostCell(submit: submit)
                                 .body(maxHeight: .infinity, alignment: .high)   
                        }
                    }
                },
                onRefresh: { management in
                    management.endRefreshing() 
                    newsfeedVM.loadNewsFeed()
                })
            .toolbar(content material: {
                ToolbarItem(placement: .navigationBarLeading) {
                    ZStack {
                        Button(motion: {}, label: { })
                        DiscoverButtton().opacity(0.0)
                    }.padding(.main, 10)
                }
                ToolbarItem(placement: .principal) {
                    TrendingButton()
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    HStack(spacing: 22) {
                        GoLiveButton(presentLiveView: $presentLiveView).opacity(0.0)
                        InboxViewButton(showInbox: $showInbox).opacity(0.0)
                    }.padding(.trailing, 10)
                }
            })
        }
    }
}

UI VIEW REPRESENTABLE

struct RefreshableScrollView<Content material: View>: UIViewRepresentable {
    
    var content material: Content material
    var onRefresh: (UIRefreshControl) -> ()
    var refreshControl = UIRefreshControl()
    
    init(@ViewBuilder content material: @escaping () -> Content material, onRefresh: @escaping (UIRefreshControl) -> () ) {
        self.content material = content material()
        self.onRefresh = onRefresh
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(guardian: self)
    }
    
    func makeUIView(context: Context) -> UIScrollView {
        let uiScrollView = UIScrollView()
        refreshControl.tintColor = .crimson
        refreshControl.addTarget(context.coordinator, motion: #selector(context.coordinator.onRefresh), for: .valueChanged)
        refreshControl.attributedTitle = NSAttributedString(string: "Refreshing")
        setupView(uiScrollView: uiScrollView)
        
        uiScrollView.refreshControl = refreshControl 
        
        return uiScrollView
    }
    
    func updateUIView(_ uiView: UIScrollView, context: Context) {
        setupView(uiScrollView: uiView)
    }
    
    func setupView(uiScrollView: UIScrollView) {
        let hostView = UIHostingController(rootView: content material.body(peak: .infinity, alignment: .high))
        hostView.view.translatesAutoresizingMaskIntoConstraints = false
        
        let constraints = [
            // four corners
            hostView.view.topAnchor.constraint(equalTo: uiScrollView.topAnchor),
            hostView.view.bottomAnchor.constraint(equalTo: uiScrollView.bottomAnchor),
            hostView.view.leadingAnchor.constraint(equalTo: uiScrollView.leadingAnchor),
            hostView.view.trailingAnchor.constraint(equalTo: uiScrollView.trailingAnchor),
            hostView.view.widthAnchor.constraint(equalTo: uiScrollView.widthAnchor),
            hostView.view.heightAnchor.constraint(greaterThanOrEqualTo: uiScrollView.heightAnchor, constant: 1)
        ]
        // eradicating beforehand added view
        uiScrollView.subviews.final?.removeFromSuperview()
        uiScrollView.addSubview(hostView.view)
        uiScrollView.addConstraints(constraints)
      
    }
    
    class Coordinator: NSObject {
        var guardian: RefreshableScrollView
        init(guardian: RefreshableScrollView) {
            self.guardian = guardian
        }
        
        @objc func onRefresh() {
            guardian.onRefresh(guardian.refreshControl) 
        }
    }
    
}

[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments