Want to get the calculated value from all rows - ios

I have a table consist of more than 20 rows and each row has 3 text field named Rate, minutes and total. calculation is as rate/60 * minutes = total. I want to get total of all 20 rows in another text field Balance that is not a part of table view cell but of view controller. I want to calculate the value in real time and get the addition of total text field named as Rupees Text field below table view cell enter image description here.I can see on 3 rows on screen and 17 other are down. I get for only 3 text field in row not for all. I h have written this code but can calculate for 3 rows not for all 20. Please do check Thanks in advance. second issue I have used notification to pass string and it send me the last value in string not the updated one . Please do check the image
import UIKit
class calculationTVC: UITableViewCell, UITextFieldDelegate{
var numberOfItems = 0
var myTV : UITableView!
#IBOutlet weak var minutes: UITextField!
#IBOutlet weak var total: UITextField!
#IBOutlet weak var rate: UITextField!
#IBAction func rateChanged(_ sender: UITextField) {
// print(minutes.text, total.text, rate.text)
ratesischanged()
}
public func ratesischanged(){
let first = Double(rate.text!)
let second = Double(minutes.text!)
let third = Double(0)
if minutes.text?.count == 0{
total.text = "\(third)"
}
if minutes.text?.count == 0{
// print("null")
total.text = "\(third)"
// print("got zero")
}else{
let output = Double((first!/60) * second!)
total.text = "\(output)"
let rows = myTV.numberOfRows(inSection: 0)
var add : Double!
var c = [Int]()
for i in 0..<rows{
let path = IndexPath(row: i, section: 0)
let cell = myTV.cellForRow(at: path) as? calculationTVC
add = (cell?.total.text as NSString?)?.doubleValue
// print(Int(add))
//print(add)
if add != nil{
c += [Int(add)]
// print(c)
}
}
var sum = 0
var counter = 0
// Enter your code below
while counter < c.count {
var newValue = c[counter]
sum += newValue
counter += 1
// print(sum, "sum")
}
var myString = String(describing: sum)
NotificationCenter.default.post(name: calculationScreen.notificationName, object: nil, userInfo: ["DataMy": myString ?? ""])
//print(ar, "new ar")
}
}
func numberOfRows(numberInt : Int,tableView : UITableView){
numberOfItems = numberInt
myTV = tableView
}
}

you can define protocol on tableViewCell and fire it when the UITextField on each cell modified, and in your viewController implement of delegate:
protocol TableViewCellDelegate: class {
func textViewValueChanged(minutes: String, rate: String, total: String)
}
class calculationTVC: UITableViewCell { // delete UITextFieldDelegate
weak var delegate: TableViewCellDelegate?
// ... the rest of your code
#IBAction func textFieldEditingChanged(_ sender: UIButton) { //action of ***Editing Changed*** and connected to all *UITextField*
//calculate total
delegate?.textViewValueChanged(minutes: self.minutes, rate: self.rate, total: self.total)
}
}
class viewController: UIViewController, UITableView, UITableViewDelegate, UITableViewdataSource, TableViewCellDelegate { //and what you want to implement
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: IndexPath) as? calculationTVC
cell.delegate = self
// ... the rest of your code
return cell
}
func textViewValueChanged(minutes: String, rate: String, total: String) {
var total = 0
for i in 1...20 {
let cell = tableView.cellForRow(at: i) as? calculationTVC
total += cell.rate/60 * cell.minutes
}
//set your totalLabel
}
}

Related

Updating label in UITableViewCell with UIStepper in Swift

