UIView框架每次加载ViewController时都会更改

问题描述

我在xib上有一个UIView,当我在viewDidLoad上检查它的框架时,它说:

  - some : <UIView: 0x7fcc3948b8a0; frame = (56.3333 122; 262.333 262.333); clipsToBounds = YES; autoresize = RM+BM; layer = <CALayer: 0x600003a62060>>

调用layoutIfNeeded()之后,紧接在上一条日志之后,它显示

  - some : <UIView: 0x7fcc3948b8a0; frame = (56.5 121.917; 262 262.5); clipsToBounds = YES; autoresize = RM+BM; layer = <CALayer: 0x600003a62060>>

viewDidLayoutSubviews()上,框架为:

  - some : <UIView: 0x7fcc3948b8a0; frame = (62 122; 290 289.5); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x600003477420>; layer = <CALayer: 0x600003a62060>>

为什么对我很重要?因为我在该视图内设置了UIScrollView,并且在UIImage内设置了具有缩放功能UIScrollView,这使图像正确的缩放框断裂。

我该如何解决

解决方法

这是一个非常简单的示例,可能会对您有所帮助。

我有一个1200 x 1200图像,网格线为100像素。绿色矩形位于600,200,像素为300 x 400。那将是我的目标“缩放到”矩形。

enter image description here

当然,我的滚动视图将没有确切的3:4比率,因此绿色矩形将在缩放时最终在滚动视图的中心。

此处为iPhone 11 Pro Max。我使用的是导航控制器,因此您会在顶部看到导航栏...视图背景为白色...滚动视图被限制在视图的安全区域,每侧各有8点:

enter image description here

以下是生成该代码的代码:

class ScrollTestViewController : UIViewController,UIScrollViewDelegate {
    
    let scrollView: UIScrollView = {
        let v = UIScrollView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = .cyan
        return v
    }()
    
    let zoomImageView: UIImageView = {
        let v = UIImageView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.contentMode = .scaleToFill
        return v
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        guard let img = UIImage(named: "img1200x1200") else {
            fatalError("Could not load image!!!")
        }
        print(img.size)
        zoomImageView.image = img
        
        view.backgroundColor = .white
        
        // add the scroll view
        self.view.addSubview(scrollView)
        
        // add contentView to scroll view
        scrollView.addSubview(zoomImageView)
        
        // respect safe-area
        let g = view.safeAreaLayoutGuide
        
        // we're going to constrain the zoomImageView to the scroll view's content layout guide
        let scg = scrollView.contentLayoutGuide
        
        NSLayoutConstraint.activate([
            
            // constrain scrollView Top / Leading / Trailing / Bottom to view (safe-area)
            //  with 8-pts on each side
            scrollView.topAnchor.constraint(equalTo: g.topAnchor,constant: 8.0),scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor,scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor,constant: -8.0),scrollView.bottomAnchor.constraint(equalTo: g.bottomAnchor,// constrain zoomImageView Top / Leading / Trailing / Bottom to scroll view's Content Layout Guide
            zoomImageView.topAnchor.constraint(equalTo: scg.topAnchor,constant: 0.0),zoomImageView.leadingAnchor.constraint(equalTo: scg.leadingAnchor,zoomImageView.trailingAnchor.constraint(equalTo: scg.trailingAnchor,zoomImageView.bottomAnchor.constraint(equalTo: scg.bottomAnchor,// constrain zoomImageView's width and height to the width and height of the image
            zoomImageView.widthAnchor.constraint(equalToConstant: img.size.width),zoomImageView.heightAnchor.constraint(equalToConstant: img.size.height),])
        
        scrollView.minimumZoomScale = 0.25
        scrollView.maximumZoomScale = 10.0

        scrollView.delegate = self

    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        // we need to set the "zoom to" rect *after* auto-layout
        //  has finished everything else
        let r = CGRect(x: 600,y: 200,width: 300,height: 400)
        scrollView.zoom(to: r,animated: false)
    }
    
    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return zoomImageView
    }
    
}