SwiftUI IOS 15 미만에서 ScrollView에 RefreshControll 이 지원이 안되는 어이없는 ㅋㅋㅋ

 

IOS 13~14 까지는 UIViewRepresentable 이용해서 구현해야되다능....

 

 

import SwiftUI

struct RefreshableScrollView<Content: View>: UIViewRepresentable {
    var content: Content
    var onRefresh: (UIRefreshControl) -> ()
    var scrollViewDidScroll: ((UIScrollView) -> ())?
    var scrollViewWillBeginDragging: ((UIScrollView) -> ())?
    var scrollViewDidEndDragging: ((UIScrollView, _ willDecelerate: Bool) -> ())?
    var refreshControl = UIRefreshControl()

    init(@ViewBuilder content: @escaping () -> Content,
         onRefresh: @escaping (UIRefreshControl) -> ()) {
        self.content = content()
        self.onRefresh = onRefresh
    }
    
    init(@ViewBuilder content: @escaping () -> Content,
         onRefresh: @escaping (UIRefreshControl) -> (),
         scrollViewWillBeginDragging: ((UIScrollView) -> ())?,
         scrollViewDidScroll: ((UIScrollView) -> ())?,
         scrollViewDidEndDragging: ((UIScrollView, _ willDecelerate: Bool) -> ())?) {
        self.content = content()
        self.onRefresh = onRefresh
        
        self.scrollViewWillBeginDragging = scrollViewWillBeginDragging
        self.scrollViewDidScroll = scrollViewDidScroll
        self.scrollViewDidEndDragging = scrollViewDidEndDragging
    }

    func makeCoordinator() -> Coordinator {
        return Coordinator(parent: self)
    }

    func makeUIView(context: Context) -> UIScrollView {
        let uiScrollView = UIScrollView()

        refreshControl.attributedTitle = NSAttributedString(string: "더 보기")
        refreshControl.tintColor = .black
        refreshControl.addTarget(context.coordinator, action: #selector(context.coordinator.onRefresh), for: .valueChanged)
    
        setUpView(uiScrollView: uiScrollView)
        
        uiScrollView.refreshControl = refreshControl
        uiScrollView.delegate = context.coordinator

        return uiScrollView
    }

    func updateUIView(_ uiView: UIViewType, context: Context) {
        setUpView(uiScrollView: uiView)
    }

    func setUpView(uiScrollView: UIScrollView) {
        let hostingView = UIHostingController(rootView: content.frame(maxHeight: .infinity, alignment: .top))
        
        hostingView.view.translatesAutoresizingMaskIntoConstraints = false
        let constraints = [
            hostingView.view.topAnchor.constraint(equalTo: uiScrollView.topAnchor),
            hostingView.view.bottomAnchor.constraint(equalTo: uiScrollView.bottomAnchor),
            hostingView.view.leadingAnchor.constraint(equalTo: uiScrollView.leadingAnchor),
            hostingView.view.trailingAnchor.constraint(equalTo: uiScrollView.trailingAnchor),
            hostingView.view.widthAnchor.constraint(equalTo: uiScrollView.widthAnchor),
            hostingView.view.heightAnchor.constraint(greaterThanOrEqualTo: uiScrollView.heightAnchor, constant: 1),
        ]
        uiScrollView.isScrollEnabled = true
        uiScrollView.subviews.last?.removeFromSuperview()
        uiScrollView.addSubview(hostingView.view)
        uiScrollView.addConstraints(constraints)
    }
    
    class Coordinator: NSObject, UIScrollViewDelegate {
        var parent: RefreshableScrollView

        init(parent: RefreshableScrollView) {
            self.parent = parent
        }

        @objc func onRefresh() {
            parent.onRefresh(parent.refreshControl)
        }
        
        // MARK: - UIScrollViewDelegate
        func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
            if parent.scrollViewWillBeginDragging == nil { return }
            parent.scrollViewWillBeginDragging!(scrollView)
        }
        
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            if parent.scrollViewDidScroll == nil { return }
            parent.scrollViewDidScroll!(scrollView)
        }
        
        func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
            if parent.scrollViewDidEndDragging == nil { return }
            parent.scrollViewDidEndDragging!(scrollView, decelerate)
        }
        
        
    }
}

 

 

사용방법 

RefreshableScrollView(content: {
	// 컨텐츠 
    
    
}, onRefresh: { control in
    // 새로고침 
    
    // 스크롤 컨트롤 종료
    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
        control.endRefreshing()
    }
}, scrollViewWillBeginDragging: { scrollView in
	// 스크롤 드래그 시작 
}, scrollViewDidScroll: { scrollView in
	// 스크롤 드래그 끝남
}, scrollViewDidEndDragging: nil)

+ Recent posts