0

I have two ViewControllers, assume one is named MainVC and the other one is named GetCameraRollImageViewController. In the second one, there is a UIScrollView which holds a UIImageView, since I'm using segue to show the second view controller, I've to use its delegate in the MainVC:

class ViewController: UIViewController, GetTextDelegate, GetCameraRollImageDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate  {
//
//other codes
//
    @IBAction func setNewImageFromCameraRoll(segue:UIStoryboardSegue)    {
        if let newImageVC = segue.sourceViewController as? GetCameraRollImageViewController{

            var scale:CGFloat = 1.0/newImageVC.scrollView.zoomScale;
            var visibleRect:CGRect!
            visibleRect.origin.x = newImageVC.scrollView.contentOffset.x * scale;
            visibleRect.origin.y = newImageVC.scrollView.contentOffset.y * scale;
            visibleRect.size.width = newImageVC.scrollView.bounds.size.width * scale;
            visibleRect.size.height = newImageVC.scrollView.bounds.size.height * scale;
            var cr:CGImageRef = CGImageCreateWithImageInRect(newImageVC.inputImage.image?.CGImage,visibleRect)
            var cropped:UIImage = UIImage(CGImage: cr)!
            imageView.image = cropped
        }
    }
}

The GetCameraRollImageViewController code:

import UIKit

protocol GetCameraRollImageDelegate{
    //
}

class GetCameraRollImageViewController: UIViewController, UIScrollViewDelegate {

    var delegate:GetCameraRollImageDelegate? = nil
    var inputImageDelegate:UIImage!

    @IBOutlet var scrollView: UIScrollView!
    @IBOutlet var inputImage:UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.scrollView.minimumZoomScale = 0.5
        self.scrollView.maximumZoomScale = 6.0
        self.scrollView.contentSize = self.inputImage.frame.size;
        self.scrollView.delegate = self
        inputImage.image = inputImageDelegate
}
    func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
        return self.inputImage
    }

}

But when I trigger setNewImageFromCameraRoll() it crashes the app with this error:

fatal error: unexpectedly found nil while unwrapping an Optional value

Note: Bothe scrollView and inputImage are bounded, and I'm not reading them in the viewDidLoad(), when they are empty.

enter image description here

Maysam
  • 7,246
  • 13
  • 68
  • 106
  • possible duplicate of [fatal error: unexpectedly found nil while unwrapping an Optional value in Swift](http://stackoverflow.com/questions/26701993/fatal-error-unexpectedly-found-nil-while-unwrapping-an-optional-value-in-swift) – GoZoner May 30 '15 at 16:26
  • @GoZoner it' not duplicated, because 1) I'm not reading in `ViewDidLoad()` 2) i'm using `if ..let` – Maysam May 30 '15 at 16:32

4 Answers4

0

I'm not 100% but I believe your problem is that the scrollView has not yet been created. Try passing the image to the new view controller and doing your resizing in the viewDidLoad of GetCameraRollImageViewController.

0

Your code has a number of problems.

First of all, why do you have an IBAction that takes a segue as a parameter?

Usually what you do is invoke a segue through whatever method, and then implement the preformSegue method. That method gets called whenever a segue is triggered in your view controller.

In performSegue you can get a pointer to the destination view controller and pass parameters to it.

It isn't clear to me how your setNewImageFromCameraRoll method is being called, or how it gets a segue object. It also doesn't make sense to me that you're using the source view controller from the segue. I suspect the method doesn't work as you expected.

The next problem has to do with what you're trying to do with the view controller you get from the segue. You're trying to manipulate it's views directly. Don't do that. You should treat a view controller's views as private. Instead you should add properties to your view controller that expose the information you need, and reference those properties.

Messing around with another view controller's views violates the principle of encapsulation. It also frequently fails because the other view controller's views don't get created until it's displayed on-screen.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Thanks for your reply. It's your first question [answer](http://stackoverflow.com/questions/12561735/what-are-unwind-segues-for-and-how-do-you-use-them). And for the second question, I don't manipulate that view directly, i'm just reading some values. – Maysam May 30 '15 at 17:29
  • Oh, an unwind segue! Ok, that explains it. I haven't used them much. – Duncan C May 30 '15 at 19:31
  • Reading values is just as bad as writing values, and also likely to fail. You should treat another view controller's views as private, and add properties to expose the information the the VC's public interface. – Duncan C May 30 '15 at 19:32
0

According to me you haven't connected delegate of V2 class to self in MainVC "newImageVC?.delegate=self"

ankit
  • 3,537
  • 1
  • 16
  • 32
-1

[Updated based on comments]

The line

var visibleRect:CGRect!

assigns visibleRect to nil and thus the subsequent line of

visibleRect.origin.x = newImageVC.scrollView.contentOffset.x * scale;

will then dereference visibleRect, find nil and produce the exception. You need to allocate a CGRect and assign it to visibleRect.

[Original Answer]

Is visibleRect bound? It doesn't look to be. If that is bound, then you'll notice other uses of !... You need to bind your outlets (typically in InterfaceBuilder):

@IBOutlet var scrollView: UIScrollView!
@IBOutlet var inputImage:UIImageView!

Perhaps scrollView is not bound and thus, because it is implicitly unwrapped (the ! operator), when you reference it as nil your program will fatal.

Use:

var visibleRect = 
  CGRectMake (newImageVC.scrollView.contentOffset.x * scale,
              newImageVC.scrollView.contentOffset.y * scale,
              newImageVC.scrollView.bounds.size.width * scale,
              newImageVC.scrollView.bounds.size.height * scale)
GoZoner
  • 67,920
  • 20
  • 95
  • 145