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

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

Related

How to add additional textfields by clicking button in table view

I am trying to add an option to add additional student fields inside table so that user can add more than one student name.
But I am confused how to do it using table view.
I am not interested in hiding view with specific number of fields.
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
struct listItems{
var title : String
var isExpandable:Bool
var maxFields :Int
init(title:String,isExp:Bool,mxF:Int) {
self.title = title
self.isExpandable = isExp
self.maxFields = mxF
}
}
#IBOutlet weak var tblListTable: UITableView!
let data : [listItems] = [listItems(title: "Name", isExp: false, mxF: 1), listItems(title: "Student Name", isExp: true, mxF: 20), listItems(title: "Email", isExp: false, mxF: 1)]
override func viewDidLoad() {
super.viewDidLoad()
tblListTable.delegate = self
tblListTable.dataSource = self
self.tblListTable.reloadData()
print("isLoaded")
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("cellForRow")
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! ListCell
cell.lblName.text = data[indexPath.row].title
if data[indexPath.row].isExpandable == true {
cell.btnAddField.isHidden = false
print("ishidden")
}
else {
cell.btnAddField.isHidden = true
}
return cell
}
}
List Cell Class
import UIKit
protocol AddFieldDelegate : class {
func addField( _ tag : Int)
}
class ListCell: UITableViewCell {
#IBOutlet weak var btnAddField: UIButton!
#IBOutlet weak var lblName: UILabel!
#IBOutlet weak var txtField: UITextField!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func addField( _ tag : Int){
}
}
You are on the right track creating the AddFieldDelegate. However, rather than implementing the method inside the ListCell class you need to implement it in the ViewController.
First, change the view controller class definition line to:
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource, AddFieldDelegate {
This will allow you to call the delegate method from the view controller. Next, when you are creating your table view cells add the line:
cell.delegate = self
After that, move the method definition of the method addField to the view controller.
So inside of your view controller add:
func addField(titleOfTextFieldToAdd: String, numberAssociatedWithTextFieldToAdd: Int) {
data.append(listItems(title: titleOfTextFieldToAdd, isExp: false, mxF: numberAssociatedWithTextFieldToAdd))
self.tableView.reloadData()
}
I used an example definition of the addField method but you can change it to anything that you would like, just make sure that you change the data array and reload the table view data.
Lastly, we must define the delegate in the ListCell class. So add this line to the ListCell class:
weak var delegate: MyCustomCellDelegate?
You can then add the text field by running the following anywhere in your ListCell class:
delegate?.addField(titleOfTextFieldToAdd: "a name", numberAssociatedWithTextFieldToAdd: 50)
For more information on delegation, look at the answer to this question.
You have to append another item in your data array on button click and reload the tableview.

Accessing Variables From a Different Swift Class

I have two swift files, each corresponding to a different view controller. I also have two classes, one for creating "Workout" objects and the other for holding these objects into an array. The workout class is a very simple class that just holds properties such as workout name, description, etc.
I am trying to access the array count of workoutList in my OverViewViewController.swift
Im a new developer and don't know how I would achieve this. Would I have to make a reference to the NewWorkoutViewController then try to grab the variable?
import UIKit
class OverViewViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 12
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "Hello"
return cell
}
}
import UIKit
class NewWorkoutViewController: UIViewController {
#IBOutlet weak var setStepper: UILabel!
#IBOutlet weak var repStepper: UILabel!
#IBOutlet weak var workoutName: UITextField!
#IBOutlet weak var workoutDescription: UITextField!
var workoutList = WorkoutList().listOfWorkouts
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func stepCounter(_ sender: UIStepper) {
if sender.tag == 1 {
setStepper.text = "\(Int(sender.value))"
}
if sender.tag == 2 {
repStepper.text = "\(Int(sender.value))"
}
}
#IBAction func addToWorkoutList(_ sender: UIButton) {
let workout = Workout(name: workoutName.text!, description: workoutDescription.text!, sets: Int(setStepper.text!)!, reps: Int(repStepper.text!)!)
workoutList.append(workout)
print(workoutList.count)
}
}
So the best way to do is create a model class name it as WorkOut with your required information. Then add the that object in array which you can define in your viewController class. Now you can pass that array information to another viewController class and can use it.

Passing TableView Data to DetailViewController in 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!

two table view in one view controller, swift

My view controller has two table views. The askTable works, but bidTable doesn't work. No error comes out.
Here is what it prints. The array exactly contains the elements I want. Not sure what I did wrong or miss for bidTable. Also, wondering why "Hi" is never printed too.
askPriceArray: []
bidPriceArray: []
bid: 0
Above repeat several times
askPriceArray: []
bidPriceArray: ["21"]
ask: 0
askPriceArray: []
bidPriceArray: ["21", "212"]
ask: 0
askPriceArray: ["21"]
bidPriceArray: ["21", "212"]
ask: 1
import UIKit
class ProductDetailViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
{
#IBOutlet weak var bidTable: UITableView!
#IBOutlet weak var askTable: UITableView!
var askPriceArray = [String]()
var bidPriceArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.bidTable.dataSource = self
self.bidTable.delegate = self
self.askTable.dataSource = self
self.askTable.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(animated: Bool) {
.....insert elements to arrays from Parse..........
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("askPriceArray: \(self.askPriceArray)")
print("bidPriceArray: \(self.bidPriceArray)")
if tableView == self.askTable {
print("ask: \(askPriceArray.count)")
return askPriceArray.count
} else {
print("bid: \(bidPriceArray.count)")
return bidPriceArray.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView == self.askTable{
let cell:DetailAskTableViewCell = tableView.dequeueReusableCellWithIdentifier("askCell") as! DetailAskTableViewCell
cell.askPriceAndQuantity.text = self.askPriceArray[indexPath.row]
return cell
} else {
print("Hi")
let cell:DetailBidTableViewCell = tableView.dequeueReusableCellWithIdentifier("bidCell") as! DetailBidTableViewCell
cell.bidPriceAndQuantity.text = self.bidPriceArray[indexPath.row]
return cell
}
}
}
Be sure that you are reloading both UITableViews after you have retrieved your data from Parse.

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