Passing TableView Data to DetailViewController in swift - swift

I have a simple tableview loading with array of colours(each cell with different colour).i am trying to pass the background colour of detailViewController when user press the colour array cell from colourTableviewcontroller(simply i want to pass the cell colour as a detailview background colour)
my code as follows.....
import UIKit
class colourTableviewcontroller: UITableViewController {
#IBOutlet weak var colorTableView: UITableView!
let colors = [UIColor.redColor(), UIColor.blueColor(),UIColor.greenColor(), UIColor.orangeColor(),UIColor.purpleColor(),UIColor.yellowColor(),UIColor.cyanColor(),UIColor.darkGrayColor(),UIColor.blackColor(), UIColor.brownColor(),UIColor.grayColor(), UIColor.magentaColor(), UIColor.whiteColor()]
var colourData = UIColor()
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.
}
override func viewDidAppear(animated: Bool) {
colorTableView.separatorColor = UIColor.clearColor()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return colors.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("colourCell", forIndexPath: indexPath) as UITableViewCell
cell.backgroundColor = self.colors[indexPath.row % self.colors.count]
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
colourData = self.colors[indexPath.row]
performSegueWithIdentifier("colourSegue", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "colourSegue") {
let viewController = segue.destinationViewController as! DetailViewController
viewController.bc?.backgroundColor = colourData }
}}
// My DetailViewController as follows...
import UIKit
class DetailViewController: UIViewController {
#IBOutlet var bc: UIView!
override func viewDidLoad() {
self.bc.backgroundColor = UIView.appearance().backgroundColor
}
when i run the code my DetailViewController background colour changing to dark text colour when i press the colour array.....
i don't know what i am missing or am i doing wrong approach/logic....
Thanks in Advance.....

First of all in ColourTableviewcontroller connect the segue to the table view cell rather than to the view controller and delete the method didSelectRowAtIndexPath
Replace prepareForSegue with
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "colourSegue" {
let viewController = segue.destinationViewController as! DetailViewController
let selectedIndexPath = tableView.indexPathForCell(sender as! UITableViewCell)
viewController.color = colors[selectedIndexPath.row]
}
}
In DetailViewController declare a variable color
var color : UIColor!
And set the color of bc in viewDidLoad()
bc.backgroundColor = color
The reason for the additional variable is that the IBOutlets in DetailViewController don't exist yet while prepareForSegue is executed.

You aren't passing the UIColor and assigning it in the next View Controller
You just need to do few modifications to your existing code
1) Add var recievedColor : UIColor! in the DetailViewController
2) In your prepareForSegue replace viewController.bc?.backgroundColor = colourData with viewController.recievedColor = colourData
3) In your DetailViewController, in viewDidLoad() function, replace self.bc.backgroundColor = UIView.appearance().backgroundColor with self.bc.backgroundColor = recievedColor
And there you go!

