ERROR unwrapping an Optional value AND dequeueReusableCellWithIdentifier(:cell identifier) - iphone

this is app for search
Not error before app running !
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell()
cell = tableView.dequeueReusableCellWithIdentifier("SpotListCell")!
if(cell.isEqual(NSNull))
{
cell = (NSBundle.mainBundle().loadNibNamed("SpotListCell", owner: self, options: nil)[0] as? UITableViewCell)!;
}
if tableView == self.tableView {
cell.textLabel?.text = posts.objectAtIndex(indexPath.row).valueForKey("title") as! NSString as String
} else {
cell.textLabel?.text = self.filteredPosts[indexPath.row]
}
return cell
}
Moment to run apps, searching the error.
The following error.
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
Where should be modified?
Thank you for reading it.
Note I am a Korean high school student.

This line is what is causing your troubles I guess:
cell = tableView.dequeueReusableCellWithIdentifier("SpotListCell")!
It seems your table view is unable to create a SpotListCell for you and since you add the ! you force the compiler to give you the value regardless of it being nil or not.
In the next line you then say:
if(cell.isEqual(NSNull))
but cell is nil so you can not ask it for anything (and besides...NSNull probably isn't what you're looking for).
Edit: updated my answer
First you should register you Nib so the UITableView can use it.
make an outlet to your UITableView and connect that:
#IBOutlet weak var tableView: UITableView!
Then in your viewDidLoad() you can do something like:
contentTableView.registerNib(UINib(nibName: "SpotListCell", bundle: nil), forCellReuseIdentifier: "SpotListCell")
And finally you can use your cell like this, notice the guard letto safely unwrap your cell:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCellWithIdentifier("SpotListCell") else {
return UITableViewCell()
}
//Populate as you did before
if tableView == self.tableView {
cell.textLabel?.text = posts.objectAtIndex(indexPath.row).valueForKey("title") as! NSString as String
} else {
cell.textLabel?.text = self.filteredPosts[indexPath.row]
}
return cell
}
See if that is any better (and I haven't checked it with a compiler so there might be errors...I'm sure the compiler will let you know :))
Hope that helps you.

Related

Initialize optional UIActivityIndicatorView in Swift

I have no idea what I am doing wrong. In my TableViewController, I want each cell to have a UIActivityIndicator when tapped. So in my TableViewCell class I have the following:
#IBOutlet weak var loadingIcon: UIActivityIndicatorView!
And in TableViewController I have the following:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "taskCell"
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? TodayTableViewCell else {
fatalError("The dequeued cell is not an instance of TodayTableViewCell.")
}
let task = tasks[indexPath.row]
cell.nameLabel.text = task.name
cell.descriptionLabel.text = task.description
cell.timeRangeLabel.text = task.timeRangeLabel
cell.currentTime.text = String(format:"%f", task.currentTime)
cell.totalTime.text = String(format:"%f", task.totalTime)
cell.taskIcon.image = task.icon
cell.loadingIcon = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)
cell.loadingIcon.hidesWhenStopped = true
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt
indexPath: IndexPath){
let cell = (TodayTableViewCell)();tableView.cellForRow(at: indexPath)
print("tapped")
tasks[indexPath.row].isActive = !tasks[indexPath.row].isActive
if(tasks[indexPath.row].isActive) {
//Loading.start()
cell.loadingIcon.startAnimating()
}
else {
//Loading.stop()
cell.loadingIcon.stopAnimating()
}
}
I get fatal error: unexpectedly found nil while unwrapping an Optional value but I have no idea why because it looks like I am initializing it.
I get:
EXC_BAD_INSTRUCTION
Here is the storyboard:
Now back to the error I was getting earlier:
As you can see in the image, you can set that property on the storyboard. You can find on the right panel of your xcode.
If you still want to write that line you should connect the UIActivityIndicator to the IBOutlet

Dictionary value when deleting cell - unexpectedly found nil while unwrapping an Optional value

