Search code examples
iosswiftnstimer

NSTimer Issues to start image slideshow automatically


I'm discovering issues on attempting to start image slideshow on my app after launching splash screen. For some reason the image slideshow takes too long to start I had to click either previous button or next button or my UISlider to display slideshow then the app crashes. Is there something wrong or missing in my code? The goal is to start image slideshow automatically. Here is my code below. Also, I have a screenshot of how my image slideshow setup in the link below.

Image Slideshow Setup

var Array = [UIImage]()
var counter = 2
var time = Timer()


@IBOutlet weak var menuButton: UIBarButtonItem!
@IBOutlet weak var ImageView: UIImageView!
@IBOutlet weak var Slider1: UISlider!
@IBAction func Slider(_ sender: UISlider) {
    _ = 0
    let value = Int(sender.value)
    ImageView.image = Array[value]
}

@IBAction func NextButton(_ sender: Any) {
    Slider1.value += 1
    ImageView.image = Array[Int(Slider1.value)]
    self.ImageView.animationImages = self.Array
    self.ImageView.animationDuration = 3.0
    self.ImageView.animationRepeatCount = 0
    self.ImageView.startAnimating()

    UIView.transition(with: self.ImageView, duration: 5.0, options: .transitionCrossDissolve, animations: {self.ImageView.image = self.ImageView.image}, completion: nil)

}


@IBAction func PrevButton(_ sender: Any) {
    Slider1.value -= 1
    ImageView.image = Array[Int(Slider1.value)]
    self.ImageView.animationImages = self.Array
    self.ImageView.animationDuration = 3.0
    self.ImageView.animationRepeatCount = 0
    self.ImageView.startAnimating()

    UIView.transition(with: self.ImageView, duration: 5.0, options: .transitionCrossDissolve, animations: {self.ImageView.image = self.ImageView.image}, completion: nil)
}

 //Set Status Bar to light content (white)
override var preferredStatusBarStyle : UIStatusBarStyle {
    return .lightContent
}

override func viewDidLoad() {
    //Set Navigation Bar color Example Home, Back button
    self.navigationItem.backBarButtonItem?.tintColor = UIColor.white;

   time = Timer.scheduledTimer(timeInterval: 5,
                        target: self,
                        selector: #selector(getter: self.Slider1),
                        userInfo: nil,
                        repeats: true)
super.viewDidLoad()

setup()

   Array = [#imageLiteral(resourceName: "MainImage1.jpg"), #imageLiteral(resourceName: "MainImage2.jpg"), #imageLiteral(resourceName: "MainPage3.jpg"), #imageLiteral(resourceName: "MainImage4.jpg"), #imageLiteral(resourceName: "MainImage5.jpg"), #imageLiteral(resourceName: "MainImage6.jpg"), #imageLiteral(resourceName: "MainImage7.jpg"), #imageLiteral(resourceName: "MainImage8.jpg")]

    sideMenus()

    // Do any additional setup after loading the view.
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func setup(){
self.navigationController?.navigationBar.tintColor = UIColor.white
}

override var prefersStatusBarHidden: Bool{
    return false
}

var navigationBarAppearace = UINavigationBar.appearance()
 override func viewDidAppear(_ animated: Bool){
}



func sideMenus() {

    if revealViewController() != nil {

        menuButton.target = revealViewController()
        menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
        revealViewController().rearViewRevealWidth = 275
        revealViewController().rightViewRevealWidth = 160

        view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }
}
    }` 

Solution

  • The timer's target selector is the function that gets called on the interval that you specify. In the code above, you're using the getter for your slider property as the function for the timer to call-- that's not doing what you want. The timer is going to call that getter every 5 seconds, but all that getter function does is just "get" the value of the slider property.

    You want the timer's selector to do something for you, for example, to trigger the "next" button function. Why not use the form of timer creation that allows you to specify a closure to wrap the behavior? Something like:

    time = Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { _ in
        self.NextButton(self)
    }
    

    (This seems more elegant in Swift than using a #selector to point to an objc exposed function anyway.)