swift insert new static cells tableview - ios

want to add new cells. how can i do this?
please help!
i try
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 1 {
return 3 + eventDates.count
} else {
return super.tableView(tableView, numberOfRowsInSection: section)
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if (indexPath.section == 0 && indexPath.row == 1) {
eventDaysVisible = !eventDaysVisible
tableView.reloadData()
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: eventDates.count + 3, inSection: 0)], withRowAnimation: .Automatic)
tableView.reloadData()
}
for day in eventDates {
print("OBJ: \(day)")
}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
i have 3 static cells and the new cells needs to insert after the first if i switch a button.
var eventdates = Friday, Saturday, Sunday
hope you can help me with that.

import UIKit
class ViewController: UIViewController {
var cellCount = 1
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController:UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellCount
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.backgroundColor = UIColor.grayColor()
return cell
}
func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let eventDates = ["1", "2", "3"]
var indexPathsArray = [NSIndexPath]()
for rowCount in 0 ..< eventDates.count {
indexPathsArray.append(NSIndexPath(forRow: rowCount, inSection: 0))
cellCount += 1
}
tableView.beginUpdates()
tableView.insertRowsAtIndexPaths(indexPathsArray, withRowAnimation: .Automatic)
tableView.endUpdates()
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}

Related

How can I call a tableview delegate methods from one class to another class in swift?

I want to perform a drop down for each cell hence I have inserted a tableview with in a cell and I am working with the expanding cell that a cell gets expanded when it clicks, so that it will show as a dropdown.
MainTableView:
import UIKit
class MainTableView: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var mainTableView: UITableView!
var selectedCellIndexPath: NSIndexPath?
let selectedCellHeight: CGFloat = 300.0
let unselectedCellHeight: CGFloat = 44.0
var name = ["red","green","blue","white"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return name.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = mainTableView.dequeueReusableCellWithIdentifier("cell1" , forIndexPath: indexPath) as! mainTableViewCell
cell.Title.text = name[indexPath.row]
return cell
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if selectedCellIndexPath == indexPath {
return selectedCellHeight
}
return unselectedCellHeight
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if selectedCellIndexPath != nil && selectedCellIndexPath == indexPath {
selectedCellIndexPath = nil
} else {
selectedCellIndexPath = indexPath
}
tableView.beginUpdates()
tableView.endUpdates()
if selectedCellIndexPath != nil {
// This ensures, that the cell is fully visible once expanded
tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .None, animated: true)
}
}
}
MainTableViewCell:
import UIKit
class MainTableViewCell:UITableViewCell,UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var dropDownList: UITableView!
#IBOutlet weak var Title: UILabel!
var selectedCellIndexPath: NSIndexPath?
let selectedCellHeight: CGFloat = 0.0
let unselectedCellHeight: CGFloat = 44.0
var name = ["magenta","yellow","orange","cyan","black","grey"]
override func awakeFromNib() {
super.awakeFromNib()
dropDownList.delegate = self
dropDownList.dataSource = self
}
override func setSelected(selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return name.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = dropDownList.dequeueReusableCellWithIdentifier("cell2", forIndexPath: indexPath) as! subTableViewCell
cell.subTitle.text = name[indexPath.row]
return cell
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if selectedCellIndexPath == indexPath {
return selectedCellHeight
}
return unselectedCellHeight
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
/* If I select any row in subTableView then the tableview has to disappear and the height of mainTableView row should be rearranged(i.e the dropdown should dissappear) */
}
InnerTableViewCell:
import UIKit
class subTableViewCell: UITableViewCell {
#IBOutlet weak var subTitle: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
If I call the mainTableView delegate methods in the mainTableViewCell class then it would be easy but I am getting struggle with this .Help me!
First Create a delegate method to cell :-
import UIKit
protocol MainTableViewCellDelegate {
func myFunc()
}
class MainTableViewCell:UITableViewCell,UITableViewDataSource,UITableViewDelegate {
var MainTableViewCellDelegate! = nil
// Put Your Other code Lines
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
delegate.myFunc()
}
}
Then in your MainTableView add MainTableViewCellDelegate :-
import UIKit
class MainTableView: UIViewController,UITableViewDelegate,UITableViewDataSource, MainTableViewCellDelegate {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = dropDownList.dequeueReusableCellWithIdentifier("cell2", forIndexPath: indexPath) as! subTableViewCell
cell.subTitle.text = name[indexPath.row]
cell.delegate = self
return cell
}
func myFunc() {
self.performSegueWithIdentifier("yourSegueIdentifier", sender: nil) //Put your segue
}
}

