0

So here is what's happening in human logic (but not suppose to be).

  1. My View controller loads
  2. retrieves my images from Parse successfully
  3. sets the first retrieved image equal to my UIImageView image
  4. starts my timer of 5 Seconds (I think)
  5. And then it doesn't do anything, just remains on the very first image
  6. Once I close the window (which was presented modally by previous view controller), I see in the console my println() outputs and my timer begins to work.

The GOAL: To present an image in my UIImageView for 5 seconds or so, and then display the next one in line (imageArray).

Is it my timer that's causing this pause in function, or does it have something to do with how my code is arranged? All suggestions/help are very much appreciated as this is a very frustrating issue.

This is in Swift language, but I can read Objective-C.

Here is my code for the class:

//
//  ImageDisplayViewController.swift
//  
//
//  Created by on 5/3/15.
//
//

import Cocoa
import ParseOSX

class ImageDisplayViewController: NSViewController {


@IBOutlet weak var imageView: NSImageView!

var venue: String!
var imageArray = [(Int, NSImage)]()
var image: NSImage!
var timeToDisplay: Int = 0

var timer = NSTimer()

override func viewDidLoad() {
    super.viewDidLoad()

    venue = "Bees"
    loadImages()


}

var k: Int = 0

func presentNextImage() {
    if(k<imageArray.count) {
    imageView.image = imageArray[k].1
    timer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: Selector("presentNextImage"), userInfo: nil, repeats: false)
        println(timer.timeInterval)
        //imageView.image = imageArray[k].1
        println("k is \(k)")
        k++
        println("Just set a new imageView.image")
    } else {
        println("K is n longer <imageArray.count")
    }
}



func loadImages() {
    var query = PFQuery(className:groupz)
    query.whereKeyExists("imageFile")
    query.findObjectsInBackgroundWithBlock {
        (objects: [AnyObject]?, error: NSError?) -> Void in

        if error == nil {
            println("Successfully retrieved \(objects!.count) objects.")
            // Do something with the found objects
            if let objects = objects as? [PFObject] {
                for object in objects {
                    let thumbNail = object["imageFile"] as! PFFile
                    self.image = NSImage(data: thumbNail.getData()!)
                    let time: AnyObject? = object["displayTime"]
                    self.timeToDisplay = time!.integerValue

                    let tempTuple = (self.timeToDisplay, self.image!)
                    self.imageArray.append(tempTuple)

                }
            }
            println("imageArray.count is: \(self.imageArray.count)")
            self.presentNextImage()
        } else {
            // Log details of the failure
            println("Error: \(error!) \(error!.userInfo!)")
        }
    }
}

}

justColbs
  • 1,504
  • 2
  • 18
  • 28

2 Answers2

2

Declare your NSTimer as weak. From the Apple docs on NSTimer:

Note in particular that run loops maintain strong references to their timers, so you don’t have to maintain your own strong reference to a timer after you have added it to a run loop.

Also, you actually do not need to maintain a reference to the timer since you aren't calling invalidate outside of the method being called in the selector argument which, in your case, happens to be the method that allocates the timer.

In your case maintain a weak reference to the timer and invalidate it to remove it from the run loop in viewWillDisappear:.

Timer Programming Topics - Cocoa concept

Michael
  • 6,561
  • 5
  • 38
  • 55
  • I appreciate you help, but I am not removing the view. Also, in the Apple Docs I read that only timers that repeat need to use invalidate(). I am only trying to start a timer for a given amount of seconds and at the end of that given amount time, call the method it is in order to set my imageView to the next image in my imageArray array. – justColbs May 06 '15 at 15:59
0

I found the problem. For some reason, presenting my view controller (the one which displays the images) as Modal cause the timer not to run or possibly be added to the NSRunLoop. I'm not really sure on that. But as soon as I changed the Segue to just Showmy timer began to work correctly.

Thank you for the help Nikita, I actually learned a lot from your answer to my question.

justColbs
  • 1,504
  • 2
  • 18
  • 28