代码之家  ›  专栏  ›  技术社区  ›  Aleksi Sjöberg

设置Scroll View的zoomScale和点击后退按钮会导致程序崩溃

  •  0
  • Aleksi Sjöberg  · 技术社区  · 9 年前

    我试着制作一个程序,你点击一个图像,它会在全屏上显示,缩放以使周围没有空白(CS 193P任务4任务7,任何知道它的人都可以)。视图控制器嵌入在导航控制器中。结果是程序崩溃了 EXC_BAD_ACCESS (code = EXC_I386_GPFLT) 当我按下导航栏上的后退按钮时。

    我发现我可以通过滚动到图像顶部然后返回来防止这种崩溃。另一种完全防止这种情况的方法是注释掉设置scrollView的zoomScale的行。下面是我用于加载和处理图像的代码:

    import UIKit
    
    class ImageViewController: UIViewController, UIScrollViewDelegate {
    
        @IBOutlet weak var scrollView: UIScrollView! {
            didSet {
                scrollView.contentSize = imageView.frame.size
                scrollView.delegate = self
                scrollView.minimumZoomScale = 0.03
                scrollView.maximumZoomScale = 5.0
            }
        }
    
        func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
            return imageView
        }
    
        var imageURL: NSURL? {
            didSet {
                image = nil
                if view.window != nil {
                    fetchImage()
                }
            }
        }
    
        private func fetchImage() {
            if let url = imageURL {
                let qos = Int(QOS_CLASS_USER_INITIATED.value)
                dispatch_async(dispatch_get_global_queue(qos, 0)) {
                    let imageData = NSData(contentsOfURL: url)
                    dispatch_async(dispatch_get_main_queue()) {
                        if url == self.imageURL {
                            if imageData != nil {
                                self.image = UIImage(data: imageData!)
                            } else {
                                self.image = nil
                            }
                        }
                    }
                }
            }
        }
    
        private var imageView = UIImageView()
    
        private var image: UIImage? {
            get { return imageView.image }
            set {
                imageView.image = newValue
                imageView.sizeToFit()
                scrollView?.contentSize = imageView.frame.size
                scrollViewDidScrollOrZoom = false
                autoScale()
            }
        }
    
        private var scrollViewDidScrollOrZoom = false
    
        private func autoScale() {
            if scrollViewDidScrollOrZoom {
                return
            }
            if let sv = scrollView {
                if image != nil {
                    sv.zoomScale = max(sv.bounds.size.width / image!.size.width, sv.bounds.size.height / image!.size.height)
                    sv.contentOffset = CGPoint(x: (imageView.frame.size.width - sv.frame.size.width) / 2, y: (imageView.frame.size.height - sv.frame.size.height) / 2)
                    scrollViewDidScrollOrZoom = false
                }
            }
        }
    
    
        func scrollViewDidEndZooming(scrollView: UIScrollView, withView view: UIView!, atScale scale: CGFloat) {
            scrollViewDidScrollOrZoom = true
        }
    
        func scrollViewDidScroll(scrollView: UIScrollView) {
            scrollViewDidScrollOrZoom = true
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            scrollView.addSubview(imageView)
        }
    
        override func viewWillAppear(animated: Bool) {
            super.viewWillAppear(animated)
            if image == nil {
                fetchImage()
            }
        }
    
        override func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
            autoScale()
        }
    }
    

    我试图制作一个简单的应用程序,它从一个只有一个按钮并嵌入在导航控制器中的视图控制器切换到ImageViewController,但崩溃仍然是一样的。下面是我在第一个视图控制器中使用的代码:

    class FirstViewController: UIViewController {
    
        let url = NSURL(string: "https://developer.apple.com/swift/images/swift-og.png")
    
        override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
            if segue.identifier == "Show Full Image" {
                let ivc = segue.destinationViewController as! ImageViewController
                ivc.imageURL = url
            }
        }
    }
    

    是什么原因导致的?我在这里做错了什么?我正在使用Xcode 6.3 beta 3。

    1 回复  |  直到 9 年前
        1
  •  0
  •   Aleksi Sjöberg    9 年前

    问题似乎实际上与scrollView的委托有关,因为我可以通过添加

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        scrollView.delegate = nil
    }