After reordering cell is behind another cell

I'm trying to create a reorder indicator. So what I'm trying to do is that when the user is dragging the cell. That on the place the user wants to drop the cell an other cell is added with a background. I already achieved that. But when the user drops the cell, the indicator cell needs to be deleted and the table must stay the same like the user intended to.
Now I have the following problem. When the user drops the cell. The indicator cell is correctly removed but the dropped cell is behind another cell suddenly.
Screenshots to clarify:
My code:
import UIKit
import PureLayout
class ViewController: UIViewController {
lazy var tableView: UITableView = {
let tableView = UITableView(forAutoLayout: ())
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .SingleLine
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Default")
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Indicator")
tableView.tableFooterView = UIView()
return tableView
}()
private var data: [Int] = [Int]()
private var isIndicatorRowAddedInSection: Bool = false
private var lastIndicatorRowIndexPath: NSIndexPath?
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.tableView)
self.tableView.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsetsZero, excludingEdge: .Top)
self.tableView.autoPinEdgeToSuperviewEdge(.Top, withInset: 40)
for index in 0..<20 {
data.append(index)
}
self.tableView.editing = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController: UITableViewDelegate {
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 44
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
}
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
if let lastIndexPath = self.lastIndicatorRowIndexPath {
print("Need to delete a row on section \(lastIndexPath.section) row \(lastIndexPath.row)")
self.isIndicatorRowAddedInSection = false
self.lastIndicatorRowIndexPath = nil
tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths([lastIndexPath], withRowAnimation: .Fade)
tableView.endUpdates()
}
let itemToMove = self.data[fromIndexPath.row]
self.data.removeAtIndex(fromIndexPath.row)
self.data.insert(itemToMove, atIndex: toIndexPath.row)
}
func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return .None
}
func tableView(tableView: UITableView, shouldIndentWhileEditingRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath,
toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath {
if let lastIndexPath = self.lastIndicatorRowIndexPath {
print("Target indexpath indexpath to delete row \(lastIndexPath.section) row \(lastIndexPath.row)")
self.isIndicatorRowAddedInSection = false
tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths([lastIndexPath], withRowAnimation: .Fade)
tableView.endUpdates()
self.lastIndicatorRowIndexPath = nil
}
self.isIndicatorRowAddedInSection = true
self.lastIndicatorRowIndexPath = proposedDestinationIndexPath
tableView.beginUpdates()
print("Indicator view inserted at section \(proposedDestinationIndexPath.section) row \(proposedDestinationIndexPath.row)")
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: proposedDestinationIndexPath.row, inSection: proposedDestinationIndexPath.section)], withRowAnimation: .Automatic)
tableView.endUpdates()
return proposedDestinationIndexPath
}
}
extension ViewController: UITableViewDataSource {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.isIndicatorRowAddedInSection {
return self.data.count + 1
}
return self.data.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let indicatorIndexPath = self.lastIndicatorRowIndexPath where isIndicatorRowAddedInSection {
if indicatorIndexPath.section == indexPath.section && indicatorIndexPath.row == indexPath.row {
let cell = tableView.dequeueReusableCellWithIdentifier("Indicator", forIndexPath: indexPath)
return cell
}
}
let cell = tableView.dequeueReusableCellWithIdentifier("Default", forIndexPath: indexPath)
cell.textLabel?.text = String(self.data[indexPath.row])
return cell
}
}
I don't see the problem. Can someone help me?
I found the problem. In the moveRow it is executed on Thread 1 (main thread) but it seems like it's not. Because when you wrap it with a dispatch async to the main thread it just works.
Full working code:
import UIKit
import PureLayout
class ViewController: UIViewController {
lazy var tableView: UITableView = {
let tableView = UITableView(forAutoLayout: ())
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .SingleLine
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Default")
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Indicator")
tableView.tableFooterView = UIView()
return tableView
}()
private var data: [Int] = [Int]()
private var isIndicatorRowAddedInSection: Bool = false
private var lastIndicatorRowIndexPath: NSIndexPath?
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.tableView)
self.tableView.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsetsZero, excludingEdge: .Top)
self.tableView.autoPinEdgeToSuperviewEdge(.Top, withInset: 40)
for index in 0..<5 {
data.append(index)
}
self.tableView.editing = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController: UITableViewDelegate {
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 44
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
}
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
let itemToMove = self.data[fromIndexPath.row]
self.data.removeAtIndex(fromIndexPath.row)
self.data.insert(itemToMove, atIndex: toIndexPath.row - 1)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
if let lastIndexPath = self.lastIndicatorRowIndexPath {
print("Need to delete a row on section \(lastIndexPath.section) row \(lastIndexPath.row)")
self.isIndicatorRowAddedInSection = false
self.lastIndicatorRowIndexPath = nil
tableView.beginUpdates()
// Need to put some logic if you pull to top it has to be + 1
tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: lastIndexPath.row - 1, inSection: 0)], withRowAnimation: .Fade)
tableView.endUpdates()
}
})
}
func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return .None
}
func tableView(tableView: UITableView, shouldIndentWhileEditingRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath,
toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath {
if let lastIndexPath = self.lastIndicatorRowIndexPath {
print("Target indexpath indexpath to delete row \(lastIndexPath.section) row \(lastIndexPath.row)")
self.isIndicatorRowAddedInSection = false
tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths([lastIndexPath], withRowAnimation: .None)
tableView.endUpdates()
self.lastIndicatorRowIndexPath = nil
}
self.isIndicatorRowAddedInSection = true
self.lastIndicatorRowIndexPath = proposedDestinationIndexPath
tableView.beginUpdates()
print("Indicator view inserted at section \(proposedDestinationIndexPath.section) row \(proposedDestinationIndexPath.row)")
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: proposedDestinationIndexPath.row, inSection: proposedDestinationIndexPath.section)], withRowAnimation: .Automatic)
tableView.endUpdates()
return proposedDestinationIndexPath
}
}
extension ViewController: UITableViewDataSource {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.isIndicatorRowAddedInSection {
return self.data.count + 1
}
return self.data.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let indicatorIndexPath = self.lastIndicatorRowIndexPath where isIndicatorRowAddedInSection {
if indicatorIndexPath.section == indexPath.section && indicatorIndexPath.row == indexPath.row {
let cell = tableView.dequeueReusableCellWithIdentifier("Indicator", forIndexPath: indexPath)
cell.textLabel?.text = "IndicatorView: ROW \(indexPath.row) SECTION = \(indexPath.section)"
print("Indictorview cell for row")
return cell
}
}
let cell = tableView.dequeueReusableCellWithIdentifier("Default", forIndexPath: indexPath)
cell.textLabel?.text = "ROW = \(indexPath.row) SECTION = \(indexPath.section)"
return cell
}
}