Im working in Swift/Xcode and I am new to app development, i have a tableView with 2 labels. The issue is when deleting a cell of my tableView. I need to get the data of one of the cell labels but the app crashes with the fatal error - 'unexpectedly found nil while unwrapping an Optional value'
I have set up break points so that i can check if the dictionary has anything stored in it, which it does, there is an element stored in it.
Appreciate any help
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! myCustomCell
self.cost = self.total
// This line gives me the error** self.total = self.cost - self.dict[cell.cellPrice.text!]!
self.totalLabel.text = "Total: \(self.total)"
self.dict.removeValueForKey(cell.cellTitle!.text!)
tableView.reloadData()
saveState()
}
This my code to set up the cell:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: myCustomCell = tableView.dequeueReusableCellWithIdentifier("customCell", forIndexPath: indexPath) as! myCustomCell
var myDataSource : [String] = Array(self.dict.keys)
let key = myDataSource[indexPath.row] as String
cell.cellTitle?.text = myDataSource[indexPath.row]
cell.cellPrice?.text = "£(self.dict[key]!)"
self.saveState()
return cell
}
I'd have to see more of your code to know how you are setting properties of myCustomCell, but it looks like either cellPrice.text is nil or self.dict[cell.cellPrice.text] is nil. You should just unwrap those optionals safely rather than trying to force them. That'd look something like this:
if let price = cell.cellPrice.text, let priceValue = self.dict[price] {
self.totalLabel.text = "Total: \(priceValue)"
...
}
In general you should stay away from force unwrapping (using !) unless you're just writing really quickly for testing or something. It makes debugging harder.
You are trying to force unwrap. I guess it's cellPrice label or it text but one of those things. Figure out which one is nil.

Avoiding excessive ! use in Swift function (cellForRowAtIndexPath)

Simply put: How can I avoid writing ! for every line in the Swift code below? I considered guard, but the UITableViewCell initialiser can return nil, but on the other hand cellForRowAtIndexPath must return non-nil, which seems like a contradiction in itself. Hope there is a short and sweet way.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier)
if cell == nil {
cell = UITableViewCell(style: .Default, reuseIdentifier: reuseIdentifier)
}
cell!.textLabel?.text = ...
cell!.textLabel?.textColor = ...
cell!.detailTextLabel?.textColor = ...
cell!.detailTextLabel?.textColor = ...
return cell!
}
The ?? operator understands that if the rhs is not optional, then the result is not optional:
let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier)
?? UITableViewCell(style: .Default, reuseIdentifier: reuseIdentifier)
cell.textLabel?.text = ... // No ! needed
Better yet, if you register your cell identifiers (either in a storyboard or with the registerNib / registerClass methods), then you can use the newer form of dequeueReusableCellWithIdentifier which does not return an optional:
let cell = tableView.dequeueReusableCellWithIdentifier("repo", forIndexPath: indexPath)
cell.textLabel?.text = ... // No ! needed
Let me paste someting copied directly from the UITableView public API:
public func dequeueReusableCellWithIdentifier(identifier: String, forIndexPath indexPath: NSIndexPath) -> UITableViewCell
// newer dequeue method guarantees a cell is returned and resized properly, assuming identifier is registered
Looking at the method above, it guarantees returning a correct cell, thus the return type is not optional and you can avoid force unwrapping.
You can also code like this:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier)!
cell.textLabel?.text = ...
cell.textLabel?.textColor = ...
cell.detailTextLabel?.textColor = ...
cell.detailTextLabel?.textColor = ...
return cell
}

Retrieving data from Parse.com (Swift)