I'm a Swift beginner and I'm trying to make a simple app for ordering food. The user could add a new order by setting food name, price and serving. After adding an order, that order will be shown on the tableView as a FoodTableViewCell, and the user could change the serving with an UIStepper called stepper in each cell. Each order is a FoodItem stored in an array called foodList, and you can see all orders listed in a tableView in ShoppingListVC.
My problem is: When I press "+" or "-" button on stepper, my servingLabel doesn't change to corresponding value. I tried to use NotificationCenter to pass serving value to stepper, and store new value back to food.serving after stepperValueChanged with delegate pattern. However, there still seems to be some bugs. I've been kind of confused after browsing lots of solutions on the Internet. Any help is appreciated.
Update
I removed NotificationCenter and addTarget related methods as #Tarun Tyagi 's suggestion. Now my UIStepper value turns back to 1 whereas the servingLabels are showing different numbers of serving. Since NotificationCenter doesn't help, how can I connect the label and stepper value together? Is it recommended to implement another delegate?
Here are my codes(Updated on July 8):
FoodItem
class FoodItem: Equatable {
static func == (lhs: FoodItem, rhs: FoodItem) -> Bool {
return lhs === rhs
}
var name: String
var price: Int
var serving: Int
var foodID: String
init(name: String, price: Int, serving: Int) {
self.name = name
self.price = price
self.serving = serving
self.foodID = UUID().uuidString
}
}
ViewController
import UIKit
class ShoppingListVC: UIViewController, UITableViewDataSource, UITableViewDelegate {
var foodList = [FoodItem]()
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
...
for i in 1...5 {
let testItem = FoodItem(name: "Food\(i)", price: Int.random(in: 60...100), serving: Int.random(in: 1...10))
self.foodList.append(testItem)
}
}
// MARK: - Table view data source
...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "foodCell", for: indexPath) as! FoodTableViewCell
let food = foodList[indexPath.row]
cell.nameLabel.text = food.name
cell.priceLabel.text = "$\(String(food.price)) / serving"
cell.servingLabel.text = "\(String(food.serving)) serving"
cell.stepper.tag = indexPath.row
cell.delegate = self
return cell
}
}
// MARK: - FoodTableViewCellDelegate Method.
extension ShoppingListVC: FoodTableViewCellDelegate {
func stepper(_ stepper: UIStepper, at index: Int, didChangeValueTo newValue: Double) {
let indexPath = IndexPath(item: index, section: 0)
guard let cell = tableView.cellForRow(at: indexPath) as? FoodTableViewCell else { return }
let foodToBeUpdated = foodList[indexPath.row]
print("foodToBeUpdated.serving: \(foodToBeUpdated.serving)")
foodToBeUpdated.serving = Int(newValue)
print("Value changed in VC: \(newValue)")
cell.servingLabel.text = "\(String(format: "%.0f", newValue)) serving"
}
}
TableViewCell
import UIKit
protocol FoodTableViewCellDelegate: AnyObject {
func stepper(_ stepper: UIStepper, at index: Int, didChangeValueTo newValue: Double)
}
class FoodTableViewCell: UITableViewCell {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var priceLabel: UILabel!
#IBOutlet weak var servingLabel: UILabel!
#IBOutlet weak var stepper: UIStepper!
weak var delegate: FoodTableViewCellDelegate?
#IBAction func stepperValueChanged(_ sender: UIStepper) {
sender.minimumValue = 1
servingLabel.text = "\(String(format: "%.0f", sender.value)) serving"
// Pass the new value to ShoppingListVC and notify which cell to update using tag.
print("sender.value: \(sender.value)")
delegate?.stepper(stepper, at: stepper.tag, didChangeValueTo: sender.value)
}
override func awakeFromNib() {
super.awakeFromNib()
print(stepper.value)
}
}
Initially FoodTableViewCell is the ONLY target for UIStepper value changed (looking at #IBAction inside FoodTableViewCell).
When you dequeue a cell to display on screen, you call -
cell.stepper.addTarget(self, action: #selector(stepperValueChanged(_:)), for: .valueChanged)
which causes your ShoppingListVC instance to be added as an additional target every time a cellForRow call is executed.
Things to fix :
Remove all of your NotificationCenter related code from both classes.
Remove cell.stepper.addTarget() line as well.
This would give you a better idea of why it is happening this way. Update your question with these changes in case you still don't have what you want.
UPDATE
// Inside cellForRow
cell.stepper.value = food.serving
Cell Config:
protocol FoodTableViewCellDelegate: AnyObject {
func stepper(sender: FoodTableViewCell)
}
#IBAction func stepperButtonTapped(sender: UIStepper) {
delegate?.stepperButton(sender: self)
stepperLabel.text = "\(Int(countStepper.value))"
}
Controller Config:
cellForRow:
cell.countStepper.value = Double(foodList[indexPath.row].serving);
cell.stepperLabel.text = "\(Int(cell.countStepper.value))"
Delegate Method:
func stepperButton(sender: FoodTableViewCell) {
if let indexPath = tableView.indexPath(for: sender){
print(indexPath)
foodList[sender.tag].serving = Int(sender.countStepper.value)
}
}
Please check value stepper pod it will help you: Value stepper
Integrate value stepper pod and use below code for basic implementation.
import ValueStepper
let valueStepper: ValueStepper = {
let stepper = ValueStepper()
stepper.tintColor = .whiteColor()
stepper.minimumValue = 0
stepper.maximumValue = 1000
stepper.stepValue = 100
return stepper
}()
override func viewDidLoad() {
super.viewDidLoad()
valueStepper.addTarget(self, action: "valueChanged:", forControlEvents: .ValueChanged)
}
#IBAction func valueChanged1(sender: ValueStepper) {
// Use sender.value to do whatever you want
}
Its simplify custom stepper implantation.Take outlet of value stepper view in table tableview and use it.