Expand and Collapse tableview cells

I'm able to expand and collapse cells but i wanna call functions (expand and collapse) inside UITableViewCell to change button title.
import UIKit
class MyTicketsTableViewController: UITableViewController {
var selectedIndexPath: NSIndexPath?
var extraHeight: CGFloat = 100
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! MyTicketsTableViewCell
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if(selectedIndexPath != nil && indexPath.compare(selectedIndexPath!) == NSComparisonResult.OrderedSame) {
return 230 + extraHeight
}
return 230.0
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if(selectedIndexPath == indexPath) {
selectedIndexPath = nil
} else {
selectedIndexPath = indexPath
}
tableView.beginUpdates()
tableView.endUpdates()
}
}
import UIKit
class MyTicketsTableViewCell: UITableViewCell {
#IBOutlet weak var expandButton: ExpandButton!
#IBOutlet weak var detailsHeightConstraint: NSLayoutConstraint!
var defaultHeight: CGFloat!
override func awakeFromNib() {
super.awakeFromNib()
defaultHeight = detailsHeightConstraint.constant
expandButton.button.setTitle("TAP FOR DETAILS", forState: .Normal)
detailsHeightConstraint.constant = 30
}
func expand() {
UIView.animateWithDuration(0.3, delay: 0.0, options: .CurveLinear, animations: {
self.expandButton.arrowImage.transform = CGAffineTransformMakeRotation(CGFloat(M_PI * 0.99))
self.detailsHeightConstraint.constant = self.defaultHeight
self.layoutIfNeeded()
}, completion: { finished in
self.expandButton.button.setTitle("CLOSE", forState: .Normal)
})
}
func collapse() {
UIView.animateWithDuration(0.3, delay: 0.0, options: .CurveLinear, animations: {
self.expandButton.arrowImage.transform = CGAffineTransformMakeRotation(CGFloat(M_PI * 0.0))
self.detailsHeightConstraint.constant = CGFloat(30.0)
self.layoutIfNeeded()
}, completion: { finished in
self.expandButton.button.setTitle("TAP FOR DETAILS", forState: .Normal)
})
}
}
If you want the cell to get physically bigger, then where you have your store IndexPath, in heightForRow: use:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if selectedIndexPath == indexPath {
return 230 + extraHeight
}
return 230.0
}
Then when you want to expand one in the didSelectRow:
selectedIndexPath = indexPath
tableView.beginUpdates
tableView.endUpdates
Edit
This will make the cells animate themselves getting bigger, you dont need the extra animation blocks in the cell.
Edit 2
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if(selectedIndexPath == indexPath) {
selectedIndexPath = nil
if let cell = tableView.cellForRowAtIndexPath(indexPath) as? MyTicketsTableViewCell {
cell.collapse()
}
if let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow:indexPath.row+1, section: indexPath.section) as? MyTicketsTableViewCell {
cell.collapse()
}
} else {
selectedIndexPath = indexPath
if let cell = tableView.cellForRowAtIndexPath(indexPath) as? MyTicketsTableViewCell {
cell.expand()
}
if let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow:indexPath.row+1, section: indexPath.section) as? MyTicketsTableViewCell {
cell.expand()
}
}
tableView.beginUpdates()
tableView.endUpdates()
}
All you need is implement UITableView Delegate this way:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
By default, estimatedHeight is CGRectZero, when you set some value for it, it enables autoresizing (the same situation with UICollectionView), you can do even also so:
tableView?.estimatedRowHeight = CGSizeMake(50.f, 50.f);
Then you need to setup you constraints inside your cell.
Check this post: https://www.hackingwithswift.com/read/32/2/automatically-resizing-uitableviewcells-with-dynamic-type-and-ns
Hope it helps)
In MyTicketsTableViewController class, inside cellForRowAtIndexPath datasource method add target for the button.
cell.expandButton.addTarget(self, action: "expandorcollapsed:", forControlEvents: UIControlEvents.TouchUpInside)
I tried to implement lots of the given examples on this and other pages with similar questions, but none worked for me since I had to perform some logic in my custom cell (eg. hide unneeded UILables in CustomCell.swift when the cell is collapsed).
Here is the implementation that worked for me:
Create a dictionary:
private var _expandedCells: [IndexPath:Bool] = [:]
Implement the heightForRowAt method:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return _expandedCells[indexPath] == nil ? 70 : _expandedCells[indexPath]! ? 150 : 70
}
Implement the didSelectRowAt method:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
_expandedCells[indexPath] = _expandedCells[indexPath] == nil ? true : !_expandedCells[indexPath]!
tableView.reloadRows(at: [indexPath], with: .fade)
}
Adjust your customCell:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let cell = cell as? YourCustomTableViewCell, let isExpanded = _expandedCells[indexPath] else { return }
cell.set(expanded: isExpanded)
}

