Allow me to provide some context. I have a UITableViewCell that contains an EditText and a Button. This cell is then inserted into the self.tableView.tableHeaderView
property of the table to achieve the following result:
Below is my implementation for the view controller:
class ViewController: UITableViewController {
var data = ["Apple", "Apricot"] as NSMutableArray
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Testing"
createHeader()
}
func createHeader(){
let headerViewCell = NSBundle.mainBundle().loadNibNamed("InputToListCell", owner: nil, options: nil)[0] as! InputToListCell
headerViewCell.setTableViewWithData(self,data: data)
self.tableView.tableHeaderView = headerViewCell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("rowCell", forIndexPath: indexPath)
cell.textLabel?.text = data[indexPath.row] as? String
return cell
}
}
Here is my implementation for the UITableViewCell that is inserted into the table:
class InputToListCell: UITableViewCell {
@IBOutlet weak var inputEditText: UITextField!
var tableViewController: ViewController!
var arrayForTable: NSMutableArray!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func setTableViewWithData(inputTableViewController:ViewController, data:NSMutableArray){
tableViewController = inputTableViewController
arrayForTable = data
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
@IBAction func addValueToArray(sender: AnyObject) {
let inputFromEditText = inputEditText.text!
arrayForTable.addObject(inputFromEditText)
tableViewController.data = arrayForTable
tableViewController.tableView.reloadData()
tableViewController.createHeader()
}
}
I have just started with iOS development and I dont have access to a senior developer to review my code to see if things could be improved or done in a better/best practices sort of way. Any help or suggestions would be great.
1 Answer 1
Random Fixes
You don't need to pre-pend with self in self.title = "Testing" or self.tableView.
var data = ["Apple", "Apricot"] as NSMutableArray
This doesn't need to be declared as an NSMutableArray. Swift defines a mutable array like this var data = ["Apple", "Apricot"] and if you wanted it to be non-mutable, then declare it with let
Remove the functions that Xcode auto populated your code with if you aren't actually doing something in them. This includes didReceiveMemoryWarning, awakeFromNib, and setSelected.
Subclassing
I think you're incorrectly labeling the parts of a UITableView in your description. Going by your comp, the UITextField and Add button are contained inside a tableHeaderView. This shouldn't be subclassed as a UITableViewCell - if you look at the documentation for the tableHeaderView property of a UITableView you'll see its a UIView. Let's just rename the InputToListCell as InputToListView and change it to a UIView.
Passing Data From the Header View to the TableView
As a general rule in iOS, a view that is a component of a larger system shouldn't know anything about nor should it be able to control that larger system. Here, the component is the InputToListView and its parent is the UITableView. The InputToListView shouldn't have an array of its own. When it is declared in the ViewController, its button property should add a selector that is called inside the ViewController. Delete both tableView and array properties from it.
func createHeader(){
headerView = NSBundle.mainBundle().loadNibNamed("InputToListView", owner: nil, options: nil) as! InputToListView
// delete the next line - the cell shouldn't need to know anything about what the table view has or doesn't have
// the tableview already has its own array that it is using as its source of data
//headerViewCell.setTableViewWithData(self,data: data)
tableView.tableHeaderView = headerViewCell
headerView.button.addTarget(self, action: "addButtonPressed", forControlEvents: UIControlEvents.TouchUpInside)
}
func addButtonPressed() {
// 1 access the headerView's textField property
// 2 check to see if the the textField has text by unwrapping it and if it has characters to display in the table view
// 3 add that text to the tableView's data array
// 4 either insert a new row into the tableView (preferred) or reload the tableView (messy)
}
Notice that the headerView should be a property of the ViewController. That way you can access its textView property to use its text to add to the ViewController's array. Conversely, you can declare a callback closure in the addButtonPressed: function of the header view and pass in the textView's text.