ellman121
ellman121

Reputation: 1835

UIImageViewImage doesn't change when set

I've read through about 15 posts on StackOverflow discussing the topic of UIImageViews and animating them to crossfade. I would like to eventually have a crossfade, but I can't even get the images to change at this point.

My code is

var next = 0
let names = ["image_1", "image_2", "image_3", "image_4"]

// While the image is still in memory, keep cycling every few seconds
while ImageView != nil {
    print(next % 4)

    // Grab the new image
    let nextImage = UIImage(named: names[next % 4])
    next++

    // Set the new image
    ImageView.image = nextImage

    // Wait a few seconds
    NSThread.sleepForTimeInterval(NSTimeInterval(4))
}

The image names are coming out of my xcassets. When I run it, the image doesn't change, but the loop still prints every few seconds

What am I doing wrong?

Upvotes: 0

Views: 41

Answers (2)

Duncan C
Duncan C

Reputation: 131418

No. Wrong. Forget you ever heard about sleep and it's variants. It is a huge no-no from the main thread. It blocks the UI, will cause the system to kill your app, and also just plain doesn't work in this case. (UI changes don't take effect until your code returns and visits the event loop)

What you want to do is install and image, then start a timer or use dispatch_after to queue up code that will display a new image after some time interval, and THEN RETURN.

Your code might look like this:

var next = 0

func fetch()
{
    // Grab the new image
    let nextImage = UIImage(named: names[next % 4])
    next++

    // Set the new image
    ImageView.image = nextImage

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.5 * NSEC_PER_SEC))
    {
       fetch()
    }
}

Upvotes: 1

Dominik Vincenz
Dominik Vincenz

Reputation: 435

You are running this Loop in the main Thread

So the loop blocks your MainThread and the ImageView cannot be updated.

UI-Stuff is not updated immediately when your code is hit.

You can do something like this:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 
    while ImageView != nil {
        print(next % 4)

        let nextImage = UIImage(named: names[next % 4])
        next++

        dispatch_async(dispatch_get_main_queue()) { 
            // UI Changes need to be done in the main thread
            ImageView.image = nextImage
        }


        // blocking code needs to be done in another thread
        NSThread.sleepForTimeInterval(NSTimeInterval(4))
    }
}

Upvotes: 1

Related Questions