user2320861
user2320861

Reputation: 1431

Error thrown when trying to animate UIImageView with programmatically created images

I'm trying to animate a UIImageView with images that I created programmatically. Whenever I call startAnimating() I get the error

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'

I understand that this error is thrown when one of the images in imageView.animationImages is nil, but none of mine are.

Create a new single-view iOS-9 application and paste the following code in viewDidLoad() of the view controller to see what's going on.

    super.viewDidLoad()


    //Create an imageview and add it to the view

    let imageView = UIImageView()

    imageView.translatesAutoresizingMaskIntoConstraints = false

    view.addSubview(imageView)

    imageView.leftAnchor.constraintEqualToAnchor(view.leftAnchor).active = true

    imageView.rightAnchor.constraintEqualToAnchor(view.rightAnchor).active = true

    imageView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor).active = true

    imageView.topAnchor.constraintEqualToAnchor(view.topAnchor).active = true



    //Create an image

    let solidColorFilter = CIFilter(name: "CIConstantColorGenerator")!

    solidColorFilter.setValue(CIColor(color: UIColor.redColor()), forKey: "inputColor")

    let cropFilter = CIFilter(name: "CICrop")!

    cropFilter.setValue(CIVector(CGRect: CGRectMake(0, 0, 300, 300)), forKey: "inputRectangle")

    cropFilter.setValue(solidColorFilter.outputImage, forKey: "inputImage")



    //Create animation images

    var animationImages = [UIImage]()

    let hueAdjustFilter = CIFilter(name: "CIHueAdjust")!

    hueAdjustFilter.setValue(cropFilter.outputImage, forKey: "inputImage")

    for (var i: CGFloat = 0; i < 10; i++) {

        hueAdjustFilter.setValue(-CGFloat(M_PI) + CGFloat(i/10.0) * 2.0 * CGFloat(M_PI), forKey: "inputAngle")

        let hueAdjustedImage = UIImage(CIImage: hueAdjustFilter.outputImage)

        animationImages.append(hueAdjustedImage)

    }


    print("Break here to inspect images in animationImages array. None are nil")


    //Try to animate the images using imageview animationImages

    imageView.animationImages = animationImages

    imageView.animationDuration = 4.0

    imageView.startAnimating() //ERROR THROWN HERE

Please help! Thanks!

Upvotes: 1

Views: 265

Answers (1)

user2320861
user2320861

Reputation: 1431

I figured it out. When a UIImage is created from a CIImage the CGImage property of the UIImage is nil. I guess the backing layer for the UIImageView uses the CGImage to render itself. Anyways, to get a CGImage from a CIImage I had to create a CIContext and then call CIContext.createCGImage:FromRect:, then use the CGImage to create a UIImage... here's code

    //Create a context
    let myEAGLContext = EAGLContext(API: EAGLRenderingAPI.OpenGLES2)

    let options = [kCIContextWorkingColorSpace: NSNull()]

    let myContext = CIContext(EAGLContext: myEAGLContext, options: options)


    //Create animation images

    var animationImages = [UIImage]()

    let hueAdjustFilter = CIFilter(name: "CIHueAdjust")!

    hueAdjustFilter.setValue(cropFilter.outputImage, forKey: "inputImage")

    for (var i: CGFloat = 0; i < 10; i++) {

        hueAdjustFilter.setValue(-CGFloat(M_PI) + CGFloat(i/10.0) * 2.0 * CGFloat(M_PI), forKey: "inputAngle")

        let hueAdjustedCGImage = myContext.createCGImage(hueAdjustFilter.outputImage, fromRect: CGRectMake(0, 0, 300, 300))

        let finalImage = UIImage(CGImage: hueAdjustedCGImage)

        animationImages.append(finalImage)

    }

Upvotes: 3

Related Questions