Calculating sum until the indexPath.row instead of total using tableView

I had a question about calculation functions and I cant seem to understand the logic behind it yet as I just started to do coding in iOS about 3 months ago.
Here's a screenshot in the link and please take a look at it.
I would like to achieve results as explained Below
Expected Results : there will be more than 10000 cell of rows eventually, so my sum Cell will required to calculate based on the first index of the data instead of cell, I tried enumerated, mapping, for in loops but to no success
.
PLEASE PROVIDE CODE ALONG WITH YOUR EXPLANATION SO I CAN UNDERSTAND AS I AM NOT AN EXPERIENCED CODER
Example
UIVIEW
TotalBalance = $ 28.00 << Achieve by updateTotal()
TableView
TransactionType : $ 10.00 ($10.00) < this will sum cell 1 only as it is the first cell
TransactionType : $ 5.00 ($15.00) < this will sum cell 1 - 2 only
TransactionType : $ 3.00 ($18.00) < this will sum cell 1 - 3 only
TransactionType : $ 10.00 ($28.00) < this will sum cell 1 - 4 only
class Account: Object {
#objc dynamic var name : String = ""
#objc dynamic var balance : Double = 0
var ofTransaction = List<Transaction>()
}
class Transaction: Object {
#objc dynamic var name : String = ""
#objc dynamic var amount : Double = 0
var parentAccount = LinkingObjects(fromType: Account.self, property: "ofTransaction")
}
class AccountCell: UITableViewCell {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var amount: UILabel!
#IBOutlet weak var sum: UILabel!
}
func updateTotal() {
let total = getTransactions
.map { $0.amount }
.reduce(0, +)
let totalFormatter = NumberFormatter()
totallabel.text = totalFormatter.string(for: total)!
}
override func viewDidLoad() {
super.viewDidLoad()
account = realm.objects(Account.self)
getTransactions = realm.objects(Transaction.self)
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! AccountCell
if let transCell = getTransactions?[indexPath.row] {
cell.name.text = transCell.name
cell.amount.text = "\(transCell.amount)"
///Wrong Logic : This logic updates the Sum to Total !
let sumCell = getTransactions
.map { $0.amount }
.reduce(0, +)
cell.sum.text = "\(sumCell)"
}
return cell
}
Use it like below-
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! AccountCell
if let transCell = getTransactions?[indexPath.row] {
cell.name.text = transCell.name
cell.amount.text = "\(transCell.amount)"
//Correct calculation in Loops
var sumUp = 0.0
for (index,trans) in getTransactions.enumerated() {
if (index == indexPath.row) { break }
sumUp += trans.amount
cell.sum.text = "\(sumUp)"
}
}
return cell
}

text field become blank when table View Scrolled in two Section Swift