You need to pass the color, then assign the color to the view on the viewDidLoad(). You are assigning a variable to a view that hasn't been initialized yet.
in your detail class do as follow:
class DetailViewController: UIViewController {
#IBOutlet var bc: UIView!
var selectedBackgroundColor: UIColor? // this should be set on the prepareForSegue method.
override func viewDidLoad() {
super.viewDidLoad()
if let selectedBackgroundColor = selectedBackgroundColor {
bc.backgroundColor = selectedBackgroundColor
}
}
Hope this helps!

Related

How to input the value from UI button in Teble View cell to the variable declared in Table View Controller?

I want to save the value of filled button(●) into the array "q.answer[indexPath.row]" about each question "q.question[indexPath.row]).
currentQuizButtonIndex is currently renewed every time when ◯ changes to ● by tapping. However, I have no idea how to save in to variable q which is declared in TableViewController.
View Controller display
Code about QuizCell.swift (TableCell which is about 5 buttons and UIlabel.)
import UIKit
import Foundation
protocol QuizCellDelegate {
func quizCellDidChangeCurrentButtonIndex(_ cell: QuizCell, index: Int)
}
class QuizCell: UITableViewCell {
var currentQuizButtonIndex: Int = 0 {
didSet {
let value = self.currentQuizButtonIndex
self.updateCurrentQuizButton(value)
if let delegate = self.delegate {
delegate.quizCellDidChangeCurrentButtonIndex(self, index: value)
}
}
}
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet var answerButtons: [UIButton]!
var delegate: QuizCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
//print("ここまできてるか確認")
// Initialization code
}
#IBAction func didTapQuizButton(_ sender: UIButton) {
if let index = self.answerButtons.firstIndex(of: sender){
self.currentQuizButtonIndex = index
delegate?.quizCellDidChangeCurrentButtonIndex(self, index: index)
print(index)
}
}
private func updateCurrentQuizButton(_ currentIndex: Int){
for (index, answerButton) in self.answerButtons.enumerated(){
if index == currentIndex {
answerButton.setTitle("●", for: .normal)
} else {
answerButton.setTitle("○", for: .normal)
}
}
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Code about View Controller
import UIKit
class AnswerQuizViewController: UIViewController, UITableViewDelegate {
var q: QuestionSeries!
#IBOutlet weak var quizTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
quizTableView.dataSource = self
quizTableView.delegate = self
// cell xibファイルを使うときは書く必要があるやつ。
// quizTableView.register(UINib(nibName: K.Cells.QuizCellNibName, bundle: nil), forCellReuseIdentifier: K.Cells.QuizCellIdentifier)
quizTableView.register(UINib(nibName: "QuizCell", bundle: nil), forCellReuseIdentifier: "QuizCellIdentifier")
// Do any additional setup after loading the view.
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
// override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// // Get the new view controller using segue.destination.
// // Pass the selected object to the new view controller.
//// if segue.identifier == K.Segue.checkResult {
//// let resultViewController = segue.destination as! ResultViewController
//// answerQuizViewController.q =
//// print(answerQuizViewController.q)
// }
}
// MARK: - quizTableViewのアレンジ
extension AnswerQuizViewController: UITableViewDataSource, QuizCellDelegate {
func quizCellDidChangeCurrentButtonIndex(_ cell: QuizCell, index: Int) {
if let indexPath = self.quizTableView.indexPath(for: cell){
self.q.question[indexPath.row].answer = index
print(index)
}else{
print("ここきてます")
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return q.question.count
//print(q.question.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let question = q.question[indexPath.row]
let cell = quizTableView.dequeueReusableCell(withIdentifier: K.Cells.QuizCellIdentifier, for: indexPath) as! QuizCell
cell.questionLabel.text = question.text
// print(question.text)
return cell
}
}
It is also helpful if you have any idea of implementing this by alternative way.
Thanks.
How about you create a static array and store your data into that array.
when the button is tapped you can append it into that static array.
Create a new file. Just a basic "Swift file".
struct structName {
static var qArray: [String] = []
}
Then append data by:
structName.q.append()
Finally get your data trough:
structName.q[index]

Table Content disappears on Scroll in TableView with Custom Cell using Subview - Swift

I have a ViewController which uses multiple Subviews (HomeViewController, etc.) which can be selected via a Custom Tab Bar at the bottom of my app. Inside the HomeViewController there is a UIView containing a UITableView containing a Prototype Custom Cell with name and image.
import UIKit
class HomeViewController: UIViewController {
#IBOutlet weak var friendView: UITableView!
let friends = ["batman", "harsh", "ava", "sasha", "fatima", "alfred"]
override func viewDidLoad() {
super.viewDidLoad()
friendView.delegate = self
friendView.dataSource = self
friendView.allowsSelection = false
}
}
extension HomeViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 120
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return friends.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = friendView.dequeueReusableCell(withIdentifier: "customCell") as! CustomCell
let friend = friends[indexPath.row]
cell.avatarImg.image = UIImage(named: friend)
cell.nameLbl.text = friend
return cell
}
}
Custom cell:
import UIKit
class CustomCell: UITableViewCell {
#IBOutlet weak var friendView: UIView!
#IBOutlet weak var nameLbl: UILabel!
#IBOutlet weak var avatarImg: UIImageView!
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
}
}
When I start the app, everything looks just fine. However, when I start scrolling inside the table, all data suddenly disappears. All relations between storyboard and code should be just fine. I think it might have got something to do with my need of using a Subview.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var tabBarView: UIView!
#IBOutlet weak var contentView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
Design.makeCornersRound(view: tabBarView, radius: 10.0)
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: false) { (timer) in
self.switchToHomeViewController()
}
}
#IBAction func onClickTabBar(_ sender: UIButton) {
let tag = sender.tag
if tag == 1 {
switchToIncomingsViewController()
}
else if tag == 2 {
switchToSpendingsViewController()
}
else if tag == 3 {
switchToHomeViewController()
}
else if tag == 4 {
switchToSavingsViewController()
}
else if tag == 5 {
switchToSettingsViewController()
}
}
func switchToHomeViewController() {
guard let Home = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as? HomeViewController else { return }
contentView.addSubview(Home.view)
Home.didMove(toParent: self)
}
...
}
Reference to the tutorial I have been trying to implement: https://www.youtube.com/watch?v=ON3Z0PXSoVk
In this function:
func switchToHomeViewController() {
// 1
guard let Home = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as? HomeViewController else { return }
// 2
contentView.addSubview(Home.view)
// 3
Home.didMove(toParent: self)
// 4
}
At 1 you create an instance of HomeViewController
at 2 you add its view to cotentView
at 3 you call didMove() ... but that doesn't do anything because you haven't added the controller to your hierarchy
at 4 your Home instance goes away, so the code in that controller no longer exists
You need to add the controller as a child controller.
As a side note, use lowerCase for variable names:
func switchToHomeViewController() {
// create an instance of HomeViewController
guard let homeVC = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as? HomeViewController else { return }
// add it as a child view controller
self.addChild(homeVC)
// add its view
contentView.addSubview(homeVC.view)
// here you should either set the view's frame or add constraints
// such as:
homeVC.view.frame = contentView.bounds
// inform the controller that it moved to a parent controller
homeVC.didMove(toParent: self)
}

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)
}

