0

This problem has troubled me for three days So I'm hoping to ask for some help Thank you so much

screenWidth & screenHeight

The value is correct and updated, but I don't understand why the UIViewController's view and the contained UIButton or PlayerLayer frame are not updated

enter image description here

enter image description here

struct PlayVideo: View {

    @State var screenCommnit : Bool = false 
    @State private var screenWidth: CGFloat = UIScreen.main.bounds.width UIScreen.main.scale
    @State private var screenHeight: CGFloat = 260   
              
 var body: some View {
 
        VStack{
            
            PlayerView(url: $url,screenCommnit:$screenCommnit,screenWidth:$screenWidth,screenHeight:$screenHeight).fixedSize()
         
            Spacer()
            
        } .onChange(of: screenCommnit) { newValue in 

          //Set landscape and portrait switch and set screenWidth and screenHeight
    }
}


struct PlayerView : UIViewControllerRepresentable {

   
    @Binding var screenCommnit : Bool 
    @Binding var screenWidth : CGFloat
    @Binding var screenHeight : CGFloat
    let controller = MyViewController()
    
    
    func makeUIViewController(context: Context) -> MyViewController {

        print("makeUIViewController")
        return controller
    }
    

    func updateUIViewController(_ uiViewController: MyViewController, context: Context) {

        print("updateUIViewController")
        controller.screenCommnit = screenCommnit
        controller.screenWidth = screenWidth
        controller.screenHeight = screenHeight
        controller.delegate = context.coordinator
      
        let size = controller.view.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
        controller.preferredContentSize = size
     
        
    }
    
    func makeCoordinator() -> PlayerView.Coordinator {
        
        Coordinator(url:$url, screenCommnit:$screenCommnit,screenWidth:$screenWidth,screenHeight:$screenHeight)
       
    }
}

class MyViewController: UIViewController {
    
    
    var url: String = ""
    var screenCommnit : Bool = false
    var screenWidth: CGFloat = UIScreen.main.bounds.width 
    var screenHeight: CGFloat = 260

    var fullScreenBtn = UIButton()
    var uiView = UIView()
    var delegate : PlayerViewDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()
        print("viewDidLoad...")
        self.view.backgroundColor = .white
        self.view.frame = CGRect(x: 0, y: 0, width:self.screenWidth, height: self.screenHeight)
        self.PlayerLayer()
        self.ScreenButton()
      
    }
    


  
    func ScreenButton(){
        print("ScreenButton...")
        fullScreenBtn.frame = CGRect.init(x: -20, y: 30, width: 200, height: 30)
        fullScreenBtn.setTitle("全屏", for: .normal)
        fullScreenBtn.setImage(UIImage(systemName: "arrow.up.and.down.circle"), for:.normal)
        fullScreenBtn.tag = 1
        fullScreenBtn.addTarget(self,action:#selector(btnClick), for: .touchUpInside)
        self.view.insertSubview(fullScreenBtn, at:1)
    }

   
    func PlayerLayer(){
        print("PlayerLayer...")
        let playerLayer = AVPlayerLayer(player: AVPlayer(url: URL(string:  "https://media.w3.org/2010/05/sintel/trailer.mp4")!))
        print("PlayerLayer() : \(self.view.frame.width) \(self.view.frame.height)")
        playerLayer.frame = CGRect.init(x: 0, y: 9, width: screenWidth, height: screenHeight)
        playerLayer.frame.size.height = playerLayer.frame.size.height * 0.92
        playerLayer.videoGravity = .resizeAspect
        playerLayer.backgroundColor = UIColor.black.cgColor
        playerLayer.player?.play()
        self.view.layer.insertSublayer(playerLayer, at: 0)
   
    }
    
   
   @objc func btnClick(btn: UIButton) {
  
       screenCommnit = !screenCommnit
       delegate?.OneGroupDidFinished(self) 
   }

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }

}
vimuth
  • 5,064
  • 33
  • 79
  • 116
  • Your `var screenCommnit : Bool = false` is completely disconnected from your other `Binding`s. Perhaps you meant to have a `Binding` there as well? – jnpdx Apr 23 '23 at 03:51

1 Answers1

0

makeUIViewController needs to init the controller, e.g.

func makeUIViewController(context: Context) -> MyViewController {
    let vc = MyViewController()
    vc.delegate = context.coordinator
    return vc
}

And you should not hang onto it in the struct because it will be lost when this struct is re-init. SwiftUI holds onto it for you and passes it in to updateUIViewController.

FYI since you have a UIViewController subclass you don't really need a coordinator object.

Also, since you only toggle screenCommit and don't read it you could replace it with a closure, e.g.

struct PlayerView : UIViewControllerRepresentable {
    let screenCommit: () -> Void

Use like:

PlayerView(...) {
    //on commit
}
malhal
  • 26,330
  • 7
  • 115
  • 133