makthrow makthrow - 2 months ago 21
Swift Question

multiple taps of a uitableviewcell result in exception: Application tried to present modally an active controller

i'm not sure if there is a real "solution" for this, but when I press multiple times on a tableviewcell really quickly, i get this error:


Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: 'Application tried to present
modally an active controller


If I press just once, my code works fine. It's only if I press really really quickly multiple times. Is there a way to avoid this?

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

let selectedCell = tableView.cellForRow(at: indexPath)

selectedUserAtIndexPath = (indexPath as NSIndexPath).section
// download and show video
playVideoAtCell((indexPath as NSIndexPath).section)

}

func playVideoAtCell(_ cellNumber: Int) {

getDownloadURL(cellNumber) { (url) in

self.avPlayer = AVPlayer(url: url)
self.avPlayerViewController.player = self.avPlayer
self.avPlayerViewController.showsPlaybackControls = false

NotificationCenter.default.addObserver(self, selector: #selector(self.videoItemFinished(_:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: self.avPlayer?.currentItem)

self.present(self.avPlayerViewController, animated: true) { () -> Void in
self.avPlayerViewController.player?.play()
}
}
}


func getDownloadURL (_ cellNumber: Int, callback: @escaping (URL) -> ()) {
let mediaID = mediaIntroQueueList[cellNumber]["mediaID"] as? String

Constants.storageMediaRef.child("\(mediaID!)").downloadURL(completion: { (URL, error) in
if let downloadURL = URL {
callback (downloadURL)
}
})
}

Answer

The error code gives you all you need to know. You're trying to call this over and over when you tap the cell more than once:

    self.present(self.avPlayerViewController, animated: true) { () -> Void in
        self.avPlayerViewController.player?.play()
    }

What you could do is check at the beginning of playVideoAtCell if you're player has already been created. Therefore you could assume it's already presented:

func playVideoAtCell(_ cellNumber: Int) {
    if self.avPlayer != nil { return }

Or you could add a bool in somewhere to keep track if you've already presented a modal view.