change image in Xcode Swift when row selected - iphone

My first Phone app in Xcode (7.3 and Swift 2). Spent weeks trying to change an image when a row is selected.
myImageView is a custom cell class (swift file) with the imageView outlet:
import UIKit
class myTableViewCell: UITableViewCell {
#IBOutlet weak var myCellLabel: UILabel!
#IBOutlet weak var myImageView: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
When a row is selected I want to replace the image but unable to reference the cell.myImageView.image{indexPath.row] = UIImage(named: “SquareGreen.png”)
This is OK
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! myTableViewCell
cell.myImageView.image = UIImage(named: "Square.png")
This does not work
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
myTableViewCell.myImageView.image[indexPath.row] = "SquareGreen.png"
cell.myImageView.image[indexPath.row] = UIImage(named: "SquareGreen.png")
// error “use of unresolved identifier cell”
}
any ideas?

This line is wrong:
myTableViewCell.myImageView.image[indexPath.row] = "SquareGreen.png"
change to:
let cell = tableView.cellForRowAtIndexPath(indexPath) as myTableViewCell
cell.myImageView.image = "SquareGreen.png"
The first problem was what Phillip Mills pointed out in the comments - you don't have a cell variable, you need to create one. The second problem was that to assign a new image to the myImageView property, you need to assign as my code shows above (image is not an array or a dictionary).

Related

How to open View Controller in Table View with Button by using Objc in Swift?

Stackoverflow
I know how to make a button in the table view cells with website links, rate, mail, and many things. However, How could I open the view controller with the instantiateViewController in the #Objc func's statements?
For example.
Create a new Table View Cell folder called FeedBackButtonsTableViewCell
class FeedBackButtonsTableViewCell: UITableViewCell {
#IBOutlet weak var ButtonCells: UIButton!
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
}
}
Let create a new view controller folder called
class FeedbackViewController: UIViewController {
#IBOutlet weak var TableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.navigationItem.title = "Feedback"
}
}
add the extension to calling the view controller to UITableViewDataSource and UITableViewDelegate and create a obj func statements inside of the second FeedbackViewController with UITableViewDataSource and UITableViewDelegate under the cells.
extension FeedbackViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
if indexPath.row == 1 {
buttonCell = TableView.dequeueReusableCell(withIdentifier: "ButtonCells") as? FeedBackButtonsTableViewCell
buttonCell?.ButtonCells.addTarget(self,action: #selector(LearnMore),for: .touchUpInside)
buttonCell?.ButtonCells.tag = indexPath.row
return buttonCell!
}
#objc func LearnMore() {
// How could I write to open the view controller with UIButton in the Table View Cells?
}
}
Thank you for bring a kind of help! :)
Simple solution could be to use procol.
protocol CellActionDelegate{
func didButtonTapped(index: Int)
}
Now confirm the protocol in FeedbackViewController. Take index and actionDelegate properties in your UITableViewCell subclass.
class FeedBackButtonsTableViewCell: UITableViewCell{
var actionDelegate: CellActionDelegate?
var index: Int?
.....
// Take Action of UIButton here
#IBAction func more(_ sender: Any) {
if let delegate = self.actionDelegate{
delegate.didButtonTapped(index!)
}
}
}
Now in your FeedbackViewController set actionDelegate & Corresponding index in
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {}
you can open anotherView controller from func didButtonTapped(index: Int) definition .
extension FeedbackViewController:CellActionDelegate{
func didButtonTapped(index: Int) {
let storybord = UIStoryboard(name: "Main", bundle: nil)
guard let controller = storybord.instantiateViewController(withIdentifier: "AnotherControllerIdentfier") as? AnotherViewController else{
fatalError("Could not finc another view controller")
}
self.present(controller, animated: true, completion: nil)
}
}
#objc func LearnMore() {
let viewController = FeedbackDetailsViewController()// creation of viewController object differs depends on how you fetch the UI, means either you are using storyboard or xib or directly making ui in code.
self.navigationController?.pushViewController(viewController, animated: true)
}

Tab Bar Item hidden behind tableview / not being shown?

