Reputation: 21
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
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.)
Upvotes: 0
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