I am attempting to fetch data from an object created on Parse.com into a custom cell that contains labels and images. The code I implemented thus far runs but my tableview remains empty and at runtime displays the following error. ERROR: Thread 1: Exc_BAD_INSTRUCTION (Code =EXC_1386_INVOP, subcode=0x0). Can someone please explain why this is occurring I am new to programming in Xcode.
#objc
protocol ViewControllerDelegate {
optional func toggleLeftPanel()
optional func toggleRightPanel()
optional func collapseSidePanels()
}
class ViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate
{
var delegate: ViewControllerDelegate?
var arrayOfParties: [Information] = [Information]()
#IBAction func menuTapped(sender: AnyObject) {
delegate?.toggleLeftPanel?()
}
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.loadData()
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
//return self.arrayOfParties.count
return self.arrayOfParties.count
}
//Function to adjust the height of the custom cell
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
return 230
}
override func tableView(tableView: UITableView,cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell: CustomCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! CustomCell
let party = arrayOfParties[indexPath.row]
cell.setCell(party.partyName, promoterLabelText: party.promoterName, partyCostLabelText: party.partyCost, partyFlyerUIImage: party.flyerImage, promoterUIImage: party.promoterImage)
return cell
}
func loadData()
{
var findDataParse:PFQuery = PFQuery(className: "flyerDataFetch")
findDataParse.findObjectsInBackgroundWithBlock{
(objects: [AnyObject]?, error: NSError?)->Void in
if (error == nil){
for object in objects!
{
var party1 = Information(partyName: (object["partyName"] as? String)!, promoterName: (object["promoterName"] as? String)!, partyCost: (object["partyCost"] as? String)!, flyerImage: "", promoterImage: "")
self.arrayOfParties.append(party1)
}
}
else {
// something went wron
}
}
}
}
The problem is that you probably have cells in the tableview already that don't have the new labels/images.
You need to tell the program to insert a type of text where there is no input of the new type.
In this case I have already since a month back worked on a project, and now I started inserting more labels into my cell, thats where the problem pops up, so the previous cells don't have this information.
So I just tell the system to check all cells, if a cell doesn't have the needed text, it should just enter some placeholder text (in this case = "").
if let content = text.objectForKey("Content") as? String {
cell.TextView.alpha = 1.0
cell.TextView.text = content
}
else{
cell.TextView.alpha = 1.0
cell.TextView.text = ""
}
I hope this helps, I have only explained how to do, I haven't really told you were in your code to do it, but from what I see you should input the code right under the part where you declare "Party1".

swift: prepareForSegue indexPathForSelectedRow

I have an UITableView populated by a cellForRowAtIndexPath:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("customTableViewCell") as! UITableViewCell
let task = frc.objectAtIndexPath(indexPath) as! Task
cell.textLabel?.text = task.summary
var detail = task.detail
var context = task.context
var due = task.date
var status = task.status
var responsible = task.responsable
var folder = task.folder
cell.detailTextLabel?.text = "Contexte: \(context), Detail: \(detail), Status: \(status), Ending date: \(due)"
return cell
}
On the storyboard, I have made a segue when clicking one cell of the tableView to open a detailViewController
this is my didSelectRowAtIndexPath:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
self.name = cell!.textLabel!.text!
println(self.name)
self.performSegueWithIdentifier("Show Detail", sender: indexPath);
}
and the prepareForSegue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if let identifier = segue.identifier{
switch identifier {
case "Show Detail":
let indexPath = self.tableView.indexPathForSelectedRow()
let editTaskVC = segue.destinationViewController as! EditTaskViewController
editTaskVC.Name = "cell.textLabel?.text is what I would like to.."
default: break
}
}
}
If I do editTaskVC.Name = indexPath?.description I can see the description of the cell clicked like, <NSIndexPath: 0x78f96ab0>... for example.
Is it possible, instead of printing the description of the indexPath, printing the cell.textLabel?.text of the clicked row?
I have seen many, many tutorials or posts on forum but I haven't succeed to solve my problem...
Thank you for your help.
Regards.
Your intention is to pass along the cell.textLabel?.text to the destination view controller right?
You're taking a needless detour. The sender parameter in performSegueWithIdentifier: can take in an AnyObject, so you can go right ahead and pass it the name.
self.performSegueWithIdentifier("Show Detail", sender: name)
That way, prepareForSegue will have the item you need to pass along to the next view controller. Simply assign editTaskVC = sender as! String and you're good to go.
The piece of knowledge you were missing is that, the sender parameter in performSegueWithIdentifier: sender will automatically pass the sender's contents into prepareForSegue, as the sender parameter.
Since you already have the index path, you can simply invoke the table's cellForRowAtIndexPath to obtain the cell:
if let indexPath = self.tableView.indexPathForSelectedRow() {
if let cell = self.tableView.cellForRowAtIndexPath(indexPath) as? UITableViewCell {
let editTaskVC = segue.destinationViewController as! EditTaskViewController
editTaskVC.Name = cell.textLabel?.text
}
}
The indexPathForSelectedRow returns nil in 2 cases only:
if the index is out of range
if the cell is not visible