user3676870
user3676870

Reputation: 21

Xcode 6 GM storyboard outlets always nil

I am developing an app with swift in Xcode 6 GM using storyboard. On my viewcontroller if I drag and drop any view and connect it with an IBOutlet in the related viewcontroller file, that outlet is always nil in viewDidLoad and I always get BAD_INSTRUCTION error if I try to interact with that outlet like changing the title of a button or anything else because that referenced outlet is always nil and I cannot understand why.. I've checked that the viewcontroller on the storyboard is owned by my viewcontroller file in identity inspector under custom class option.. Is it an issue of Xcode and someone else is getting the same problem or I'm doing something wrong?

EDIT 1:

this is the first viewcontroller that is launched

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    let vc = segue.destinationViewController as TableViewController
    vc.prepare(/*initializing things..*/)

}

//and this is the viewcontroller with my tableview outlet and custom cell

import UIKit

class TableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

@IBOutlet var tableView: UITableView!


//this array contains the date to display in cells and in viewDidLoad is correctly  initialized with all the right data..
private var toVisualize:[Visualizable] = []

 override func viewDidLoad() {
    super.viewDidLoad()
    /*I need to initialize the tableview even if it's an outlet rightly connected to the storyboard because it's always nil when viewDidLoad is called*/
    self.loadArticles()
    self.tableView = UITableView(frame: self.tableView.frame, style: UITableViewStyle.Plain)
    //navigationController?.hidesBarsOnSwipe = true
    self.tableView.delegate = self
    self.tableView.dataSource = self
    self.tableView.allowsSelection = true
    var cell = UINib(nibName: "MyCell", bundle: nil)
    /*first I've used a prototype cell defined in the storyboard and a class with the related outlets and all connected in the right way but the result was a blank screen so I've tried to use a xib file to define the layout of my custom cell and the tableview started showing my cells.. but still I can't figure out why the tableview is nil*/
    self.tableView.registerNib(cell, forCellReuseIdentifier: "Cell")
    //self.tableView.registerClass(CellaTableViewCell.classForCoder(), forCellReuseIdentifier: "Cell")
    self.view.addSubview(self.tableView)
    self.tableView.reloadData()
    // Do any additional setup after loading the view.
}


func prepare(/*preparing function used from first view controller..*/)->()
{
    //this func is not changing anything because I've added it later..
}

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

//this function is correctly working and showing the cells when the tableview is initialized
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = self.tableView?.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as MyCell

    var toLoad = self.toVisualize[indexPath.row].getVisualizableProperties()



    cell.loadItem(toLoad.title, descr: toLoad.descr, date: toLoad.date)


    if let URL = toLoad.thumbUrl
    {
        var image = self.imageCache[URL]

        if( image == nil ) {
            // If the image does not exist, we need to download it
            var imgURL: NSURL = NSURL(string: URL)

            // Download an NSData representation of the image at the URL
            let request: NSURLRequest = NSURLRequest(URL: imgURL)
            NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!,error: NSError!) -> Void in
                if error == nil {
                    image = UIImage(data: data)

                    // Store the image in to our cache
                    self.imageCache[URL] = image
                    dispatch_async(dispatch_get_main_queue(), {
                        if let cellToUpdate = tableView.cellForRowAtIndexPath(indexPath) as? MyCell {
                            cellToUpdate.thumbnail?.image = image
                        }
                    })
                }
                else {
                    println("Error: \(error.localizedDescription)")
                }
            })

        }
        else {
            dispatch_async(dispatch_get_main_queue(), {
                if let cellToUpdate = tableView.cellForRowAtIndexPath(indexPath) as? MyCell {
                    cellToUpdate.thumbnail?.image = image
                }
            })
        }

    }

    return cell
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

func tableView(tableView: UITableView!,heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat
{
    return 120.0
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.toVisualize.count
}

}

First I was using presentViewController to push the TablewViewController programmatically and my outlet tableview was always nil in viewDidLoad, then I've tried to use the "Triggered Segues" action of buttons in my ViewController to push the TableViewController (ViewController in it's view contains only 4 buttons with presenting segues actions that all present TableViewController.. nothing special or strange) and the tableview started to be initialized and then I've commented out the init method of tableview and delegate setting (delegate and dataSource are already set in storyboard) but the result is again a blank screen showing nothing.. I've double checked all the connections with storyboard and various identifiers so they are all correctly set.. Can't figure out what's the problem

Upvotes: 2

Views: 1654

Answers (2)

Mike Gledhill
Mike Gledhill

Reputation: 29213

that outlet is always nil in viewDidLoad and I always get BAD_INSTRUCTION error if I try to interact with that outlet like changing the title of a button or anything else because that referenced outlet is always nil and I cannot understand why

Try referencing the control in the viewWillAppear or viewDidAppear functions instead.

When viewDidLoad runs, your app won't have created the views and controls yet, so it's too early to modify their contents.

Also, in your Storyboard, right-click on your control, and check that you have something listed under the "Referencing Outlets" section, with the circle filled in on that row. (That just confirms that you do have a variable bound to that control.)

enter image description here

Upvotes: 0

Patrick Lynch
Patrick Lynch

Reputation: 2782

I had the same problem in Xcode 6.1 beta and finally the outlets stopped being nil after removing the custom cell registration line from my viewDidLoad method:

// Remove this: self.tableView.registerClass( MyTableViewCell.self, forCellReuseIdentifier: "MyIdentifier" )

Works when instantiating from a storyboard and pushing or adding as a subview to another view programmatically.

Upvotes: 1

Related Questions