I'm working on the tableView in swift 2.2 in xcode 7.3.1 and I'm sure from my code because it's not the first time for me to deal with tableView , I'm pulling data correctly from server and stored it in array but I notice the two function that is related to table view is not called so the table view appear empty for me ! I added cell and linked tableview with view also from layout.
I don't know where is the problem!
class studentTeacherList: UIViewController , UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var studentParentTable: UITableView!
#IBOutlet weak var loadIndicator: UIActivityIndicatorView!
var username:String!
var fromSender: String?
var toRec: String?
var student_id = [Int]()
var parent_id = [String]()
var student_names = [String]()
var parent_name = [String]()
//Sent Data
var s_id:Int = 0
var s_name = ""
var p_id = ""
var p_name = ""
override func viewDidLoad() {
super.viewDidLoad()
studentParentTable.delegate = self
studentParentTable.dataSource = self
let prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()
username = prefs.objectForKey("user")as! String
fromSender = prefs.objectForKey("Sender")as! String
toRec = prefs.objectForKey("Receiver")as! String
self.loadIndicator.startAnimating()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
self.loadList()
//self.studentParentTable.reloadData()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.loadIndicator.stopAnimating()
})
});
studentParentTable.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return student_names.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//This method to define each cell at Table View
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
cell.textLabel?.text = student_names[indexPath.row]
cell.detailTextLabel?.text = parent_name[indexPath.row]
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func backButton(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil )
}
func loadList()
{
var normallink = "mylinkhere"
normallink = normallink + "?teacherid=" + self.username
var studentParentURL:NSURL = NSURL (string: normallink)!
let data = NSData(contentsOfURL: studentParentURL)!
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
if let alldata = json["data"] as? [[String: AnyObject]] {
for onedata in alldata {
if let stu_id = onedata["id"] as? Int {
student_id.append(stu_id)
}
if let stu_name = onedata["studentName"] as? String {
student_names.append(stu_name)
}
if let par_id = onedata["parentId"] as? String {
parent_id.append(par_id)
}
if let par_name = onedata["parentName"] as? String {
parent_name.append(par_name)
}
}
}
} catch {
print("Error Serializing JSON: \(error)")
}
print(student_names.count)
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
s_id = student_id[indexPath.row]
s_name = student_names[indexPath.row]
p_id = parent_id[indexPath.row]
p_name = parent_name[indexPath.row]
}
}
It looks like you aren't reloading after this call:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
self.loadList()
//self.studentParentTable.reloadData()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.loadIndicator.stopAnimating()
})
});
So you should add studentParentTable.reloadData() after self.loadIndicator.stopAnimating().
Related
I'm using firebase to make an iOS app. I want to retrieve all the users on my database and display their name and profile picture in a table view. Here is my code for my TableViewCell:
import UIKit
import FirebaseDatabase
import FirebaseAuth
import SDWebImage
class HomeTableViewCell: UITableViewCell {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var profileImageView: UIImageView!
#IBOutlet weak var likeImageView: UIImageView!
#IBOutlet weak var messageImageView: UIImageView!
#IBOutlet weak var likeCountButton: UIButton!
var homeVC: HomeViewController?
var postReference: DatabaseReference!
var post: UserFile?{
didSet {
updateView()
}
}
var user: UserFile? {
didSet {
updateUserInfo()
}
}
override func awakeFromNib() {
super.awakeFromNib()
nameLabel.text = ""
let berryTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleLikeTap))
likeImageView.addGestureRecognizer(berryTapGesture)
likeImageView.isUserInteractionEnabled = true
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func updateView() {
if let photoURL = post?.picURL {
profileImageView.sd_setImage(with: URL(string: photoURL))
}
API.Post.REF_POSTS.child(post!.id!).observeSingleEvent(of: .value, with: { postSnapshot in
if let postDictionary = postSnapshot.value as? [String:Any] {
let post = UserFile.transformPost(postDictionary: postDictionary, key: postSnapshot.key)
self.updateLike(post: post)
}
})
API.Post.REF_POSTS.child(post!.id!).observe(.childChanged, with: { snapshot in
if let value = snapshot.value as? Int {
self.likeCountButton.setTitle("\(value) berries", for: .normal)
}
})
}
func updateLike(post: UserFile) {
let imageName = post.berries == nil || !post.isBerried! ? "berry" : "berrySelected"
likeImageView.image = UIImage(named: imageName)
// display a message for berries
guard let count = post.berryCount else {
return
}
if count != 0 {
likeCountButton.setTitle("\(count) berries", for: .normal)
} else if post.berryCount == 0 {
likeCountButton.setTitle("Be the first to Like this", for: .normal)
}
}
func incrementberries(forReference ref: DatabaseReference) {
ref.runTransactionBlock({ (currentData: MutableData) -> TransactionResult in
if var post = currentData.value as? [String : AnyObject], let uid = Auth.auth().currentUser?.uid {
var berries: Dictionary<String, Bool>
berries = post["berries"] as? [String : Bool] ?? [:]
var likeCount = post["berryCount"] as? Int ?? 0
if let _ = berries[uid] {
// Unlike the post and remove self from stars
likeCount -= 1
berries.removeValue(forKey: uid)
} else {
// Like the post and add self to stars
likeCount += 1
berries[uid] = true
}
post["berryCount"] = likeCount as AnyObject?
post["berries"] = berries as AnyObject?
currentData.value = post
return TransactionResult.success(withValue: currentData)
}
return TransactionResult.success(withValue: currentData)
}) { (error, committed, snapshot) in
if let error = error {
print(error.localizedDescription)
}
if let postDictionary = snapshot?.value as? [String:Any] {
let post = UserFile.transformPost(postDictionary: postDictionary, key: snapshot!.key)
self.updateLike(post: post)
}
}
}
func handleLikeTap() {
postReference = API.Post.REF_POSTS.child(post!.id!)
incrementberries(forReference: postReference)
}
override func prepareForReuse() {
super.prepareForReuse()
profileImageView.image = UIImage(named: "industribune-default-no-profile-pic")
}
func updateUserInfo() {
nameLabel.text = user?.username
if let photoURL = user?.profileImageURL {
profileImageView.sd_setImage(with: URL(string: photoURL), placeholderImage: UIImage(named: "industribune-default-no-profile-pic"))
}
}
}
I am displaying this cell on my HomeViewController:
import UIKit
import FirebaseAuth
import FirebaseDatabase
import FirebaseStorage
import Firebase
class HomeViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var activityIndicatorView: UIActivityIndicatorView!
var posts = [UserFile]()
var users = [UserFile]()
override func viewDidLoad() {
super.viewDidLoad()
// for performance set an estimated row height
tableView.estimatedRowHeight = 1
// but also request to dynamically adjust to content using AutoLayout
tableView.rowHeight = UITableViewAutomaticDimension
//tableView.delegate = self
tableView.dataSource = self
loadPosts()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadPosts() {
activityIndicatorView.startAnimating()
API.User.observePosts { (newPost) in
guard let userID = newPost.uid else { return }
self.fetchUser(uid: userID, completed: {
// append the new Post and Reload after the user
// has been cached
self.posts.append(newPost)
self.activityIndicatorView.stopAnimating()
self.tableView.reloadData()
})
}
}
func fetchUser(uid: String, completed: #escaping () -> Void) {
API.User.observeUser(withID: uid) { user in
self.users.append(user)
completed()
}
}
}
extension HomeViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeTableViewCell", for: indexPath) as! HomeTableViewCell
cell.post = posts[indexPath.row]
cell.user = users[indexPath.row]
cell.homeVC = self
return cell
}
}
I have a lot of craziness going on in my project so let me know if you have any questions and what I'm doing wrong. If it's too complicated to understand I'm ready to erase everything and start over too.
And I do honestly think that I followed all the guidelines to ask a question so don't like shut this question down or something.
That's a lot of code. Try this super reduced example. For this, the users node only stores the name as a child node but it could also have an image, email, address, etc.
Example users node
users
uid_0:
name: "Bert"
uid_1:
name: "Ernie"
and some code
var usersArray = [ [String: Any] ]() //an array of dictionaries.
class ViewController: UIViewController {
//set up firebase references here
override func viewDidLoad() {
super.viewDidLoad()
let usersRef = self.ref.child("users")
usersRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
let userDict = snap.value as! [String: Any]
self.usersArray.append(userDict)
}
self.tableView.reloadData()
})
and the tableView delegate methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.usersArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeTableViewCell", for: indexPath) as! HomeTableViewCell
let userDict = self.usersArray[indexPath.row]
cell.text = userDict["name"] as! String
//cell.imge = userDict["image"] etc etc
return cell
}
Now... that all being said. This is the perfect use for an array of UserClass objects instead of the dictionaries.
Here's a starting point....
class UserClass {
var name = ""
var image = ""
func init(snap: DataSnapshot) {
//populate the vars from the snapshot
}
}
var userClassArray = [UserClass]()
Don't copy and paste this as there are probably typos but it should point you in the right direction.
I am currently using a table view to display a menu, in which people can click on the add or subtract buttons to increase/decrease their order.
This table view has approximately 30 items and so you have to scroll down to get to all the menu items. The problem is, when you scroll down, the table view cells above the scroll (that are now hidden) lose the data that they have just contained.
For example, if you have a menu item that you have ordered 2 of an item, that 2 on the label has now turned back to 0. This is very object oriented so I am not sure why this is happening.
My table view class:
#IBOutlet weak var appetizerTableView: UITableView!
var appetizerList = [OrderModel]()
let ref = FIRDatabase.database().reference()
override func viewDidLoad() {
appetizerTableView.delegate = self
appetizerTableView.dataSource = self
ref.child("Broadway").child("AppetizerDishes").observeSingleEventOfType(.Value, withBlock: { snapshot in
if let snapshot = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshot {
print("WILL: \(snap)")
if let postDict = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let post = OrderModel(postkey: key, postData: postDict)
self.appetizerList.append(post)
}
}
}
self.appetizerTableView.reloadData()
})
}
var data=[OrderModel]()
func addButtonAction(addedList:[String:Float]) {
print("WILLCOHEN:\(addedList)")
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return appetizerList.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let post = appetizerList[indexPath.row]
if let cell = appetizerTableView.dequeueReusableCellWithIdentifier("OrderCell") as? OrderCell{
cell.configureCell(post)
cell.delegate = self
return cell
} else {
return OrderCell()
}
}
}
My cell model class:
class OrderModel {
private var _dishName: String!
private var _dishDescription: String!
private var _numberOfOrders: Int!
private var _postKey: String!
private var _dishPrice: Float!
var dishName: String {
return _dishName
}
var dishDescription: String {
return _dishDescription
}
var numberOfOrders: Int {
get {
return _numberOfOrders
}
set (newVal) {
_numberOfOrders = newVal
}
}
var postKey: String {
return _postKey
}
var dishPrice: Float {
return _dishPrice
}
init(dishName: String, dishDescription: String, numberOfOrders: Int) {
self._dishName = dishName
self._dishDescription = dishDescription
}
init(postkey: String, postData: Dictionary<String, AnyObject>) {
self._postKey = postkey
if let dishName = postData["dishName"] as? String {
self._dishName = dishName
}
if let dishDescription = postData["dishDescription"] as? String {
self._dishDescription = dishDescription
}
if let numberOfOrders = postData["anumberOfOrders"] as? Int {
self._numberOfOrders = numberOfOrders
}
if let dishPrice = postData["dishPrice"] as? Float32 {
self._dishPrice = dishPrice
}
}
}
My cell class:
protocol ClassNameDelegate:class {
func addButtonAction(addedList:[String:Float])
}
var addedList: [String:Float] = [:]
class OrderCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
}
var post: OrderModel!
var link: Link!
#IBOutlet weak var dishName: UILabel!
#IBOutlet weak var dishDescriptionAndPrice: UILabel!
#IBOutlet weak var numberOfOrders: UILabel!
#IBOutlet weak var addOrderBtn: UIButton!
#IBOutlet weak var subtractOderBtn: UIButton!
weak var delegate: ClassNameDelegate?
#IBAction func addButtonPressed(sender: AnyObject) {
if post.numberOfOrders == 9 {
numberOfOrders.text = "9"
} else {
if addedList[post.dishName] != nil {
addedList[post.dishName] = post.dishPrice
} else {
addedList["\(post.dishName) \(Int(numberOfOrders.text!)! + 1)"] = post.dishPrice
}
post.numberOfOrders = post.numberOfOrders - 1
numberOfOrders.text = "\(post.numberOfOrders)"
}
if delegate != nil {
delegate?.addButtonAction(addedList)
}
}
#IBAction func subtractButtonPressed(sender: AnyObject) {
if post.numberOfOrders == 0 {
numberOfOrders.text = "0"
} else {
post.numberOfOrders = post.numberOfOrders + 1
numberOfOrders.text = "\(post.numberOfOrders)"
}
}
func getOrders() -> Dictionary<String, Float> {
return addedList
}
func configureCell(post: OrderModel) {
self.post = post
self.dishName.text = post.dishName
self.dishDescriptionAndPrice.text = post.dishDescription
self.numberOfOrders.text = "0"
}
}
I should mention that I am pulling my table view data from Firebase.
Thank you in advance for any help or suggestions, it is very much appreciated.
You are calling configureCell(post:) on every cell, and in the configureCell(post:) function you set the text value of the numbersOfOrders label to "0". You should probably set the text to a value in the OrderModel/post argument.
Also, you should be sure to always call configureCell(post:) (you are not calling it if you have to manually create an OrderCell), so your tableView(tableView:cellForRowAtIndexPath:) function should look like this:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let post = appetizerList[indexPath.row]
let cell = appetizerTableView.dequeueReusableCellWithIdentifier("OrderCell") as? OrderCell ?? OrderCell()
cell.configureCell(post)
cell.delegate = self
return cell
}
I have one screen like the following picture:
I uploaded list with student name by using custom cell as you are seeing and I want when click on save button save the status of student in array , I initialized array with 0 for all student at the first time and when the status of switch is enabled then this value at the clicked cell index converted to 1 but I couldn't make that when the click action happened on switch this is only now happening when click on the cell ( row ) how I can do the same thing when only change the status of switch to update the array without click on complete row at table
Code of main view :
import UIKit
class teacherAttendanceVC: UIViewController , UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var studentlistTable: UITableView!
#IBOutlet weak var loadIndicator: UIActivityIndicatorView!
var username:String?
var classID: String?
var branchID: String?
var normal_id = [String]()
var student_name = [String]()
var student_attendance = [String]()
//Sent Data
var n_id = ""
var stu_name = ""
#IBAction func backButton(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil )
}
override func viewDidLoad() {
super.viewDidLoad()
studentlistTable.delegate = self
studentlistTable.dataSource = self
let prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()
username = prefs.objectForKey("user")as! String
classID = prefs.objectForKey("ClassID")as! String
branchID = prefs.objectForKey("BranchID")as! String
self.loadIndicator.startAnimating()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
self.loadList()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.loadIndicator.stopAnimating()
self.studentlistTable.reloadData()
})
});
}
override func viewDidAppear(animated: Bool) {
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return normal_id.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//This method to define each cell at Table View
let cell = self.studentlistTable.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! teacherAttendanceCell
cell.studentNameLabel.text = student_name[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Get Cell Label
let currentCell = studentlistTable.cellForRowAtIndexPath(indexPath) as! teacherAttendanceCell!
student_attendance[indexPath.row] = currentCell.status
}
#IBAction func saveButton(sender: AnyObject) {
print(student_attendance) // this only to ensure from the final array before sending to server
}
func loadList()
{
var normallink = "myurl"
normallink = normallink + "?classid=" + self.classID! + "&branchid=" + self.branchID!
print(normallink)
var studentParentURL:NSURL = NSURL (string: normallink)!
let data = NSData(contentsOfURL: studentParentURL)!
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
if let alldata = json["data"] as? [[String: AnyObject]] {
for onedata in alldata {
if let no_id = onedata["id"] as? String {
normal_id.append(no_id)
}
if let s_name = onedata["studentName"] as? String {
student_name.append(s_name)
}
}
}
} catch {
print("Error Serializing JSON: \(error)")
}
if(normal_id.count != 0)
{
for i in 1...self.normal_id.count
{
self.student_attendance.append("0")
}
}
print(normal_id.count)
print(student_name.count)
}
}
Cell Code :
class teacherAttendanceCell: UITableViewCell {
#IBOutlet weak var studentNameLabel: UILabel!
#IBOutlet weak var attendSwitch: UISwitch!
var status:String = ""
override func awakeFromNib() {
super.awakeFromNib()
if(attendSwitch.on)
{
status = "1"
print("ON")
}
else{
status = "0"
print("OFF")
}
attendSwitch.addTarget(self, action: "stateChanged:", forControlEvents: UIControlEvents.ValueChanged)
}
func stateChanged(switchState: UISwitch) {
if switchState.on {
status = "1"
print("ON")
} else {
status = "0"
print("OFF")
}
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
#IBAction func attendSwitchChanged(sender: AnyObject) {
}
}
Updated:
Main View Controller:
import UIKit
class teacherAttendanceVC: UIViewController , UITableViewDataSource,UITableViewDelegate,CellInfoDelegate {
#IBOutlet weak var studentlistTable: UITableView!
#IBOutlet weak var loadIndicator: UIActivityIndicatorView!
var username:String?
var classID: String?
var branchID: String?
var normal_id = [String]()
var student_name = [String]()
var student_attendance = [String]()
//Sent Data
var n_id = ""
var stu_name = ""
#IBAction func backButton(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil )
}
override func viewDidLoad() {
super.viewDidLoad()
studentlistTable.delegate = self
studentlistTable.dataSource = self
let prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()
username = prefs.objectForKey("user")as! String
classID = prefs.objectForKey("ClassID")as! String
branchID = prefs.objectForKey("BranchID")as! String
self.loadIndicator.startAnimating()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
self.loadList()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.loadIndicator.stopAnimating()
self.studentlistTable.reloadData()
})
});
}
override func viewDidAppear(animated: Bool) {
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return normal_id.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//This method to define each cell at Table View
let cell = self.studentlistTable.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! teacherAttendanceCell
cell.delegate = self
cell.studentNameLabel.text = student_name[indexPath.row]
student_attendance[indexPath.row] = cell.status
//print(student_attendance.count)
//let currentCell = studentlistTable.cellForRowAtIndexPath(indexPath) as! teacherAttendanceCell!
// student_attendance.append(cell.status)
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Get Cell Label
// let currentCell = studentlistTable.cellForRowAtIndexPath(indexPath) as! teacherAttendanceCell!
// student_attendance[indexPath.row] = currentCell.status
//print("OK Status here!" + String(student_attendance.count))
}
#IBAction func saveButton(sender: AnyObject) {
print(student_attendance)
}
func loadList()
{
var normallink = "mylinkhere"
normallink = normallink + "?classid=" + self.classID! + "&branchid=" + self.branchID!
print(normallink)
var studentParentURL:NSURL = NSURL (string: normallink)!
let data = NSData(contentsOfURL: studentParentURL)!
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
if let alldata = json["data"] as? [[String: AnyObject]] {
for onedata in alldata {
if let no_id = onedata["id"] as? String {
normal_id.append(no_id)
}
if let s_name = onedata["studentName"] as? String {
student_name.append(s_name)
}
}
}
} catch {
print("Error Serializing JSON: \(error)")
}
if(normal_id.count != 0)
{
for i in 1...self.normal_id.count
{
self.student_attendance.append("0")
}
}
print(normal_id.count)
print(student_name.count)
}
func processThatNumber(theStatus: String) {
print("out : \(theStatus)")
}
}
protocol CellInfoDelegate {
func processThatNumber(theStatus: String)
}
Cell View Controller:
import UIKit
class teacherAttendanceCell: UITableViewCell{
#IBOutlet weak var studentNameLabel: UILabel!
#IBOutlet weak var attendSwitch: UISwitch!
var status:String = ""
var delegate: CellInfoDelegate?
override func awakeFromNib() {
super.awakeFromNib()
if(attendSwitch.on)
{
status = "1"
print("ON")
}
else{
status = "0"
print("OFF")
}
attendSwitch.addTarget(self, action: "stateChanged:", forControlEvents: UIControlEvents.ValueChanged)
}
func stateChanged(switchState: UISwitch) {
if switchState.on {
status = "1"
print("ON")
} else {
status = "0"
print("OFF")
}
if let delegate = self.delegate {
delegate.processThatNumber(self.status)
}
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
#IBAction func attendSwitchChanged(sender: AnyObject) {
}
}
There are few ways to do this: using closure or delegate, but I preferred to use delegate.
Create a delegate for your teacherAttendanceCell cell like in this answer https://stackoverflow.com/a/25792213/2739795
Make you teacherAttendanceVC conforms the delegate
Each time when cellForRowAtIndexPath calls set cell.delegate = self. Also return the cell into your delegate method
Call method from delegate insidestateChanged
And when delegate method calls you can get an index if switched cell
tableView.indexPathForCell(cellFromParam)
I have a problem with reload data in tableView in my simple swift app for iOS.
If I for the first time enter the city name into the cityTextField and press the getDataButton, so the data displays correctly, but If I enter the new city name into cityTextField and press button, so data are still the same like for the first city.
ViewController
import UIKit
class ViewController: UIViewController,UITableViewDelegate {
var arrDict :NSMutableArray=[]
#IBOutlet weak var cityTextField: UITextField!
#IBOutlet weak var weatherTableView: UITableView!
#IBAction func getDataButton(sender: AnyObject) {
weatherDataSource("http://api.openweathermap.org/data/2.5/forecast?q=" + cityTextField.text! + "&appid=<app id>")
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func weatherDataSource(urlString: String) {
let urlUTF = urlString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
let url = NSURL(string: urlUTF!)
let query = NSURLSession.sharedSession().dataTaskWithURL(url!) { (data, response, error) in dispatch_async(dispatch_get_main_queue(), { ()
self.loadDataWeather(data!)
self.weatherTableView.reloadData()
})
}
query.resume()
}
func loadDataWeather(dataPocasi: NSData){
do {
if let json = try NSJSONSerialization.JSONObjectWithData(dataPocasi, options: []) as? NSDictionary {
print(json)
for var i = 0 ; i < (json.valueForKey("list") as! NSArray).count ; i++
{
arrDict.addObject((json.valueForKey("list") as! NSArray) .objectAtIndex(i))
}
}
} catch {
print(error)
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return arrDict.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell : TableViewCell! = tableView.dequeueReusableCellWithIdentifier("Cell") as! TableViewCell
if(cell == nil)
{
cell = NSBundle.mainBundle().loadNibNamed("Cell", owner: self, options: nil)[0] as! TableViewCell;
}
let strTitle : NSNumber=arrDict[indexPath.row] .valueForKey("dt") as! NSNumber
let epocTime = NSTimeInterval(strTitle)
let myDate = NSDate(timeIntervalSince1970: epocTime)
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "hh:mm"
let dateString = dateFormatter.stringFromDate(myDate)
cell.dayLabel.text=dateString
let strDescription : NSDictionary=arrDict[indexPath.row] .objectForKey("main") as! NSDictionary
if let bla = strDescription["temp"]{
cell.tempLabel.text=bla.stringValue
}
return cell as TableViewCell
}
}
TableViewCell
import UIKit
class TableViewCell: UITableViewCell{
#IBOutlet weak var dayLabel: UILabel!
#IBOutlet weak var tempLabel: UILabel!
}
You are not instantiating your tableView delegate. Make sure you call self.weatherTableView.delegate = self inside viewDidLoad().
Also, you should create a new arrDict every time you load your data. self.arrDict = [].
In case the above ajustments dont work you should get some time debugging it. Make sure the second request is loading the data and, if so, your self.weatherTableView.reloadData() might not being called. You could try moving it to loadDataWeather().
You can reload tableview in "loadDataWether()" function.
Like,
func loadDataWeather(dataPocasi: NSData){
do {
if let json = try NSJSONSerialization.JSONObjectWithData(dataPocasi, options: []) as? NSDictionary {
print(json)
for var i = 0 ; i < (json.valueForKey("list") as! NSArray).count ; i++
{
arrDict.addObject((json.valueForKey("list") as! NSArray) .objectAtIndex(i))
}
}
} catch {
print(error)
}
self.weatherTableView.reloadData()
}
I have a global variables within view class, I am doing some functions inside viewDidLoad(), and through those functions I assign some values to those global variables (arrays). But when I try to reuse them outside viewDidLoad() I get their count = 0 like this function:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return prodItem.count;
}
Here's my full code:
import UIKit
class NewViewController: UIViewController, UITableViewDelegate {
//define product details vars
var prodLink = [String]();
var prodImg = [String]();
var prodItem = [String]();
var prodDesc = [String]();
var prodPrice = [String]();
var prodSale = [String]();
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//define url
let url = NSURL(string: "https://www.iravin.com/new")!;
//define task
let task = NSURLSession.sharedSession().dataTaskWithURL(url) {(data, response, error) -> Void in
if let urlContent = data {
let webContent = NSString(data: urlContent, encoding: NSUTF8StringEncoding);
let webArray = webContent?.componentsSeparatedByString("<ul class=\"hProductItems clearfix\">");
let webArray2 = webArray?[1].componentsSeparatedByString("</ul>");
var prodArray = webArray2?[0].componentsSeparatedByString("<li class=\"span3 clearfix\">");
prodArray?.removeAtIndex(0);
for oneProd in (prodArray)! {
var prodData = [String]();
prodData = oneProd.componentsSeparatedByString("\n\t\t\t\t\t\t\t<div class=\"thumbnail\">\n\t\t\t\t\t\t\t\t<a href=\"");
prodData.removeAtIndex(0);
prodData = prodData[0].componentsSeparatedByString("\"><img class=\"lazy\" data-src=\"");
self.prodLink.append(prodData[0]);
prodData = prodData[1].componentsSeparatedByString("\" src=\"img/loading.gif\" alt=\"\"></a>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"thumbSetting\">\n\t\t\t\t\t\t\t\t<div class=\"thumbTitle\">\n\t\t\t\t\t\t\t\t\t<h3>\n\t\t\t\t\t\t\t\t\t<span class=\"invarseColor\">");
self.prodImg.append(prodData[0]);
prodData = prodData[1].componentsSeparatedByString("</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"product-desc\">\n\t\t\t\t\t\t\t\t\t<p>");
if prodData[0].containsString("Sale") {
let prodDataSale = prodData[0].componentsSeparatedByString("</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"label label-info\">Sale");
self.prodItem.append(prodDataSale[0]);
prodData = prodData[1].componentsSeparatedByString("</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"thumbPrice\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span>");
self.prodDesc.append(prodData[0]);
prodData = prodData[1].componentsSeparatedByString("</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"thumbButtons\">\n\t\t\t\t\t\t\t\t\t<button rel=\"");
var prodDataPrice = prodData[0].componentsSeparatedByString("<span class=\"strike-through\">");
prodDataPrice = prodDataPrice[1].componentsSeparatedByString("</span>");
self.prodPrice.append(prodDataPrice[0]);
self.prodSale.append(prodDataPrice[1]);
} else {
self.prodItem.append(prodData[0]);
prodData = prodData[1].componentsSeparatedByString("</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"thumbPrice\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span>");
self.prodDesc.append(prodData[0]);
prodData = prodData[1].componentsSeparatedByString("</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div class=\"thumbButtons\">\n\t\t\t\t\t\t\t\t\t<button rel=\"");
self.prodPrice.append(prodData[0]);
self.prodSale.append(prodData[0]);
}
}
}
}
task.resume();
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return prodItem.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// get an instance of your cell
let cell = tableView.dequeueReusableCellWithIdentifier("prodCell", forIndexPath: indexPath) as! MyCustomTableViewCell;
cell.lblProdItem.text = self.prodItem[indexPath.row];
return cell;
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
From ios dev library: Like most networking APIs, the NSURLSession API is highly asynchronous.
You need to reload your tableview after the task has been completed. Right now its starting the task and then looking at the count before it has finished which is why it is 0.
}
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
}
}
task.resume();
}