here is a table View with two Different Section Inside VC2 to Modify or add Contact into phone . the problem it is text fields become blank in Sections when table view scrolled . i found a way to fix this Problem in section 1 but i cant Handle section 2 .
Model :
class ContactModel : NSObject {
var identifier : String!
var thumbnailImageData : UIImage?
var givenName : String!
var familyName : String!
var phoneNumbers : [String]!
var emailAddresses : [String]!
override init() {
self.phoneNumbers = []
self.emailAddresses = []
super.init()
}
VC2 :
var contactModel = ContactModel()
#IBOutlet weak var tvInsert: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell0 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell0") as! InsertTableCell0
cell0.txtFirstName.text = self.contactModel.givenName
cell0.txtLastName.text = self.contactModel.familyName
return cell0
}else if indexPath.section == 1 {
let cell1 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell1") as! InsertTableCell1
cell1.btnDelete.addTarget(self, action: #selector(deleteRowDate(_:)), for: .touchUpInside)
cell1.txtPhoneNumber.placeholder = "Phone Number"
cell1.txtPhoneNumber.text = contactModel.phoneNumbers[indexPath.row]
cell1.txtPhoneNumber.delegate = self
cell1.txtPhoneNumber.tag = indexPath.row
return cell1
}else {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell2") as! InsertTableCell2
cell2.btnEmail.addTarget(self, action: #selector(deleteRowDate(_:)), for: .touchUpInside)
cell2.txtEmail.placeholder = "Email"
cell2.txtEmail.text = contactModel.emailAddresses[indexPath.row]
cell2.txtEmail.delegate = self
cell2.txtEmail.tag = indexPath.row
return cell2
}
}
func textFieldDidEndEditing(_ textField: UITextField) {
if let aText = textField.text {
self.contactModel.phoneNumbers[textField.tag] = aText
}
}
Seems like all the fields delegates are self and textFieldDidEndEditing is setting data for all the fields instead of phone number fields.
you have to check if the textField is phone number or not and also you should update the data in model when textField text is changed instead of end editing.
Easier solution will be :- Remove this line "cell1.txtPhoneNumber.delegate = self"
Replace var phoneNumbers: [String]! in model with following
var phoneNumbers = ["","",""] //for 3 phone numbers
Put this code in cellForRow of the particular cell i.e (indexPath.section == 1) for the above question
//Saved Phone number in model
cell.txtPhoneNumber.text = contactModel.phoneNumbers[indexPath.row]
//Get and save Phone number when changed
cell.txtPhoneNumber.tag = indexPath.row
cell.txtPhoneNumber.addTarget(self, action: #selector(self.phoneNumberChanged(_:)), for: .editingChanged)
In the ViewController
#objc func phoneNumberChanged(_ sender: UITextField){
//Phone number changed
contactModel.phoneNumbers[sender.tag] = sender.text ?? ""
}
In case you want to save the phone number on end Editing replace .editingChanged with .editingDidEnd

Disabling half of a UIStepper

I have a set of steppers than when added up they're supposed to give an X-amount. They're all in a UICollectionview and I used delegates to pass values between them and the ViewController.
You're supposed to allocate points among different players, once you reach the total number of points you were given to allocate you can no longer "add" points. I want to disable "half" of the stepper once the total number of points is reached. How can I do this? (without disabling the whole stepper, since the user might want to re-allocate points and return some of its points back).
Here's my code so far:
protocol CollectionVCDelegate: class {
func usedPoints() -> Int
func returnPoints() -> Int
}
class PointAllocationVC: UIViewController, CollectionVCDelegate {
func usedPoints() -> Int {
pointsToAllocate -= 1
totalPointsLabel.text = String(pointsToAllocate)
return pointsToAllocate
}
func returnPoints() -> Int
{
pointsToAllocate += 1
totalPointsLabel.text = String(pointsToAllocate)
return pointsToAllocate
}
var pointsToAllocate: Int = 5 //may change, 5 for example
#IBOutlet weak var ptsAllocView: UIView!
#IBOutlet weak var totalPointsLabel: UILabel!
#IBOutlet weak var addAllButton: UIButton!
#IBOutlet weak var ptAllocCollectionView: UICollectionView!
}
extension PointAllocationVC: UICollectionViewDelegate, UICollectionViewDataSource
{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return currentPlayers.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let myptCell = collectionView.dequeueReusableCell(withReuseIdentifier: "ptsCell", for: indexPath) as! PtsAllocationViewCell
myptCell.playerNameLabel.text = currentPlayers[indexPath.row]
myptCell.playerScoreLabel.text = "Score: \(currentScore[indexPath.row])"
myptCell.delegate = self
if indexPath.row == 0
{
myptCell.ptsAllocStepper.minimumValue = 0
}
else
{
myptCell.ptsAllocStepper.maximumValue = 0
myptCell.isSelf = false
}
return myptCell
}
}
Now, here's the code for the ViewCells:
import UIKit
class PtsAllocationViewCell: UICollectionViewCell {
var delegate: CollectionVCDelegate? = nil
var isSelf = true
var ptsRemaining: Int = 0
#IBOutlet weak var ptsLabel: UILabel!
#IBOutlet weak var playerNameLabel: UILabel!
#IBOutlet weak var playerScoreLabel: UILabel!
#IBOutlet weak var ptsAllocStepper: UIStepper!
#IBAction func stepperTapped(_ sender: UIStepper) {
let myInt: Int = Int(ptsLabel.text!)!
if delegate != nil
{
if isSelf
{
if myInt > Int(sender.value)
{
ptsRemaining = (delegate?.returnPoints())!
}
else
{
ptsRemaining = (delegate?.usedPoints())!
}
}
else
{
if myInt > Int(sender.value)
{
ptsRemaining = (delegate?.usedPoints())!
}
else
{
ptsRemaining = (delegate?.returnPoints())!
}
}
}
ptsLabel.text = String(Int(sender.value))
}
}
NOTE: This code works so far as much as I want it to (as far as adding/subtracting from the ViewController pointsToAllocate and updating labels and all. However, as of now there are no locks preventing the user form over-usings points (say he can put 5 on each and have a total of -15 points at the end, you shouldn't be able to go below 0)
and just for added clarity here's a picture, note it will have around 4 - 6 different "players":
Set all the steppers' maximumValue to the total number of points, minus the points that were already allocated each time when a stepper's value changes. You should observe UIControlEvents.valueChanged for that.
That way, the stepper's + half will be disabled if you reach the maximum amount of points.
You probably cannot "disable the + side"...
Options:
Use two buttons, instead of a stepper. Disable the "+" button as desired, or
Set the Increment Image to indicate it's disabled when you want to disable it, and just don't process the "+" taps.
Each side of the UIStepper will be automatically disabled when it reaches its min or max value. See the answer from #the4kman

(Swift) How to (animate) show/hide cells based on UITextfield input by reloading a UITableView?

I'm a beginning iOS developer and I've been stuck on an issue for quite some time now.
Background: I have a single viewcontroller with a tableview. It holds 4 dynamic prototype cells: prototypecell 1 has an UITextField and a couple of labels, prototypecell 2 has an image, prototypecell 3 and 4 only have a single label. (Note: prototype cell 4 is based on an array in the object and can have 1 or more cells)
Upon opening the screen, only the first cell with the UITextField should be visible. When an user enters a number (max. 3 digits) in this UITextField, the number has to be compared to check if it is an existing number in an array of objects. If this number proves correct, 2 things will have to happen:
The labels in the first cell will need to change layout (colour,
font, size, ...). And the first cell changes rowHeight.
The other 3 cells will have to appear and show data that corresponds to the number.
If the number is wrong, no extra cells appear and the first cell updates to tell the user it was incorrect.
Problem: I'm having issues with animating the way the 3 cells appear and disappear based on the numberinput in the first cell. More specifically the method "toggleCellsVisibility" and how it relates to the creation of the cells.
I tried multiple combinations of: beginUpdates(), endUpdates(), reloadData(), reloadRowsAtIndexPath(), DispatchQueue.main.async {} and UIView.Animate(). But the only way my code works is if I implement the toggleCellsVisibility method as below, which does not give me any animation options.
I seem to be doing something wrong with the creation and reloading of the data. I think this is related to the use of the global variables indexOfObject and tempObject which hold dummy data when the screen is loaded, and are then shown and overridden with the actual data when a correct number is given.
Summary: Could I somehow insert/create the 3 cells when a correct number is inputted in the first cell, while also animating this change with this particular setup?
Additional:
Can I show/hide the extra cells by not using the heightForRowAtIndexPath? It would be better if the cells could self-size.
I selected and simplified the relevant pieces of code:
1) TableView Class:
class TableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, updateUITableView {
var objects: [Object] = [
name: "test1", number: "test2", image: "imageName1", color: UIColor.black, array: ["test3", "test4"],
[name: "test1", number: "test2", image: "imageName2", color: UIColor.white, array: ["test3", "test4", "test5"]
//...
]
var cellsRowHeight = false
var indexOfObject: Int = 0
var tempObject = Object[name: "test1", number: "test2", color: UIColor.blue, image: "imageName3", array: ["test3"]]
#IBOutlet var tableView: UITableView!
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let numberOfRows = 3 + tempObject.subArray.count
return numberOfRows
}
//START - Input received from textfield in first cell
func checkNumberInput(senderCell: SearchInputTableViewCell, number: String) {
// step 1: Check if number exists
let match = checkNumberMatch(numberInput: number)
// step 2: Change lay-out of input cell
senderCell.changeLayout(numberMatch: match.0, name: match.1?.name, color: match.1?.color)
// step 3: Show/hide cells
toggleCellsVisibility(numberMatch: match.0)
}
//STEP 1: Check if the number corresponds to an existing number
func checkNumberMatch(numberInput: String) -> (Bool, Object?) {
var returnObject: Object?
var tuple = (false, returnObject)
for (index, object) in objects.enumerated() where object.number == numberInput {
returnObject = object
tuple = (true, returnObject)
tempObject = object
indexOfObject = index
}
return tuple
}
//STEP 3 = !!PROBLEM!!
func toggleCellsVisibility(numberMatch: Bool) {
cellsRowHeight = numberMatch
// if/else because of additional future implementation
if numberMatch == true { //Cells appear
DispatchQueue.main.async {
self.tableView?.reloadData()
}
} else { //Cells disappear
DispatchQueue.main.async {
self.tableView?.reloadData()
}
}
}
//STEP 4:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
switch (indexPath.row) {
case 0 where !cellsRowHeight:
return 187
case 0 where cellsRowHeight:
return 170
case 1 where !cellsRowHeight:
return 0
case 1 where cellsRowHeight:
return 170
case 2 where !cellsRowHeight:
return 0
case 2 where cellsRowHeight:
return 54
case 3...200 where !cellsRowHeight:
return 0
case 3...200 where cellsRowHeight:
return 44
default:
return 44
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cellIdentifier = "InputCell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! InputCell
cell.delegate = self
return cell
}
else if indexPath.row == 1 {
let cellIdentifier = "Cell2"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! Cell2
cell.image?.image = UIImage(named: objects[indexOfObject].image)
return cell
}
else if indexPath.row == 2 {
let cellIdentifier = "Cell3"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! Cell3
cell.name?.text = objects[indexOfObject].name
return cell
}
else {
let cellIdentifier = "Cell4"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! Cell4
cell.name?.text = objects[indexOfObject].subArray[(indexPath as IndexPath).row - 3]
return cell
}
}}
2) Cell Class:
protocol updateUITableView: class {
func checkNumberInput(senderCell: SearchInputTableViewCell, number: String)
}
class InputCell: UITableViewCell, UITextFieldDelegate {
var delegate: updateUITableView?
#IBOutlet var textField: UITextField!
#IBOutlet var nameLabel: UILabel!
//... and other labels
func changeLayout(numberMatch: Bool, name: String?, color: UIColor?) {
if numberMatch == true {
//lay-out changes to labels
}
else {
//lay-out changes to labels
}
}
//Set maximum character limit in textField and dismiss keyboard when character limit (3) is reached.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let currentCharacterCount = textField.text?.characters.count ?? 0
let newLength = currentCharacterCount + string.characters.count - range.length
if (newLength == 3) {
textField.text = (textField.text! as NSString).replacingCharacters(in: range, with: string)
//Get text from textField
let numberInput: String? = textField.text! //Get number if 3 characters entered
if numberInput != nil {
delegate?.checkNumberInput(senderCell: self, number: numberInput!)
}
textField.resignFirstResponder()
if (range.length + range.location > currentCharacterCount) {
return false
} else {
return true
}
}
return true
}
}
class Cell2: UITableViewCell {
#IBOutlet var image: UIImageView!
}
class Cell3: UITableViewCell {
#IBOutlet var name: UILabel!
}
class Cell4: UITableViewCell {
#IBOutlet var name: UILabel!
}
Any help would be immensely appreciated! Thank you!
When your action is done (checking that the input match whatever you want), populate the data source you're using for your tableview (you should declare an empty array of objects you want to use as a datasource, and use this), then use reloadData() on your tableview.
For the height of your cells, you can use tableView.rowHeight = UITableViewAutomaticDimension (https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithSelf-SizingTableViewCells.html)

Resources