Missing return in a function expected to return 'UITableViewCell', but actually returning twice
You should return a cell. In the above code, if both conditions failed, then nothing will be returned. So a warning raised. Just remove second "if" condition and use else case as follows:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if friendSelector.selectedSegmentIndex == 0 {
print("0")
cell = self.friendsTable.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FriendsTableViewCell
cell.nameLabel.text = friends[indexPath.row]
cell.bacLabel.text = String(friendsBac[indexPath.row])
cell.statusImageView.image = friendsImage[indexPath.row]
return cell
}
else {
print("1")
celladd = self.friendsTable.dequeueReusableCell(withIdentifier: "celladd", for: indexPath) as! FriendsAddTableViewCell
celladd.nameLabel.text = requested[indexPath.row]
celladd.statusImageView.image = UIImage(named: "greenlight")
return celladd
}
}
Missing return in a function expected to return 'UITableViewCell
This is one of those things that the compiler gets over-worried about. The compiler is basically asking you, what if indexPath.row
is neither 0 nor 1 nor 2? What to return in that case. As the programmer you know that indexPath.row
will always be one of those values, but the compiler doesn't know that.
So you need to return something in the default
case, but it does not make sense to return anything, does it? In this case, I would just write:
fatalError("Somehow indexPath.row is an unexpected value.")
This will crash the app if the default
case is ever reached. If the default case is ever reached, it probably means there is something wrong with your code (or maybe a bug in the API (unlikely)!), because as you know the table view only has 3 rows. The app should probably crash at this point.
Missing return UITableViewCell
- Declare the cell at the start of the method,
- assign a value to the cell depending on section and row number,
- throw a
fatalError()
in all cases that "should not occur", - return the cell.
Also note that the break
statements are not needed. The default
behavior in Swift is not to fall through to the next case.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: SettingsCell
switch(indexPath.section) {
case 0:
switch (indexPath.row) {
case 0:
cell = tableView.dequeueReusableCellWithIdentifier("cell0", forIndexPath: indexPath) as! SettingsCell
cell.backgroundColor = UIColor.redColor()
case 1:
cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! SettingsCell
cell.backgroundColor = UIColor.whiteColor()
default:
fatalError("Unexpected row \(indexPath.row) in section \(indexPath.section)")
}
case 1:
switch (indexPath.row) {
case 0:
cell = tableView.dequeueReusableCellWithIdentifier("cell10", forIndexPath: indexPath) as! SettingsCell
cell.backgroundColor = UIColor.redColor()
case 1:
cell = tableView.dequeueReusableCellWithIdentifier("cell11", forIndexPath: indexPath) as! SettingsCell
cell.backgroundColor = UIColor.whiteColor()
default:
fatalError("Unexpected row \(indexPath.row) in section \(indexPath.section)")
}
default:
fatalError("Unexpected section \(indexPath.section)")
}
return cell
}
The fatalError()
error function is marked as @noreturn
, so the
compiler knows that program execution will not continue from the
default cases. (This also helps to find logic errors in the program.)
The compiler verifies that a value is assigned to cell
in all
other cases.
The possibility to initialize a constant (let cell ...
) in this
way is new in Swift 1.2.
Alternatively, you can create a cell and return it "immediately"
in each case:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch(indexPath.section) {
case 0:
switch (indexPath.row) {
case 0:
let cell = tableView.dequeueReusableCellWithIdentifier("cell0", forIndexPath: indexPath) as! SettingsCell
cell.backgroundColor = UIColor.redColor()
return cell
case 1:
let cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! SettingsCell
cell.backgroundColor = UIColor.whiteColor()
return cell
default:
fatalError("Unexpected row \(indexPath.row) in section \(indexPath.section)")
}
case 1:
switch (indexPath.row) {
case 0:
let cell = tableView.dequeueReusableCellWithIdentifier("cell10", forIndexPath: indexPath) as! SettingsCell
cell.backgroundColor = UIColor.redColor()
return cell
case 1:
let cell = tableView.dequeueReusableCellWithIdentifier("cell11", forIndexPath: indexPath) as! SettingsCell
cell.backgroundColor = UIColor.whiteColor()
return cell
default:
fatalError("Unexpected row \(indexPath.row) in section \(indexPath.section)")
}
default:
fatalError("Unexpected section \(indexPath.section)")
}
}
Again, calling fatalError()
solves the "missing return expected" compiler
error.
This pattern can be useful if there are different kinds of cells
(with different classes) created in each case.
Getting error like Missing return in a function expected to return 'UITableViewCell' in swift
In both cases you have to return something if the if let
check fails.
First of all the enum cases are supposed to be named with starting lowercase letter
enum TableSection: Int {
case profileNameAndImage = 0, followAndFollowings, options
}
In numberOfRows
return 0 if the check fails – which actually will never happen
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let tableSection = TableSection(rawValue: section) else { return 0 }
switch tableSection {
case .profileNameAndImage, .followAndFollowings:
return 1
case .options:
return ProfileOptionViewModel.allCases.count
}
}
In cellForRow
force unwrap the section (the method is not called if numberOfRows
is 0) and also force downcast all cells. The code must not crash. If it does it reveals a design mistake.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let tableSection = TableSection(rawValue: indexPath.section)!
switch tableSection {
case .profileNameAndImage:
let cell = tableView.dequeueReusableCell(withIdentifier: "ProfileImageAndNameTableViewCell") as! ProfileImageAndNameTableViewCell
cell.userData = ProfileImageAndNameModel(userName: "John", userId: "12345", userImage: #imageLiteral(resourceName: "bird"))
return cell
case .followAndFollowings:
let cell = tableView.dequeueReusableCell(withIdentifier: "ProfileTableViewCell") as! ProfileTableViewCell
return cell
case .options:
let cell = tableView.dequeueReusableCell(withIdentifier: "ProfileTableViewCell") as! ProfileTableViewCell
cell.profileData = ProfileOptionViewModel(rawValue: indexPath.row)
return cell
}
}
Note that followAndFollowings
returns a cell without data. And TableSection.Options.rawValue
is 2 but you have 3 sections so it's fine to hard code the return value
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
Is there a way to not return a cell after a condition in UITableView?
I am afraid that the only acceptable solution is to do that:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Here is where I add the code to calculate which cells should appear, though it's not important for this example
if condition {
return cell
}
// return empty cell
return UITableViewCell()
}
Related Topics
How to Add a Border Just on the Top Side of a Uiview
Uiscrollview Scroll to Bottom Programmatically
How to Ignore Touch Events and Pass Them to Another Subview'S Uicontrol Objects
Arm64 Architecture in Xcode 5.1
Swift 3.1 Deprecates Initialize(). How to Achieve the Same Thing
Swift Convert Unix Time to Date and Time
Interface Builder: What Are the Uiview's Layout iOS 6/7 Deltas For
How to Programmatically Connect to a Wifi Network Given the Ssid and Password
How to Make Drawrect Work Right Now
Ld: File Not Found: Linker Command Failed with Exit Code 1
Cut Transparent Hole in Uiview
Xcode 9 Gm - Wkwebview Nscoding Support Was Broken in Previous Versions
Determine If Mkmapview Was Dragged/Moved
Passing Data Between View Controllers Using Segue
How to Segue Programmatically in iOS Using Swift
Change Default Scrolling Behavior of Uitableview Section Header