簡體   English   中英

通過 UIKit 視圖訪問 SwiftUI 視圖的值

[英]Accessing Value of SwiftUI View through a UIKit View

我在網上閱讀了這個問題,發現它非常有趣。 如果您有如下所示的 SwiftUI 視圖。 如何在更改 RatingView 中的一行的情況下訪問 UIKit 視圖中的選定評分。

struct RatingView: View {
    
    @Binding var rating: Int?
    
    private func starType(index: Int) -> String {
        
        if let rating = rating {
            return index <= rating ? "star.fill" : "star"
        } else {
            return "star"
        }
    }
    
    var body: some View {
        HStack {
            ForEach(1...5, id: \.self) { index in
                Image(systemName: self.starType(index: index))
                    .foregroundColor(Color.orange)
                    .onTapGesture {
                        rating = index
                }
            }
        }
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .white
        
        // .constant(3) will be replaced by something in the ViewController so it can handle the changes for the rating
        let hostingController = UIHostingController(rootView: RatingView(rating: .constant(3)))
        
        guard let ratingsView = hostingController.view else { return }
        self.addChild(hostingController)
        
        self.view.addSubview(ratingsView)
}

更新:

原文來源: https ://twitter.com/azamsharp/status/1540838477599752192?s=20&t=bbDp3VT9m0Ce4W3Sgr7Iyg

我從原始來源輸入了大部分代碼。 我沒有太大變化。

我們可以裝飾 RatingView 並使用 ObservableObject 來保持事實的來源。

class RatingObserver: ObservableObject {
    @Published var rating: Int?
}

struct WrappedRatingView: View {

    @ObservedObject var ratingObserver: RatingObserver

    var body: some View {
        RatingView(rating: $ratingObserver.rating)
    }
}

然后我們可以通過以下方式使用它。

class ViewController: UIViewController {

    let ratingObserver = RatingObserver()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .white

        let hostingController = UIHostingController(
            rootView: WrappedRatingView(ratingObserver: ratingObserver)
        )
        self.addChild(hostingController)
        view.addSubview(hostingController.view)
        hostingController.didMove(toParent: self)
        hostingController.view.translatesAutoresizingMaskIntoConstraints = false

        let button = UIButton()
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle("Reset Rating", for: .normal)
        button.setTitleColor(.blue, for: .normal)
        button.addTarget(self, action: #selector(resetRating), for: .touchUpInside)
        view.addSubview(button)

        NSLayoutConstraint.activate([
            hostingController.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            hostingController.view.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 100)
        ])
    }

    @objc func resetRating() {
        ratingObserver.rating = nil
    }
}

這允許更新 ViewController 和 SwiftUI 視圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM