uclagamer
uclagamer

Reputation: 987

Swift: "Attempt to present ViewController whose view is not in the window hierarchy" when using presentViewController inside a delegate method

I am using a custom cell class with a button in it.

import UIKit

protocol TouchDelegateForShotsCell {
    func touchedTwitterButton()
}

class ShotsCell : UITableViewCell {

    let touchDelegateForShotsCell: TouchDelegateForShotsCell = MasterViewController()

    @IBAction func twitterButtonPressed(sender: AnyObject) {
         touchDelegateForShotsCell.touchedTwitterButton()
    }
}

When the button is pressed I call a delegate function in the MasterViewController which contains the following standard code for sharing on Twitter:

func touchedTwitterButton() {
    var shareToTwitter :SLComposeViewController = SLComposeViewController(forServiceType: SLServiceTypeTwitter)
    self.presentViewController(shareToTwitter, animated: true, completion: nil)
}

I receive the error :

"Attempt to present ViewController whose view is not in the window hierarchy!".

I've tried several workarounds. For example, creating a separate view controller and performing a segue from the button. That works in part, however, when I try to pass data I get another error :

"'NSInvalidArgumentException', reason: Receiver ViewController has no segue with identifier 'segueToTwitterShare'".

Which isn't true. For this I tried deleting my app and restarting xcode which worked for some people. However, the problem persists.

Upvotes: 1

Views: 657

Answers (1)

Mindsers
Mindsers

Reputation: 662

let touchDelegateForShotsCell: TouchDelegateForShotsCell = MasterViewController()

It's not the good delegate. When you write MasterViewController() you create a new instance of MasterViewController (so it is not in the window hierarchy) but you don't pass the intense who is executed.

I suggest you an example to better understand what is the problem and see where changes is needed.

I add an init() function into ShotsCell :

class ShotsCell : UITableViewCell {

    var touchDelegateForShotsCell: TouchDelegateForShotsCell!

    init(withDelegate delegate: MasterViewController){
        super.init(style: UITableViewCellStyle.Default, reuseIdentifier: "cellIdentifier")

        touchDelegateForShotsCell = delegate
    }

    @IBAction func twitterButtonPressed(sender: AnyObject) {
        touchDelegateForShotsCell.touchedTwitterButton()
    }
}

And pass your MasterViewController to your cell in cellForRowAtIndexPath :

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = ShotsCell(withDelegate: self)

    return cell
}

Hope that helps. It works for me.

Upvotes: 1

Related Questions