swift, text in label doesn't change in viewDidAppear()

I'm new to IOS developtment but I'm programming an app where the user selects a row from a tableView (view 1). The text that the user selected is then displayed in a label on the same screen. When the user pushes the button the text from the label is stored in UserDefaults and the view changes to view 2. Here I have the viewDidAppear() method that gets the String out of the UserDefaults and changes the text of another Label on view 2.
Here is the code for view 1. The function that is called when the button is clicked is called schoolChosenClicked():
import UIKit
class ChooseSchool: UIViewController, UITableViewDataSource, UITableViewDelegate {
var SchoolNames = [String]()
#IBOutlet weak var table: UITableView!
var refresher: UIRefreshControl!
#IBOutlet weak var LabelSchoolName: UILabel!
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return SchoolNames.count
}
//Set the context
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = SchoolNames[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
LabelSchoolName.text = SchoolNames[indexPath.row]
}
override func viewDidLoad() {
super.viewDidLoad()
SchoolNames.append("Item")
SchoolNames.append("Item")
SchoolNames.append("Item")
SchoolNames.append("")
self.table.register(UITableViewCell.self, forCellReuseIdentifier: "cell");
self.table.dataSource = self
self.table.delegate = self
self.table.reloadData()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func schoolChosenClicked(_ sender: Any) {
UserDefaults.standard.set(LabelSchoolName.text, forKey: "chosenSchool")
}
}
Here is a picture of view 1
Here is the code for view 2
import UIKit
class Login: UIViewController {
#IBOutlet weak var LabelWelcome: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
if var schoolname = UserDefaults.standard.object(forKey: "chosenSchool") as? String
{
print("Das ist der Schoolname:" + schoolname+".")
LabelWelcome.text = "Willkommen bei deiner \(schoolname) App"
}
}
}
And here is the picture of the second view
In the 2nd picture you can see the Label that says "Name Anmelden". This text actually has to change to "Willkommen bei deiner (schoolname) App" but it does't or after a long period of time.
The value schoolname is well present and the print statement works fine but the LabelWelcome.text =... doesn't work or takes a long time. If I try to set the text in the viewDidLoad() method it works fine.
Do you know why or is there a method that i can call to update the screen?
Thank you,
Manuel
PS: Here is the screenshot of my login class (view 2)
Here is the first screenshot of my ChooseSchool class (view 1)
Here is the second screenshot of my ChooseSchool class (view 1
You need to select table cell or need to add text when clicking on the button:
#IBAction func schoolChosenClicked(_ sender: Any) {
LabelSchoolName.text = SchoolNames[indexPath.row]
UserDefaults.standard.set(LabelSchoolName.text, forKey: "chosenSchool")
}
After that still you getting the problem then add synchronize like this when you add your text in userdefault(This is not recommended):
UserDefaults.standard.set(LabelSchoolName.text, forKey: "chosenSchool")
UserDefaults.standard.synchronize()

Saving Swift TableView data using NSUSerDefaults

I have a tableview in swift. Each cell has a label with different text. When a cell is selected it passes the text to a label on another view controller. I can save this data using a button (Save Data) and load the saved data with another button (Load Data).
My problem is I would ideally like to not use buttons, but have the data loaded automatically when the view loads. However, when I place the NSUSerDefaults code within viewDidLoad (), it saves the data but I am no longer able to change the selection i.e. it loads the first selection permanently. I have posted my code below for the destination ViewController and for the TableViewController.
ViewController
import UIKit
class DetailViewController: UIViewController {
#IBOutlet weak var detailLabel: UILabel!
var passedValue: String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
detailLabel.text = passedValue
}
#IBAction func saveDataClicked(sender: AnyObject) {
var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(self.detailLabel.text, forKey: "optionValue")
}
#IBAction func loadDataClicked(sender: AnyObject) {
var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
if let optionValueIsNotNill = defaults.objectForKey("optionValue") as? String {
self.detailLabel.text = defaults.objectForKey("optionValue") as! String
}
}
}
TableViewController
import UIKit
class TableViewController: UITableViewController {
var valueToPass:String!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
override func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
// Get Cell Label
let indexPath = tableView.indexPathForSelectedRow;
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;
valueToPass = currentCell.textLabel!.text
performSegueWithIdentifier("showDetailView", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){
if segue.identifier == "showDetailView" {
// initialize new view controller and cast it as your view controller
var viewController = segue.destinationViewController as! DetailViewController
// your new view controller should have property that will store passed value
viewController.passedValue = valueToPass
}
}
}
if You want to save selected Data to NSUSerDefaults You should write your saving code in didSelectRowAtIndexPath like this
if you have a function to save the data in NSUserDefaults
save(DataArray[indexPath.row])
then it will be saved , but i think if your data used when the application is running only , i think the best option to use is static instance .