Nick Winner Nick Winner - 3 months ago 8
Swift Question

Swift - Add tableview to a UIViewController

I am building an iOS app in swift. I have a UIViewController that displays a few labels and fields and I would like to add a tableview. I'm a total swift noob, but after much googling, I've gotten everything integrated and "working" properly. However, I am encountering a "fatal error: unexpectedly found nil while unwrapping an Optional value" when I use dequeueReusableCellWithIdentifier. My cell is a custom class with just two IBOutlets, detailKey and detailValue. Any suggestions?

import UIKit

class ContactViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

// MARK:Properties
var contact : Contact?
var params : [Detail]?

@IBOutlet weak var keywords: UILabel!
@IBOutlet weak var name: UILabel!
@IBOutlet weak var contactDetails: UITableView!

// for use in params array
struct Detail {
var key : String,
value : String
}

override func viewDidLoad() {
super.viewDidLoad()

// Do any additional setup after loading the view.
contactDetails.dataSource = self
contactDetails.delegate = self

if (self.contact != nil) {
// set default value for params array since optional
self.params = []

// make keywords string
var count : Int = 0
var keywordString : String = ""

while count < contact!.keywords.count {
keywordString += contact!.keywords[count].description

if count + 1 < contact!.keywords.count {
keywordString += ", "
}

count += 1
}

// compile details for tableview
if (!self.contact!.company.isEmpty) { self.params! += [Detail(key: "Company", value: self.contact!.company)] } // company
if (!self.contact!.phone1.isEmpty) {
self.params! += [Detail(key: self.contact!.phone_label1.isEmpty ? "Phone 1" : self.contact!.phone_label1, value: self.contact!.phone1)]
}
if (!self.contact!.phone2.isEmpty) {
self.params! += [Detail(key: self.contact!.phone_label2.isEmpty ? "Phone 2" : self.contact!.phone_label2, value: self.contact!.phone2)]
}
if (!self.contact!.email1.isEmpty) {
self.params! += [Detail(key: self.contact!.email_label1.isEmpty ? "Email 1" : self.contact!.email_label1, value: self.contact!.email1)]
}
if (!self.contact!.email2.isEmpty) {
self.params! += [Detail(key: self.contact!.email_label2.isEmpty ? self.contact!.email_label2 : "Email 2", value: self.contact!.email2)]
}
if (!self.contact!.street.isEmpty) { self.params! += [Detail(key: "Address", value: self.contact!.address)] } // address (condition checks for street)
if (!self.contact!.dob.isEmpty) { self.params! += [Detail(key: "Birthday", value: self.contact!.dob)] } // dob
if (!self.contact!.social.isEmpty) { self.params! += [Detail(key: "Social Security Number", value: self.contact!.social)] } // social

self.name.text = contact!.name
self.keywords.text = keywordString
}
}

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

// table view stuffs
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.params!.count ?? 0
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("going")
let cell = tableView.dequeueReusableCellWithIdentifier("contactDetail") as! ContactDetailTableViewCell
let param = self.params![indexPath.row]

print(param.key + ": " + param.value)

cell.detailKey.text = param.key
cell.detailValue.text = param.value

return cell
}


enter image description here

Answer

To set your cell identifier Select your cell then you will see Identifier field in Attributes Inspector, set your reuse identifier there... That's about it..

Also try adding :-

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

and replace

 let cell = tableView.dequeueReusableCellWithIdentifier("contactDetail") as! ContactDetailTableViewCell

to

let cell = tableView.dequeueReusableCellWithIdentifier("contactDetail", forIndexPath: indexPath) as! ContactDetailTableViewCell

EXPLANATION

CMD+CLICK on the function Name : dequeueReusableCellWithIdentifier-- you will be directed to its documentation ..

public func dequeueReusableCellWithIdentifier(identifier: String) -> UITableViewCell? // Used by the delegate to acquire an already allocated cell, in lieu of allocating a new one.
@available(iOS 6.0, *)
public func dequeueReusableCellWithIdentifier(identifier: String, forIndexPath indexPath: NSIndexPath) -> UITableViewCell // newer dequeue method guarantees a cell is returned and resized properly, assuming identifier is registered
  • dequeueReusableCellWithIdentifier(identifier: String, forIndexPath indexPath: NSIndexPath) guarantees you a cell..

Maybe these links are helpful :-

Fatal error: unexpectedly found nil while unwrapping an Optional values

http://stackoverflow.com/a/25569704/6297658

Comments