I have an empty view with a tab bar pictured below, when i load a routine a table appears containing the contents, however it seems to overlay the tab bar killing off app navigation. Its not sized in the storyboard to overlay it and its constraint locked to not do so, so im unsure why this is happening, pics of the issue and VC's code below:
VC Code:
import Foundation
import UIKit
import CoreData
class RoutineController: UIViewController, UITableViewDataSource, UITableViewDelegate {
// MARK: - DECLARATIONS
#IBAction func unwindToRoutine(segue: UIStoryboardSegue) {}
#IBOutlet weak var daysRoutineTable: UITableView!
#IBOutlet weak var columnHeaderBanner: UIView!
#IBOutlet weak var todaysRoutineNavBar: UINavigationBar!
#IBOutlet weak var addTOdaysRoutineLabel: UILabel!
let date = Date()
let dateFormatter = DateFormatter()
let segueEditUserExerciseViewController = "editExerciseInRoutineSegue"
//This is the selected routine passed from the previous VC
var selectedroutine : UserRoutine?
// MARK: - VIEWDIDLOAD
override func viewDidLoad() {
super.viewDidLoad()
setupView()
daysRoutineTable.delegate = self
daysRoutineTable.dataSource = self
view.backgroundColor = (UIColor.customBackgroundGraphite())
dateFormatter.dateStyle = .short
dateFormatter.dateFormat = "dd/MM/yyyy"
let dateStr = dateFormatter.string(from: date)
todaysRoutineNavBar.topItem?.title = dateStr + " Routine"
}
// MARK: - VIEWDIDAPPEAR
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.daysRoutineTable.reloadData()
self.updateView()
}
// MARK: - TABLE UPDATE COMPONENTS
private func setupView() {
updateView()
}
// MARK: - TABLE SETUP
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let count = self.selectedroutine?.userexercises?.count
{
print("exercises: \(count)")
return count
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? TodaysRoutineTableViewCell else {
fatalError("Unexpected Index Path")
}
cell.backgroundColor = UIColor.customBackgroundGraphite()
cell.textLabel?.textColor = UIColor.white
configure(cell, at: indexPath)
return cell
}
// MARK: - VIEW CONTROLER ELEMENTS VISIBILITY CONTROL
fileprivate func updateView() {
var hasUserExercises = false
if let UserExercise = self.selectedroutine?.userexercises {
hasUserExercises = UserExercise.count > 0
}
addTOdaysRoutineLabel.isHidden = hasUserExercises
columnHeaderBanner.isHidden = !hasUserExercises
daysRoutineTable.isHidden = !hasUserExercises
}
// MARK: - SETTING DATA FOR A TABLE CELL
func configure(_ cell: TodaysRoutineTableViewCell, at indexPath: IndexPath) {
if let userExercise = selectedroutine?.userexercises?.allObjects[indexPath.row]
{
print("\((userExercise as! UserExercise).name)")
cell.todaysExerciseNameLabel.text = (userExercise as! UserExercise).name
cell.todaysExerciseRepsLabel.text = String((userExercise as! UserExercise).reps)
cell.todaysExerciseSetsLabel.text = String((userExercise as! UserExercise).sets)
cell.todaysExerciseWeightLabel.text = String((userExercise as! UserExercise).weight)
}
}
}
requested table constraints
Debug hierarchy
The Segue that sends the user back to the view that looses its tab bar
if segue.identifier == "addToTodaySegue" {
let indexPath = workoutTemplateTable.indexPathForSelectedRow
let selectedRow = indexPath?.row
print("selected row\(selectedRow)")
if let selectedRoutine = self.fetchedResultsController.fetchedObjects?[selectedRow!]
{
if let todaysRoutineController = segue.destination as? RoutineController {
todaysRoutineController.selectedroutine = selectedRoutine
}
}
}
I also feel perhaps the viewDidAppear code may cause the issue, perhaps the super class?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.daysRoutineTable.reloadData()
self.updateView()
Updated storyboard image
I suspect you need to embed your viewController in a UINavigationController.
Consider the following setup:
I suspect your setup is like the upper one:
TapBar -> ViewController -show segue-> ViewController
Which results in a hidden tapbar, like in your description:
While the bottom setup:
TapBar -> NavigationCntroller -rootView-> ViewController -show segue-> ViewController
results in:
which is what you want, how I understood.
Update
It's hard to see. The screenshot of your Storyboard is in pretty low resulution, but the segues look wrong. Double check them. A Segue of type show (e.g push) looks like this:
Also clear project and derived data. Segue type changes sometime are ignored until doing so.
Try calling this self.view.bringSubviewToFront(YourTabControl).
The previous suggestion should work. But the content at the bottom part of tableview will not be visible as the tabbar comes over it. So set the bottom constraint of tableview as the height of tabbar.

How to get cell index from uiview in uitableviewcell (swift/xcode)

I have two UIViewControllers called upVote and downVote in MyTableViewCell class. I have added the gesture recognizers for tapping these views programmatically but am not sure how to get the parent cell or index of the cell so I know which cell the UIView that was tapped is in. How do I get the cell or index of the tapped cell in the functions handleTapUp and handleTapDown?
Here is my class
class MyTableViewCell: UITableViewCell {
// MARK: Properties
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var upVote: UIImageView!
#IBOutlet weak var downVote: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
let tapUp = UITapGestureRecognizer(target: self, action: "handleTapUp:")
tapUp.delegate = self
upVote.addGestureRecognizer(tapUp)
let tapDown = UITapGestureRecognizer(target: self, action: "handleTapDown:")
tapDown.delegate = self
downVote.addGestureRecognizer(tapDown)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func handleTapUp(sender: UITapGestureRecognizer? = nil) {
// handling code
// get cell(index)
}
func handleTapDown(sender: UITapGestureRecognizer? = nil) {
// handling code
// get cell()
}
}
I have tried self.superclass to get the uitableviewcell, and when i print the debug description it say uitableviewcell, but whenever I try to do anything else with the object I get an error that self.superclass is type AnyObject. I have tried declaring/casting self.superclass in many different ways and none have worked. This seems like it should be simple so hopefully I am missing something.
Declare a variable in your customCellClass:-
var indexForCell : NSIndexPath!
In your ViewControllers where you are dequeing the cells in the function func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell add this :-
cell.indexForCell = indexPath
Now access the indexForCell in your functions in your class:-
func handleTapUp(sender: UITapGestureRecognizer? = nil) {
let rowValue = indexForCell.row
}
func handleTapDown(sender: UITapGestureRecognizer? = nil) {
// handling code
// get cell()
}

