设置 Scroll View 的 zoomScale 并点击返回按钮会使程序崩溃
Setting Scroll View's zoomScale and hitting back button crashes program
我正在尝试制作一个程序,您可以在其中单击图像,然后它会全屏显示它,并进行缩放以使其周围没有空白(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.
看来问题实际上出在 scrollView 的委托上,因为我可以通过添加
来解决这个问题
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
scrollView.delegate = nil
}
我正在尝试制作一个程序,您可以在其中单击图像,然后它会全屏显示它,并进行缩放以使其周围没有空白(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.
看来问题实际上出在 scrollView 的委托上,因为我可以通过添加
来解决这个问题override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
scrollView.delegate = nil
}