Swift static tableview with dynamic section

I have tableviewcontroller, with 2 sections.
First(static) section have 2 rows, and second section should be dynamic.
Storyboard:
Code:
class DocumentInventoryChangeTableViewController: UITableViewController {
var results: [String] = ["Dog", "Cat", "Snake", "Test"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerNib(UINib(nibName: "DocumentInventoryCell", bundle: nil), forCellReuseIdentifier: "DocumentInventoryCell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 1 {
return results.count
}
return 2
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell!
if indexPath.section == 0 {
cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
} else {
cell = tableView.dequeueReusableCellWithIdentifier("DocumentInventoryCell", forIndexPath: indexPath)
cell.textLabel?.text = results[indexPath.row]
}
return cell
}
}
But i'm getting this error:
Terminating app due to uncaught exception 'NSRangeException', reason:
'*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty
NSArray'
In my experience, it was enough to override these methods in UITableViewController:
tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
tableView(tableView: UITableView, indentationLevelForRowAtIndexPath indexPath: NSIndexPath) -> Int
If you want to have custom table view cell in your table view, you need to crate subclass of UITableViewCell also with nib, and register it to your table view.
My whole controller looks like this:
var data = ["Ahoj", "Hola", "Hello"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerNib(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "reuseIdentifier")
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 1 {
return data.count
}
return super.tableView(tableView, numberOfRowsInSection: section)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.section == 1 {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as! CustomCell
cell.titleLabel.text = data[indexPath.row]
return cell
}
return super.tableView(tableView, cellForRowAtIndexPath: indexPath)
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 44
}
override func tableView(tableView: UITableView, indentationLevelForRowAtIndexPath indexPath: NSIndexPath) -> Int {
return 0
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
if indexPath.section == 1 {
print(data[indexPath.row])
}
}
#IBAction func addItem() {
data.append("Item \(data.count)")
tableView.beginUpdates()
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: data.count - 1, inSection: 1)], withRowAnimation: .Left)
tableView.endUpdates()
}
#IBAction func removeItem() {
if data.count > 0 {
data.removeLast()
tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: data.count, inSection: 1)], withRowAnimation: .Left)
tableView.endUpdates()
}
}
The problem is that there is no such thing as a table view where the "First(static) section have 2 rows, and second section should be dynamic." Your table view needs to be entirely dynamic; that is, it should show a prototype cell, not static contents, in the storyboard, and its entire contents should be configured in code, including the first section — even though the first section never changes.

unexpectedly found nil while unwrapping an Optional value in uitableviewcontroller

I get this error when I actually run the code (this line is the problem var cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(CellId) as UITableViewCell. THis is in a UITableViewController class.
import UIKit
class AlarmsTableViewController: UITableViewController {
var myData:Array<AnyObject> = []
override func viewDidLoad() {
myData = ["one", "two", "three", "four"]
}
override func didReceiveMemoryWarning() {
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myData.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellId:String = "Cell"
var cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(CellId) as UITableViewCell
//if let ip = indexPath {
cell.textLabel?.text = myData[indexPath.row] as? String
//}
return cell
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
//Delete row from data source
//if let tv = tableView? {
myData.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
}
}
}
In the interface builder, select the TableViewController with which you are working with. Then, select the prototype cell and set its style to "Basic". Finally, set the cells reuse identifier to Cell.

Resources