How to access one controller variable and methods from other controller in swift correctly? - ios

I create uiSegmentedControl in HomePageViewController. There are two items in segmented control. When I select first item , I add sensorItemViewController content as a subview in HomePageViewController with displayContentController method. And when clicked second item, I want to access methods of SensorTabItemViewController class which it's name is reloadMyTableView from HomePageViewConroller. I accessed from sensorItemVC but I get "unexpectedly found nil while unwrapping an Optional value" exception. How can access SensorItemTabViewController from HomePageViewControler correctly ? Thank you all response
HomePageViewController.swift :
let segmentedControlItems = ["Table", "RefreshTableView"]
var viewControllerArray: Array<UIViewController> = []
var segmentedControl : UISegmentedControl!
var sensorItemVC: SensorTabItemViewController!
class HomePageViewController: UIViewController,UIScrollViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
segmentedControl=UISegmentedControl(items: segmentedControlItems)
segmentedControl.selectedSegmentIndex=0
segmentedControl.tintColor=myKeys.darkBlueColor
segmentedControl.layer.cornerRadius = 0.0;
segmentedControl.layer.borderWidth = 1.5
segmentedControl.frame=CGRectMake(0, frameHeight/2, frameWidth, 35)
segmentedControl.addTarget(self, action: "changeSegmentedControlItem", forControlEvents: .ValueChanged)
self.view.addSubview(segmentedControl)
let sensorItemViewController = self.storyboard!.instantiateViewControllerWithIdentifier("sensorTabItemViewController")
viewControllerArray.append(sensorItemViewController)
}
func changeSegmentedControlItem(){
print(segmentedControl.selectedSegmentIndex)
if(segmentedControl.selectedSegmentIndex==0){
displayContentController(viewControllerArray[0])
}
else{
sensorItemVC.reloadMyTableView("Temp value", light: "Light value", noise: "noise Value", motion: "motion Value")
}
}
func displayContentController (content:UIViewController) {
self.addChildViewController(content)
print(self.segmentedControl.frame.height)
content.view.frame=CGRectMake(0, self.frameHeight/2+self.segmentedControl.frame.height, self.frameWidth,
self.frameHeight-(segmentedControl.frame.height*2+self.frameHeight/2))
self.view.addSubview(content.view)
content.didMoveToParentViewController(self)
}
}
SensorTabItemViewController. swift as below :
class SensorTabItemViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
let sensorName=["Sıcaklık Sensörü","Işık Sensörü","Gürültü Sensörü","Hareket Sensörü"]
var sensorDetails=["","","",""]
var sensorImages: Array<UIImage> = []
override func viewDidLoad() {
super.viewDidLoad()
print("sensorTab")
let tempImg=UIImage(named: "temp_ic") as UIImage?
let lightImg=UIImage(named: "light_ic") as UIImage?
let noiseImg=UIImage(named: "noise_ic") as UIImage?
let motionImg=UIImage(named: "motion_ic") as UIImage?
sensorImages.append(tempImg!)
sensorImages.append(lightImg!)
sensorImages.append(noiseImg!)
sensorImages.append(motionImg!)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func reloadTableView(){
sensorDetails=[]
sensorDetails.append(temp)
sensorDetails.append(light)
sensorDetails.append(noise)
sensorDetails.append(motion)
tableView.reloadData()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sensorName.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("sensorCell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text=sensorName[indexPath.row]
cell.imageView?.image=sensorImages[indexPath.row]
cell.detailTextLabel?.text=sensorDetails[indexPath.row]
return cell
}
}

You never set the value of sensorItemVC. That is why it is nil. I guess that
let sensorItemViewController = self.storyboard!.instantiateViewControllerWithIdentifier("sensorTabItemViewController")
should be replaced with
sensorItemVC = self.storyboard!.instantiateViewControllerWithIdentifier("sensorTabItemViewController") as! SensorTabItemViewController

Related

Table view cell not showing in table view controller

I'm new to swift and I'm trying to get my cells to show in tableView. I searched for questions here but none could help. The table loads fine and I get no errors regarding the tableView. Is there something I'm missing?
-I've double-checked the reuse identifier, they are the same
-I removed and readied the outlets
Here is my UITableViewController class:
class DrawerViewController: UITableViewController{
#IBOutlet weak var drawerTable: UITableView!
var currentCell = [DrawerModel]()
override func viewDidLoad() {
super.viewDidLoad()
addGradientToView(view: drawerTable)
let temp2Model = DrawerModel()
temp2Model.item = "Profile"
temp2Model.icon = "loginbackground2.jpg"
currentCell.append(temp2Model)
drawerTable.delegate = self
drawerTable.dataSource = self
//self.drawerTable.separatorStyle = UITableViewCellSeparatorStyle.none
//self.drawerTable.reloadData()
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = drawerTable.dequeueReusableCell(withIdentifier: "drawerCell", for: indexPath) as! DrawerTableViewCell
let tempModel: DrawerModel
tempModel = currentCell[indexPath.row]
cell.thisLabel.text = tempModel.item
print("test1" + tempModel.item! as Any)
let currentImage = UIImage(named: "loginbackground2.jpg")
cell.thisImage = UIImageView(image: currentImage)
return cell
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1;
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("it ran")
return currentCell.count
}
func addGradientToView(view: UITableView)
{
//gradient layer
let gradientLayer = CAGradientLayer()
//define colors
gradientLayer.colors = [UIColor.init(rgb: 0x4b0082).cgColor, UIColor.init(rgb: 0xfa8072).cgColor]
//define locations of colors as NSNumbers in range from 0.0 to 1.0
//if locations not provided the colors will spread evenly
gradientLayer.locations = [0.0, 0.8]
//define frame
gradientLayer.frame = view.bounds
//insert the gradient layer to the view layer
view.layer.insertSublayer(gradientLayer, at: 0)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Here is my UITableViewCell class:
class DrawerTableViewCell: UITableViewCell {
#IBOutlet weak var thisImage: UIImageView!
#IBOutlet weak var thisLabel: UILabel!
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
}
}
If you are using UITableViewController (in your case DrawerViewController) it already have a tableView property embedded, which have a delegate and dataSource set to controller.
So when in your case next lines are redundant
drawerTable.delegate = self
drawerTable.dataSource = self
To fix just call tableView.reload() after currentCell.append(temp2Model)

Gets number of rows but doesn't print

I have a program written in Swift 3, that grabs JSON from a REST api and appends it to a table view.
Right now, I'm having troubles with getting it to print in my Tableview, but it does however understand my count function.
So, I guess my data is here, but it just doesn't return them correctly:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, HomeModelProtocal {
#IBOutlet weak var listTableView: UITableView!
func itemsDownloaded(items: NSArray) {
feedItems = items
self.listTableView.reloadData()
}
var feedItems: NSArray = NSArray()
var selectedLocation : Parsexml = Parsexml()
override func viewDidLoad() {
super.viewDidLoad()
self.listTableView.delegate = self
self.listTableView.dataSource = self
let homeModel = HomeModel()
homeModel.delegate = self
homeModel.downloadItems()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier: String = "BasicCell"
let myCell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)!
let item: Parsexml = feedItems[indexPath.row] as! Parsexml
myCell.textLabel!.text = item.title
return myCell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return feedItems.count
}
override func viewDidAppear(_ animated: Bool) {
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Are you by any chance able to see the error that I can't see?
Note. I have not added any textlabel to the tablerow, but I guess that there shouldn't be added one, when its custom?
Try this code:
override func viewDidLoad() {
super.viewDidLoad()
print(yourArrayName.count) // in your case it should be like this print(feedItems.count)
}

Array does not stacking Class object

I am trying to initialize and then append Class object to array through delegate func. Delegate Double comes from button press with some data.
var expensesArray = [SpendedMoneyObject]()
var delegatedDouble:Double = 0.0
func setExpenses(expensesFromMainView: Double) {
delegatedDouble = expensesFromMainView
var aSpendedMoneyObject = SpendedMoneyObject(moneySpent: delegatedDouble)
expensesArray += [aSpendedMoneyObject]
self.tableView.reloadData()
}
Problem here is that I am trying to show array at TableViewCell, but it doesn't showing at all, I guess main problem is that expensesArray value is 1 and it's not stacking but replacing same array with other value. Will be really happy to hear what you think.
Edit:
I tried .append and it still the same also TableView func cellForRowAtIndexPath does not getting called.
class ExpensesTableViewController: UITableViewController, ExpensesEnteredDelegate{
//MARK : Properties
var expensesArray = [SpendedMoneyObject]()
var delegatedDouble:Double = 0.0
override func viewDidLoad() {
super.viewDidLoad()
}
func setExpenses(expensesFromMainView: Double) {
delegatedDouble = expensesFromMainView
var aSpendedMoneyObject = SpendedMoneyObject(moneySpent: delegatedDouble)
expensesArray.append(aSpendedMoneyObject)
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return expensesArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "ExpensesCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ExpensesTableViewCell
print("Iam here")
let expense = expensesArray[indexPath.row]
let fromDoubleToString = "\(expense.moneySpent)"
cell.loadItemsToCell(fromDoubleToString, date: expense.date)
return cell
}
Object class:
class SpendedMoneyObject {
var moneySpent: Double
var currentTime = NSDate().toShortTimeString()
var date: String
init(moneySpent: Double) {
self.date = currentTime
self.moneySpent = moneySpent
}}
Edit: I can now add more than one array by moving new ViewController creation from spendButton func which was creating newVC every time i clicked button. Here are edited code:
protocol ExpensesEnteredDelegate {
func setExpenses(expensesFromMainView: Double)
}
class MainViewController: UIViewController {
#IBOutlet weak var moneyTextField: UITextField!
var delegate: ExpensesEnteredDelegate? = nil
override func viewDidLoad() {
super.viewDidLoad()
// Defining ExpensesVC
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let newExpensesVC = storyboard.instantiateViewControllerWithIdentifier("ExpensesTableView") as! ExpensesTableViewController
delegate = newExpensesVC
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func spentButton(sender: AnyObject) {
// Delegating expenses Double value
if (delegate != nil) {
let myDouble = Double(moneyTextField.text!)
let expenses: Double = myDouble!
delegate!.setExpenses(expenses)
}
}}
But still array's data does not showing up in a tableView
Try this code example:
let aSpendedMoneyObject = SpendedMoneyObject(moneySpent: delegatedDouble)
expensesArray.append(aSpendedMoneyObject)
Or you can use .extend() method if you are looking to append more elements from a different array to your array.
instead of
expensesArray += [aSpendedMoneyObject]
try
expensesArray.append(aSpendedMoneyObject)

Return number field from Parse into Tableview custom cell

I have a tableview controller with a custom Prototype Cell. The cell contains 2 labels. I am trying to return 2 values from a Parse class. One field is called Notes and is a String value. The other field is called CreditAmount and is a number value. I am having difficulty returning the number value (Credit Amount) in my tableview.
Here is code for tableview controller:
import UIKit
import Parse
import Foundation
class TableViewController: UITableViewController {
var note = [String]()
var credit = [NSInteger]()
var refresher: UIRefreshControl!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.reloadData()
updateNotes()
self.refresher = UIRefreshControl()
self.refresher.attributedTitle = NSAttributedString(string: "Pull to refresh")
self.refresher.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
self.tableView.addSubview(refresher)
}
func updateNotes() {
let query = PFQuery(className: "Paydown")
query.findObjectsInBackgroundWithBlock({ (objects:[AnyObject]?, error: NSError?) -> Void in
self.note.removeAll(keepCapacity: true)
self.credit.removeAll(keepCapacity: true)
if let objects = objects as? [PFObject] {
for object in objects {
// var noted = object as PFObject
self.note.append(object["Notes"] as! String)
self.credit.append(object["CreditAmount"] as! NSInteger)
}
self.tableView.reloadData()
} else {
//println(error)
}
self.refresher.endRefreshing()
})
}
func refresh() {
updateNotes()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return note.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! cell
myCell.notesLabel.text = note[indexPath.row]
myCell.amountLabel.text = credit[indexPath.row]
return myCell
}
}
Here is the code for my customer cell:
import UIKit
import Parse
class cell: UITableViewCell {
#IBOutlet weak var notesLabel: UILabel!
#IBOutlet weak var amountLabel: UILabel!
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
}
}
The myCell.amountLabel.text = credit[indexPath.row] causes an error: cannot assign a value of type NSInteger (aka int) to a value of type String?. How do I get the number field to work?
Update
myCell.amountLabel.text = credit[indexPath.row]
To be
myCell.amountLabel.text = "\(credit[indexPath.row])"

customCell UITextField in UITableViewController not displaying during runtime swift

I am facing a weird problem in my project. My UITextField, UILabel, and UIButton are not appearing during runtime even though all the referencing outlets are mentioned properly
here is my tableview controller code:
class ComposeMessageTableViewController: UITableViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var composeMessage: UITableView!
let composeCellArray = ["composeMessage"]
override func viewDidLoad() {
super.viewDidLoad()
composeMessage.delegate = self
composeMessage.dataSource = self
composeMessage.separatorStyle = .None
composeMessage.backgroundColor = UIColor.whiteColor()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 0
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return composeCellArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let composeCell = tableView.dequeueReusableCellWithIdentifier(composeCellArray[indexPath.row]) as! ComposeMessageCell
if(indexPath.row == 0){
// composeCell.toLabel.text = composeCellArray[indexPath.row] as String
// composeCell.recepientTextField?.text = composeCellArray[indexPath.row] as String
composeCell.toLabel.text = "To"
composeCell.recepientTextField?.placeholder = "Recepients"
composeCell.addButton.tag=indexPath.row
composeCell.addButton.addTarget(self, action: "addMembers:", forControlEvents: UIControlEvents.TouchUpInside)
}
// Configure the cell...
composeCell.backgroundColor = UIColor.clearColor()
composeCell.selectionStyle = .None
return composeCell
}
#IBAction func addMembers(sender:UIButton){
}
#IBAction func dismissnav(sender: AnyObject) {
dismissViewControllerAnimated(true, completion: nil)
}
}
here is tableviewcell code:
class ComposeMessageCell: UITableViewCell {
#IBOutlet var toLabel: UILabel!
#IBOutlet var recepientTextField: UITextField!
#IBOutlet var addButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
toLabel.font = UIFont(name: "Avenir-Black", size: 16)
toLabel.textColor = UIColor.blackColor()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Please let me know where am i going wrong
Below delegate should return 1
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
As #Prabhu mentioned delegate for method:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
should always return 1 which is default or other value set by you.

Resources