Can I add a new cell to a tableview, when I press a button in swift, with some text from a textfield?

so I have just started to learn swift, and I am a bit stuck at this.
I have this example with this table view . There are 3 texts inserted in an array from the code ... but I want to complete that array with some text that I put in a text field... -> #IBOutlet weak var inputMessage: UITextField! , and I want to add the text after I press a button : #IBAction func sendMsg(sender: AnyObject) ... I don't know how to create a cell in the table for each text I want to insert ...
It is possible to do that ... ? If yes, cand you give some tips ... ?
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
//table view
#IBOutlet weak var tableView: UITableView!
//input field
#IBOutlet weak var inputMessage: UITextField!
//text arrays
var textArray: NSMutableArray! = NSMutableArray()
//var input = inputMessage.text
//push the button
///when you press the button create a label and put in a cell view
#IBAction func sendMsg(sender: AnyObject) {
var input = inputMessage.text
self.textArray.addObject(input)
//make rows change their dimensions
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 44.0
self.textArray.addObject(input)
func viewDidLoad() {
super.viewDidLoad()
}
}
// the view did load function
override func viewDidLoad() {
super.viewDidLoad()
self.textArray.addObject("Before You Say I Can'T, Make Sure You'Ve Tried.")
self.textArray.addObject("-I'm a mirror. If you're cool with me, I'm cool with you, and the exchange starts. What you see is what you reflect. If you don't like what you see, then you've done something. If I'm standoffish, that's because you are.")
self.textArray.addObject("It seems like once people grow up, they have no idea what's cool.")
var input = inputMessage.text
//make rows change their dimensions
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 44.0
}
// the did received memory warning
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: Table View Delegate
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.textArray.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell
cell.textLabel?.text = self.textArray.objectAtIndex(indexPath.row) as? String
return cell
}
}
Thank you!
Just reload your tableView after adding new element to textArray Like this:
self.textArray.addObject(input)
self.tableView.reloadData()
And you are adding your object into textArray two times.
So remove self.textArray.addObject(input)
And your action method will be:
#IBAction func sendMsg(sender: AnyObject) {
var input = inputMessage.text
//make rows change their dimensions
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 44.0
self.textArray.addObject(input)
tableView.reloadData()
}

Custom cell: fatal error: unexpectedly found nil while unwrapping an Optional value

I have a table view with custom cell that was created as .xib . I didnt use storyboard. I have a problem that I couldnt fill my table with the data which came from webservice result. Also, I have 4 labels in the custom cell. In my custom cell class, when I try to set labels for each items, It gives me fatal error like above.
Here is my code:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
...
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
{
let cell: ItemManagementTVCell = tableView?.dequeueReusableCellWithIdentifier("cell") as ItemManagementTVCell
if let ip = indexPath
{
let item: Item = self.itemList[indexPath.row] as Item
cell.setCell(item.itemName, status: item.itemStatus, duration: item.itemDuration, price: item.itemPrice)
}
return cell
}
}
And my custom cell class is here :
import UIKit
class ItemManagementTVCell: UITableViewCell {
#IBOutlet var lblItemName: UILabel!
#IBOutlet var lblItemPrice: UILabel!
#IBOutlet var lblItemDuration: UILabel!
#IBOutlet var lblItemStatus: UILabel!
override func awakeFromNib()
{
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
}
func setCell(name: String, status: Int, duration: Int, price: Int)
{
self.lblItemName.text = name
self.lblItemStatus.text = String(status)
self.lblItemDuration.text = "Duration: \(String(duration)) months"
self.lblItemPrice.text = String(price) + " $"
}
}
I am getting the error inside of "setCell" method block.
I have read a lot of questions and solutions and I tried all of them it doesnt work for me.
Thank you for your answers,
Best regards.
SOLUTION: I've solved this problem by linking the cell items to cell's own instead of linking to File's Owner. My problem has gone by doing this.
Another solution to the problem without having to link cell items to the cell owner:
let nib = UINib(nibName: "YOUR_CUSTOM_CELL_NIB_NAME", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "YOUR_CUSTOM_CELL_ID")
Your "cell" must be nil.
Using
tableView.dequeueReusableCellWithIdentifier("cell") as ItemManagementTVCell
Can return nil. You should use:
tableView.dequeueReusableCellWithIdentifier("cell" forIndexPath:indexPath) as ItemManagementTVCell
This way it guarantees cells is not nil.
EDIT: Maybe you can prevent the crash by putting if statements inside "setCell"
if var itemName = self.lblItemName {
itemName.text = name
}
Do that for every label you set inside it and check if the crash still happens. If it don't you must check why those labels are nil.