I have 3 array different array which is cricketMatchArray, soccerMatchArray and tennisMatchArray.I'm display these 3 array data in 3 tableview which is expanding after clicking on header.Now I'm facing an issue table height is not change according to array data.
This output is I'm getting and I want remove that red mark space
for e.g:
if cricket and tennis array having a data and soccer array is empty then soccer table height not changing
I want to change tables height dynamically asper array count.
for e.g
if cricket and tennis array having a data and soccer array is empty then soccer table height should be 0
Here is my code..
class AllLiveMatchesViewController: UIViewController {
#IBOutlet weak var cricketTableView: UITableView!
#IBOutlet weak var soccerTableView: UITableView!
#IBOutlet weak var tennisTableView: UITableView!
var selectedIndx = -1
var thereIsCellTapped = false
var cricketMatchArray = [LiveMatchesData]()
var soccerMatchArray = [LiveMatchesData]()
var tennisMatchArray = [LiveMatchesData]()
override func viewDidLoad() {
super.viewDidLoad()
cricketTableView.dataSource = self
cricketTableView.delegate = self
cricketTableView.separatorStyle = .none
cricketTableView.tableFooterView = UIView()
soccerTableView.dataSource = self
soccerTableView.delegate = self
soccerTableView.separatorStyle = .none
soccerTableView.tableFooterView = UIView()
tennisTableView.dataSource = self
tennisTableView.delegate = self
tennisTableView.separatorStyle = .none
tennisTableView.tableFooterView = UIView()
getCricketMatches()
getSoccerMatches()
getTennisMatches()
}
extension AllLiveMatchesViewController: UITableViewDelegate, UITableViewDataSource{
func numberOfSections(in tableView: UITableView) -> Int {
if tableView == cricketTableView
{
return cricketMatchArray.count
}
else if tableView == soccerTableView
{
return soccerMatchArray.count
}
else if tableView == tennisTableView
{
return tennisMatchArray.count
}
else
{
return 0
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == cricketTableView
{
return cricketMatchArray[section].score.count
}
else if tableView == soccerTableView
{
return soccerMatchArray[section].score.count
}
else if tableView == tennisTableView
{
return tennisMatchArray[section].score.count
}
else
{
return 0
}
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if tableView == cricketTableView
{
let obj = cricketMatchArray[section]
if cricketMatchArray.count == 0
{
return 0
}
else
{
if obj.inplay == true && obj.status == "OPEN"
{
return 50
}
else if obj.inplay == false && obj.status == "OPEN"
{
return 0
}
else
{
return 0
}
}
}
else if tableView == soccerTableView
{
let obj = soccerMatchArray[section]
if obj.inplay == true && obj.status == "OPEN"
{
return 50
}
else if obj.inplay == false && obj.status == "OPEN"
{
return 0
}
else
{
return 0
}
}
else if tableView == tennisTableView
{
let obj = tennisMatchArray[section]
if obj.inplay == true && obj.status == "OPEN"
{
return 50
}
else if obj.inplay == false && obj.status == "OPEN"
{
return 0
}
else
{
return 0
}
}
else
{
return 0
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if tableView == cricketTableView
{
if indexPath.section == selectedIndx && thereIsCellTapped{
return 106
}
else{
return 0
}
}
else if tableView == soccerTableView
{
if indexPath.section == selectedIndx && thereIsCellTapped{
return 106
}
else{
return 0
}
}
else if tableView == tennisTableView
{
if indexPath.section == selectedIndx && thereIsCellTapped{
return 106
}
else{
return 0
}
}
else
{
return 0
}
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
if tableView == cricketTableView
{
if (self.selectedIndx != section) && thereIsCellTapped{
return 0
}
else if (self.selectedIndx == section) && thereIsCellTapped{
return 20
}
else
{
return 0
}
}
else if tableView == soccerTableView
{
if (self.selectedIndx != section) && thereIsCellTapped{
return 0
}
else if (self.selectedIndx == section) && thereIsCellTapped{
return 20
}
else
{
return 0
}
}
else if tableView == tennisTableView
{
if (self.selectedIndx != section) && thereIsCellTapped{
return 0
}
else if (self.selectedIndx == section) && thereIsCellTapped{
return 20
}
else
{
return 0
}
}
else
{
return 0
}
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ExpandExtTableViewCell.self)) as! ExpandExtTableViewCell
if section == selectedIndx && thereIsCellTapped{
cell.footerView.roundCorners(corners: [.bottomLeft,.bottomRight], radius: 10)
}
else
{
cell.footerView.roundCorners(corners: [.bottomLeft,.bottomRight], radius: 0)
}
return cell
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if tableView == cricketTableView
{
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ExpandTableViewCell.self)) as! ExpandTableViewCell
let obj = cricketMatchArray[section]
if obj.inplay == false && obj.status == "CLOSE"
{
cell.liveView.isHidden = true
}
else if obj.inplay == true && obj.status == "OPEN"
{
cell.liveView.isHidden = false
}
cell.sportIcon.image = UIImage(named: "whiteball")
cell.teamNameLabel.text = obj.name ?? ""
cell.btnSelection.tag = section
cell.btnSelection.addTarget(self, action: #selector(AllLiveMatchesViewController.btnSectionClick(sender:)), for: .touchUpInside)
if section == selectedIndx && thereIsCellTapped{
cell.headerView.roundCorners(corners: [.topLeft,.topRight], radius: 10)
}
else
{
cell.headerView.roundCorners(corners: [.topLeft,.topRight,.bottomLeft,.bottomRight], radius: 10)
}
return cell
}
else if tableView == soccerTableView
{
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SoccerExpandTableViewCell.self)) as! SoccerExpandTableViewCell
let obj = soccerMatchArray[section]
if obj.inplay == false && obj.status == "CLOSE"
{
cell.liveView.isHidden = true
}
else if obj.inplay == true && obj.status == "OPEN"
{
cell.liveView.isHidden = false
}
cell.sportIcon.image = UIImage(named: "soccerball")
cell.teamNameLabel.text = obj.name ?? ""
cell.btnSelection2.tag = section
cell.btnSelection2.addTarget(self, action: #selector(AllLiveMatchesViewController.btnSectionClick2(sender:)), for: .touchUpInside)
if section == selectedIndx && thereIsCellTapped{
cell.headerView.roundCorners(corners: [.topLeft,.topRight], radius: 10)
}
else
{
cell.headerView.roundCorners(corners: [.topLeft,.topRight,.bottomLeft,.bottomRight], radius: 10)
}
return cell
}
else if tableView == tennisTableView
{
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TennisExpandTableViewCell.self)) as! TennisExpandTableViewCell
let obj = tennisMatchArray[section]
if obj.inplay == false && obj.status == "CLOSE"
{
cell.liveView.isHidden = true
}
else if obj.inplay == true && obj.status == "OPEN"
{
cell.liveView.isHidden = false
}
cell.sportIcon.image = UIImage(named: "tennisracket")
cell.teamNameLabel.text = obj.name ?? ""
cell.btnSelection3.tag = section
cell.btnSelection3.addTarget(self, action: #selector(AllLiveMatchesViewController.btnSectionClick3(sender:)), for: .touchUpInside)
if section == selectedIndx && thereIsCellTapped{
cell.headerView.roundCorners(corners: [.topLeft,.topRight], radius: 10)
}
else
{
cell.headerView.roundCorners(corners: [.topLeft,.topRight,.bottomLeft,.bottomRight], radius: 10)
}
return cell
}
else
{
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ExpandTableViewCell.self)) as! ExpandTableViewCell
return cell
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ExpandInsideTableViewCell.self)) as! ExpandInsideTableViewCell
if tableView == cricketTableView
{
let ob = cricketMatchArray[indexPath.section]
let obj = cricketMatchArray[indexPath.section].score[indexPath.row]
if obj.spnnation1 == nil
{
let teamName = ob.name?.components(separatedBy: " v ")
let fTeamWords = teamName?[0].split { !$0.isLetter }
let sTeamWords = teamName?[1].split { !$0.isLetter }
if fTeamWords?.count == 1
{
let fTeam = teamName?[0].prefix(3)
cell.firstTeamName.text = fTeam?.description.uppercased()
}
else
{
let fTeam = teamName?[0].getAcronyms()
cell.firstTeamName.text = fTeam
}
if sTeamWords?.count == 1
{
let fTeam = teamName?[1].prefix(3)
cell.secondTeamName.text = fTeam?.description.uppercased()
}
else
{
let fTeam = teamName?[1].getAcronyms()
cell.secondTeamName.text = fTeam
}
cell.firstTeamScore.text = obj.score1
cell.secondTeamScore.text = obj.score2
cell.dateLabel.text = ob.openDate
cell.commonScore.isHidden = true
}
else
{
cell.firstTeamName.text = obj.spnnation1
cell.secondTeamName.text = obj.spnnation2
cell.firstTeamScore.text = obj.score1
cell.secondTeamScore.text = obj.score2
cell.dateLabel.text = ob.openDate
cell.commonScore.isHidden = true
}
}
else if tableView == soccerTableView
{
let ob = soccerMatchArray[indexPath.section]
let obj = soccerMatchArray[indexPath.section].score[indexPath.row]
if obj.spnnation1 == nil
{
let teamName = ob.name?.components(separatedBy: " v ")
let fTeamWords = teamName?[0].split { !$0.isLetter }
let sTeamWords = teamName?[1].split { !$0.isLetter }
if fTeamWords?.count == 1
{
let fTeam = teamName?[0].prefix(3)
cell.firstTeamScore.text = fTeam?.description.uppercased()
}
else
{
let fTeam = teamName?[0].getAcronyms()
cell.firstTeamScore.text = fTeam
}
if sTeamWords?.count == 1
{
let fTeam = teamName?[1].prefix(3)
cell.secondTeamScore.text = fTeam?.description.uppercased()
}
else
{
let fTeam = teamName?[1].getAcronyms()
cell.secondTeamScore.text = fTeam
}
cell.firstTeamName.isHidden = true
cell.secondTeamName.isHidden = true
cell.dateLabel.text = ob.openDate
cell.commonScore.isHidden = false
cell.commonScore.text = "\(obj.score1 ?? "")-\(obj.score2 ?? "")"
}
else
{
cell.firstTeamName.isHidden = true
cell.secondTeamName.isHidden = true
cell.firstTeamScore.text = obj.spnnation1?.getAcronyms()
cell.secondTeamScore.text = obj.spnnation2?.getAcronyms()
cell.dateLabel.text = ob.openDate
cell.commonScore.isHidden = false
cell.commonScore.text = "\(obj.score1 ?? "")-\(obj.score2 ?? "")"
}
}
else if tableView == tennisTableView
{
let ob = tennisMatchArray[indexPath.section]
let obj = tennisMatchArray[indexPath.section].score[indexPath.row]
if obj.spnnation1 == nil
{
let teamName = ob.name?.components(separatedBy: " v ")
let fTeamWords = teamName?[0].split { !$0.isLetter }
let sTeamWords = teamName?[1].split { !$0.isLetter }
if fTeamWords?.count == 1
{
let fTeam = teamName?[0].prefix(3)
cell.firstTeamScore.text = fTeam?.description.uppercased()
}
else
{
let fTeam = teamName?[0].getAcronyms()
cell.firstTeamScore.text = fTeam
}
if sTeamWords?.count == 1
{
let fTeam = teamName?[1].prefix(3)
cell.secondTeamScore.text = fTeam?.description.uppercased()
}
else
{
let fTeam = teamName?[1].getAcronyms()
cell.secondTeamScore.text = fTeam
}
cell.firstTeamName.isHidden = true
cell.secondTeamName.isHidden = true
cell.dateLabel.text = ob.openDate
cell.commonScore.isHidden = false
cell.commonScore.text = "\(obj.score1 ?? "")-\(obj.score2 ?? "")"
}
else
{
cell.firstTeamName.isHidden = true
cell.secondTeamName.isHidden = true
cell.firstTeamScore.text = obj.spnnation1?.getAcronyms()
cell.secondTeamScore.text = obj.spnnation2?.getAcronyms()
cell.dateLabel.text = ob.openDate
cell.commonScore.isHidden = false
cell.commonScore.text = "\(obj.score1 ?? "")-\(obj.score2 ?? "")"
}
}
return cell
}
Can someone help me out with this.
The problem is that you duplicate code but not properties :
if tableView == cricketTableView
{
// This is the problem :
// only one selectedIndx and one thereIsCellTapped but 3 tables, so it give the same result
// for the 3 tables
if (self.selectedIndx != section) && thereIsCellTapped{
return 0
}
else if (self.selectedIndx == section) && thereIsCellTapped{
return 20
}
else
{
return 0
}
}
You have this problem in :
heightForRowAt
heightForFooterInSection
viewForFooterInSection
viewForHeaderInSection
and may in didSelectRowAt
As a curiosity question - why do you have 3 separate tableviews instead of one with sections?
Having 3 different UITableViews in one ViewController is in this case - not needed.
By controlling number of cells in section we can simplify the logic of the view later on.
Tapping on the header should control the logic of "hiding" (= setting number of rows in given section to zero) of other sections.
You can use Single TableView with a cell having StackView in it by giving it Top, Leading, Trailing, Bottom.
Your number of rows in section should be 3. It means you have three cells in it now populate your arrays in each cell.
Your heightForRowAt should be UITableView.automaticDimension
Related
In my application I had make call Json function and table view delegate and datasource methods in view did load but here without loading data from web service it is calling table view methods and inside it is crashing due to having no data from model can anyone help me how to resolve this and this is happening sometimes and sometimes it working properly ?
here is my view did load
let guestAddressURL = "http://magento.selldesk.io/index.php/rest/V1/guest-carts/\(guestkey!)/billing-address"
self.guestShippingaddressURL(guestAddressApi: guestAddressURL)
self.tableDetails.delegate = self
self.tableDetails.dataSource = self
self.tableDetails.tableFooterView?.isHidden = true
self.tableDetails.separatorInset = UIEdgeInsets.zero
self.tableDetails.rowHeight = UITableViewAutomaticDimension
self.tableDetails.estimatedRowHeight = 50
self.title = "Checkout"
here is my Json function
func guestShippingaddressURL(guestAddressApi: String) {
print(guestAddressApi)
let url = URL(string: guestAddressApi)
var request = URLRequest(url: url! as URL)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil { print(error!); return }
do {
if let jsonObj = try JSONSerialization.jsonObject(with: data!) as? [String:Any] {
let obj = jsonObj["street"] as! [String]
for item in obj {
self.street = item
}
print(obj)
print(self.street)
self.guestShippingAddressModel = GuestAddress.init(dict: jsonObj)
if self.street?.isEmpty == false {
self.addressSelected = true
self.selected = false
}
DispatchQueue.main.async {
self.tableDetails.reloadData()
}
}
} catch {
print(error)
}
}
task.resume()
}
func numberOfSections(in tableView: UITableView) -> Int {
if self.street?.isEmpty == false{
return 3
}
else {
if ((addressSelected == true || checkIsPaymentRadioSelect == true) && selected == false) {
return 3
}else {
return 2
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
if ((addressSelected == true || checkIsPaymentRadioSelect == true) && selected == false) {
if (section == 0)
{
return 1
}
else if (section == 1)
{
return 1
}
else
{
return 1
}
}
else
{
if (section == 0)
{
return 1
}
else
{
return 1
}
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if ((addressSelected == true || checkIsPaymentRadioSelect == true) && selected == false){
if (indexPath.section == 0) {
return UITableViewAutomaticDimension
}
else if (indexPath.section == 1) {
return 62
}
else {
if height == 0 {
return CGFloat(heightStart)
}
else{
return CGFloat(self.height)
}
}
}
else{
if (indexPath.section == 0){
if self.street?.isEmpty == true{
return 50
}else {
return UITableViewAutomaticDimension
}
}
else if (indexPath.section == 1){
return 62
}
else {
return 0
}
}
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int){
let header = view as! UITableViewHeaderFooterView
header.textLabel?.textColor = UIColor.gray
header.textLabel?.textAlignment = NSTextAlignment.center
header.textLabel?.font = UIFont(name: "Futura", size: 17)
}
The tableview will start loading whether your JSON call has finished or not. This happens automatically after viewDidLoad finishes .. it doesn't wait for the reloadData() call in your completion handler.
So you need to setup your numberOfSections to return 0 until the data has been loaded. This way, your table will be empty (and cellForRow will not even be called) until the completion handler puts the data in place and calls reloadData(). At which time, your numberOfSections will return non-zero and your data will be displayed.
You should initialize all your variables used inside table view methods with some default values.
Like: var street: String! = "" , var addressSelected: Bool! = false etc.
Because even before the API is called, some of these values are nil or not set.
For cell.nameLabel.text = "\((dict?.firstName)!) \, you can return 0 in numberOfRows method.
guard let _ = dict {
return 0
}
You can do it by set your Delegate and DataSource in web Service call Back.
DispatchQueue.main.async {
self.tableDetails.delegate = self
self.tableDetails.dataSource = self
self.tableDetails.reloadData()
}
hope it works.
I have a table view with two different prototype cells.
The second prototype cell has a custom Label, but when I execute the project it's showing nothing. The text is there (I know because it's printing) but it's not appearing.
TableView Storyboard
Simulator: Image cell ok, but text cell is empty
-> TableViewController:
import UIKit
import Twitter
class TweetMentionsTableViewController: UITableViewController
{
lazy var images: [MediaItem] = []
lazy var userMentions: [Mention]? = []
lazy var hashtags: [Mention]? = []
lazy var urls: [Mention]? = []
var tweet: Twitter.Tweet?
private enum MentionTypes {
case Images
case Hashtags
case Users
case URLs
}
private var mentionsCollection: Dictionary<MentionTypes, Bool> = [
MentionTypes.Images: false,
MentionTypes.Hashtags: false,
MentionTypes.Users: false,
MentionTypes.URLs: false
]
private var sectionTypes: Dictionary<MentionTypes, Int?> = [
MentionTypes.Images: nil,
MentionTypes.Hashtags: nil,
MentionTypes.Users: nil,
MentionTypes.URLs: nil
]
override func numberOfSections(in tableView: UITableView) -> Int {
var count = 0
if !(tweet?.media.isEmpty)! {
mentionsCollection[MentionTypes.Images] = true
count += 1
}
if !(tweet?.hashtags.isEmpty)! {
mentionsCollection[MentionTypes.Hashtags] = true
count += 1
}
if !(tweet?.userMentions.isEmpty)! {
mentionsCollection[MentionTypes.Users] = true
count += 1
}
if !(tweet?.urls.isEmpty)! {
mentionsCollection[MentionTypes.URLs] = true
count += 1
}
return count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if mentionsCollection[MentionTypes.Images] == true {
sectionTypes[MentionTypes.Images] = section
mentionsCollection[MentionTypes.Images] = false
return (tweet?.media.count)!
} else if mentionsCollection[MentionTypes.Hashtags] == true {
sectionTypes[MentionTypes.Hashtags] = section
mentionsCollection[MentionTypes.Hashtags] = false
return (tweet?.hashtags.count)!
} else if mentionsCollection[MentionTypes.Users] == true {
sectionTypes[MentionTypes.Users] = section
mentionsCollection[MentionTypes.Users] = false
return (tweet?.userMentions.count)!
} else if mentionsCollection[MentionTypes.URLs] == true {
sectionTypes[MentionTypes.URLs] = section
mentionsCollection[MentionTypes.URLs] = false
return (tweet?.urls.count)!
}
return 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//let data = temp[indexPath.row][indexPath.section]
let cell = tableView.dequeueReusableCell(withIdentifier: "TweetMention", for: indexPath)
// Configure the cell...
if let sec = sectionTypes[MentionTypes.Images], indexPath.section == sec {
let image = tweet?.media[indexPath.row].url
if let tweetMentionCell = cell as? TweetMentionsTableViewCell {
tweetMentionCell.imageURL = image!
return cell
}
}
let cell2 = tableView.dequeueReusableCell(withIdentifier: "TweetMention2Cell", for: indexPath)
if let sec = sectionTypes[MentionTypes.Hashtags], indexPath.section == sec {
let hashtag = tweet?.hashtags[indexPath.row]
if let tweetMentionCell = cell2 as? TweetMentions2TableViewCell {
tweetMentionCell.hashtag = (hashtag?.keyword)!
}
} else if let sec = sectionTypes[MentionTypes.Users], indexPath.section == sec {
let userMention = tweet?.userMentions[indexPath.row]
if let tweetMentionCell = cell2 as? TweetMentions2TableViewCell {
tweetMentionCell.userMention = (userMention?.keyword)!
}
} else if let sec = sectionTypes[MentionTypes.URLs], indexPath.section == sec {
let url = tweet?.urls[indexPath.row]
if let tweetMentionCell = cell2 as? TweetMentions2TableViewCell {
tweetMentionCell.url = (url?.keyword)!
}
}
return cell2
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if let sec = sectionTypes[MentionTypes.Images], section == sec {
return "Images"
} else if let sec = sectionTypes[MentionTypes.Hashtags], section == sec {
return "Hashtags"
} else if let sec = sectionTypes[MentionTypes.Users], section == sec {
return "Users"
} else if let sec = sectionTypes[MentionTypes.URLs], section == sec {
return "URLs"
}
return nil
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let cell = sender as? TweetMentionsTableViewCell {
if segue.identifier == "Show Image" {
if let imageVC = segue.destination as? ImageViewController {
imageVC.imageURL = cell.imageURL?.absoluteURL
//imageVC.imageRatio = tweet?.media[0].aspectRatio
}
}
}
if let cell = sender as? TweetMentions2TableViewCell {
if segue.identifier == "Show Text" {
if let mentionsSTTVC = segue.destination as? MentionsSearchTweetTableViewController {
if let text = cell.mentLabel {
mentionsSTTVC.mentionToSearch = text.text!
}
}
}
}
}
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if let cell = sender as? TweetMentions2TableViewCell {
if (cell.url.contains("http")) {
UIApplication.shared.open(NSURL(string: cell.url)! as URL)
return false
}
}
return true
}
}
-> TableViewCell:
import UIKit
class TweetMentions2TableViewCell: UITableViewCell
{
#IBOutlet weak var mentLabel: UILabel!
var userMention = "" {
didSet {
updateUI(mentionType: 2)
}
}
var hashtag = "" {
didSet {
updateUI(mentionType: 1)
}
}
var url = "" {
didSet {
updateUI(mentionType: 3)
}
}
func updateUI(mentionType: Int) {
if mentionType == 1 {
mentLabel.text = hashtag
} else if mentionType == 2 {
mentLabel.text = userMention
} else if mentionType == 3 {
mentLabel.text = url
}
print(mentLabel.text!)
}
}
I have a tableView currently that is being populated with content from a firebase database. I am able to print out the specific information that is to be populated in the cells, and the cells physically are being populated indicated by the ability to scroll the appropriate length of the populated data. I am not sure as to why it would be accessing the information and populating the cells, but not inserting the data into the cells?
TableView:
import UIKit
import FirebaseAuth
import FirebaseStorage
class Articles: UITableViewController {
var vcType:String = "Home"
//var valueTopass = [[String:String]]()
var rooms = [Room]()
var articleCell = ArticlesCell()
#IBOutlet weak var menuButton: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
if self.vcType == "Home"
{
self.rooms += ArticlesManager.sharedClient.rooms
}
else
{
if let obj = ArticlesManager.sharedClient.catRooms[self.vcType.lowercased()] //as? [Room]
{
self.rooms += obj
}
}
self.tableView.reloadData()
ArticlesManager.sharedClient.blockValueChangeInRoomArray = {
newRoom in
if self.vcType == "Home"
{
self.rooms.append(newRoom)
self.rooms.sort(by: {
if $0.created_Date == nil
{
return false
}
if $1.created_Date == nil
{
return true
}
return $0.created_Date.compare($1.created_Date) == ComparisonResult.orderedDescending
})
}
else
{
if self.vcType.lowercased() == newRoom.category
{
self.rooms.append(newRoom)
self.rooms.sort(by: {
if $0.created_Date == nil
{
return false
}
if $1.created_Date == nil
{
return true
}
return $0.created_Date.compare($1.created_Date) == ComparisonResult.orderedDescending
})
self.tableView.reloadData()
}
}
}
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return rooms.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (indexPath as NSIndexPath).row == 0 {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "featured", for: indexPath) as! featuredCell
let room = rooms[(indexPath as NSIndexPath).row]
cell2.configureCell(room)
self.tableView.reloadData()
return cell2
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ArticlesCell
let room = rooms[(indexPath as NSIndexPath).row]
cell.configureCell(room)
self.tableView.reloadData()
return cell
}
}
}
ArticleManager:
import UIKit
class ArticlesManager: NSObject {
static let sharedClient = ArticlesManager()
var dateFormater:DateFormatter{
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd HH:mm:ss a z"
return df
}
var roomsitems = ["Home", "News", "Features", "Opinion", "Sports", "Entertainment", "Editor"]
var rooms = [Room]()
var catRooms = [String:[Room]]()
var blockValueChangeInRoomArray:((Room) -> ())!
func fetchData()
{
Data.dataService.fetchData {
(room) in
self.rooms.append(room)
self.rooms.sort(by: {
if $0.created_Date == nil
{
return false
}
if $1.created_Date == nil
{
return true
}
return $0.created_Date.compare($1.created_Date) == ComparisonResult.orderedDescending
})
if let obj = self.catRooms[room.category] //as? [Room]
{
var objRooms = obj
objRooms.append(room)
objRooms.sort(by: {
if $0.created_Date == nil
{
return false
}
if $1.created_Date == nil
{
return true
}
return $0.created_Date.compare($1.created_Date) == ComparisonResult.orderedDescending })
self.catRooms[room.category] = objRooms
}
else
{
self.catRooms[room.category] = [room]
}
if self.blockValueChangeInRoomArray != nil
{
self.blockValueChangeInRoomArray(room)
}
}
}
}
DataService:
import UIKit
class ArticlesManager: NSObject {
static let sharedClient = ArticlesManager()
var dateFormater:DateFormatter{
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd HH:mm:ss a z"
return df
}
var roomsitems = ["Home", "News", "Features", "Opinion", "Sports", "Entertainment", "Editor"]
var rooms = [Room]()
var catRooms = [String:[Room]]()
var blockValueChangeInRoomArray:((Room) -> ())!
func fetchData()
{
Data.dataService.fetchData {
(room) in
self.rooms.append(room)
self.rooms.sort(by: {
if $0.created_Date == nil
{
return false
}
if $1.created_Date == nil
{
return true
}
return $0.created_Date.compare($1.created_Date) == ComparisonResult.orderedDescending
})
if let obj = self.catRooms[room.category] //as? [Room]
{
var objRooms = obj
objRooms.append(room)
objRooms.sort(by: {
if $0.created_Date == nil
{
return false
}
if $1.created_Date == nil
{
return true
}
return $0.created_Date.compare($1.created_Date) == ComparisonResult.orderedDescending })
self.catRooms[room.category] = objRooms
}
else
{
self.catRooms[room.category] = [room]
}
if self.blockValueChangeInRoomArray != nil
{
self.blockValueChangeInRoomArray(room)
}
}
}
}
Remove this line of code from cellForRowAt indexPath method:
self.tableView.reloadData()
This is reloading Table continuously without giving it chance to configureCell and display data.
I had been able to figure out the particular issue that I was having. As I am using firebase, the rules as to who could "read" was, as default, set to authenticated users. In order to change this, you must go into the firebase console and either change it to public or authenticate users before loading the table view. Either way, I hope this was able to help you!
I have a tableViewCell that contains 8 images total divided into two blocks (4 images in each block). These images are downloaded asynchronously and stored into an array and then used in the the tableViewCell's cellForRowAtIndexPath to populate the images. I reload the tableView when all the images for one block has been added to the array in the dictionary (groupTOImages). The way I am doing it, I am getting out of order inconsistent results with the loading of the data. Some images are loaded into places where they shouldn't be. Is there a way to download the images and get consistent results in the tableViewCell.
var groupNames = [NSManagedObject]()
var groupTOPeople = [NSManagedObject: [String]]()
var groupTOImages = [NSManagedObject: [UIImage]]()
func getGroups() {
...
for group in groupNames {
groupTOImages[group] = []
if let people = groupTOPeople[group] {
var mycount = 0
for peeps in people {
InstagramEngine.sharedEngine().getUserDetails(peeps, withSuccess: { user in
if let ppic = user.profilePictureURL {
let picUrl = ppic.absoluteString
print(picUrl)
ImageLoader.sharedLoader.imageForUrl(picUrl) { (image, url) -> () in
self.groupTOImages[group]?.append(image!)
mycount++
if mycount == people.count {
self.tableView.reloadData()
}
}
} else {
self.groupTOImages[group]?.append(UIImage())
mycount++
if mycount == people.count {
self.tableView.reloadData()
}
}
}, failure: nil )
}
}
}
var counter = 0
var groupCount = 0
var groupCounter = 0
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellInfo = GroupCellsArray[indexPath.section]
...
case .userGroups:
let cell = tableView.dequeueReusableCellWithIdentifier(cellInfo.description, forIndexPath: indexPath) as! GroupTableViewCell
if groupNames.count > 0 {
var gp = groupNames[groupCounter]
switch counter {
case 0:
cell.firstTitle.text = (gp.valueForKey("name") as! String)
if let ourImages = groupTOImages[gp] {
for image in ourImages {
print(image.description)
print("groupCount \(groupCounter)")
cell.firstUserButtons[groupCount].layer.borderWidth = 0
cell.firstUserButtons[groupCount].setImage(image, forState: .Normal)
groupCount++
if groupCount == ourImages.count {
groupCount = 0
counter++
groupCounter++
gp = groupNames[groupCounter]
}
}
}
case 1:
if let title = gp.valueForKey("name") as? String {
cell.secondTitle.text = title
if let ourImages = groupTOImages[gp] {
for image in ourImages {
cell.secondUserButtons[groupCount].layer.borderWidth = 0
cell.secondUserButtons[groupCount].setImage(image, forState: .Normal)
groupCount++
if groupCount == ourImages.count {
groupCount = 0
counter = 0
groupCounter++
gp = groupNames[groupCounter]
}
}
}
} else {
cell.secondTitle.text = "Title"
}
default:
break
}
Each row looks like the picture below:
Code using ImageLoader in cellForRowAtIndexPath:
var counter = 0
for group in groupNames {
print("in the second")
groupTOImages[group] = []
if let people = groupTOPeople[group] {
var mycount = 0
for peeps in people {
InstagramEngine.sharedEngine().getUserDetails(peeps, withSuccess: { user in
if let ppic = user.profilePictureURL {
let picUrl = ppic.absoluteString
self.groupTOImages[group]?.append(picUrl)
counter++
mycount++
if counter == self.groupNames.count && mycount == people.count
{
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
}
} else {
self.groupTOImages[group]?.append(nil)
counter++
mycount++
if counter == self.groupNames.count && mycount == people.count
{
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
}
}
}, failure: nil )
}
}
if groupNames.count > 0 {
var gp = groupNames[groupCounter]
print("counter!!!!")
print("groupCount \(counter)")
switch counter {
case 0:
if let ourImages = groupTOImages[gp] {
cell.firstTitle.text = (gp.valueForKey("name") as! String)
print(cell.firstTitle.text)
for image in ourImages {
if let url = image {
print("I get in here")
ImageLoader.sharedLoader.imageForUrl(url) { (image, url) -> () in
cell.firstUserButtons[self.groupCount].layer.borderWidth = 0
cell.firstUserButtons[self.groupCount].setImage(image, forState: .Normal)
self.groupCount++
if self.groupCount == ourImages.count {
self.groupCount = 0
self.counter++
self.groupCounter++
gp = self.groupNames[self.groupCounter]
}
}
} else {
self.groupCount++
if self.groupCount == ourImages.count {
self.groupCount = 0
self.counter++
self.groupCounter++
gp = self.groupNames[self.groupCounter]
}
}
}
}
case 1:
if let title = gp.valueForKey("name") as? String {
cell.secondTitle.text = title
if let ourImages = groupTOImages[gp] {
for image in ourImages {
if let url = image {
ImageLoader.sharedLoader.imageForUrl(url) { (image, url) -> () in
cell.secondUserButtons[self.groupCount].layer.borderWidth = 0
cell.secondUserButtons[self.groupCount].setImage(image, forState: .Normal)
self.groupCount++
if self.groupCount == ourImages.count {
self.groupCount = 0
self.counter++
self.groupCounter++
gp = self.groupNames[self.groupCounter]
}
}
} else {
self.groupCount++
if self.groupCount == ourImages.count {
self.groupCount = 0
self.counter = 0
self.groupCounter++
gp = self.groupNames[self.groupCounter]
}
}
}
}
} else {
cell.secondTitle.text = "Title"
}
You should replace the self.tableView.reloadData() with
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
Hope this helps!
Good Morning
I've a table view with multipel selection enabled of maximum 5 cells .. above it there is a list of 5 buttons and images .. when the user clicked on a cell a photo shall appear in the first empty imageViewabove the table, and when the user clicks on that photo it should disaapear and the cell color return to clear or white color in my case.
my problem is, when i click on a photo which cell is not shown because of scrolling, the app crashes. can you please help me .. how can i check if the indexpath is shown or not because the problem happened when it is not
here is my code :
#IBAction func btnClicked (sender : UIButton)
{
let tester = sender
if (tester == btn1 && img1.image != nil)
{
img1.image = nil
let cell1 = myTable.cellForRowAtIndexPath(img1IP)! as CustomCell
selectedIndexPaths.removeObject(img1IP)
configure(cell1, forRowAtIndexPath: img1IP)
counter--
}
else if (tester == btn2 && img2.image != nil)
{
img2.image = nil
let cell2 = myTable.cellForRowAtIndexPath(img2IP)! as CustomCell
selectedIndexPaths.removeObject(img2IP)
configure(cell2, forRowAtIndexPath: img2IP)
counter--
}
else if (tester == btn3 && img3.image != nil)
{
img3.image = nil
let cell3 = myTable.cellForRowAtIndexPath(img3IP)! as CustomCell
selectedIndexPaths.removeObject(img3IP)
configure(cell3, forRowAtIndexPath: img3IP)
counter--
}
else if (tester == btn4 && img4.image != nil)
{
img4.image = nil
let cell4 = myTable.cellForRowAtIndexPath(img4IP)! as CustomCell
selectedIndexPaths.removeObject(img4IP)
configure(cell4, forRowAtIndexPath: img4IP)
counter--
}
else if (tester == btn5 && img5.image != nil)
{
img5.image = nil
let cell5 = myTable.cellForRowAtIndexPath(img5IP)! as CustomCell
selectedIndexPaths.removeObject(img5IP)
configure(cell5, forRowAtIndexPath: img5IP)
counter--
}
else
{
println("its already empty")
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("intrest", forIndexPath: indexPath) as CustomCell
cell.selectionStyle = .None
cell.backgroundColor = UIColor.clearColor()
configure(cell, forRowAtIndexPath: indexPath)
return cell
}
func configure(cell: CustomCell, forRowAtIndexPath indexPath: NSIndexPath) {
cell.lblInCell.text = InterstArr[indexPath.row]
if selectedIndexPaths.containsObject(indexPath) {
// selected
cell.imgInCell.backgroundColor = UIColor.redColor()
}
else if (selectedIndexPaths.containsObject(indexPath) == false ) {
// not selected
cell.imgInCell.backgroundColor = UIColor.whiteColor()
cell.lblInCell.backgroundColor = UIColor.whiteColor()
}
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if selectedIndexPaths.containsObject(indexPath) {
// deselect
println("remove object")
selectedIndexPaths.removeObject(indexPath)
////////////
if (img1str == InterstArr[indexPath.row])
{
img1.image = nil
println("remove 1 object")
}
else if ( img2str == InterstArr[indexPath.row])
{
img2.image = nil
println("remove 2 object")
}
else if (img3str == InterstArr[indexPath.row])
{
img3.image = nil
println("remove 3 object")
}
else if (img4str == InterstArr[indexPath.row])
{
img4.image = nil
println("remove 4 object")
}
else if ( img5str == InterstArr[indexPath.row])
{
img5.image = nil
println("remove 5 object")
}
counter--
// println(counter)
}
else if !(selectedIndexPaths.containsObject(indexPath)) {
// select
if (counter <= 4){
if (img1.image == nil)
{
img1str = InterstArr[indexPath.row]
img1.image = UIImage(named: InterstArr[indexPath.row])
img1IP = indexPath
println("add 1 object")
}
else if (img2.image == nil)
{
img2str = InterstArr[indexPath.row]
img2IP = indexPath
img2.image = UIImage(named: InterstArr[indexPath.row])
println("add 2 object")
}
else if (img3.image == nil)
{
img3str = InterstArr[indexPath.row]
img3IP = indexPath
img3.image = UIImage(named: InterstArr[indexPath.row])
println("add 3 object")
}
else if (img4.image == nil)
{
img4str = InterstArr[indexPath.row]
img4IP = indexPath
img4.image = UIImage(named: InterstArr[indexPath.row])
println("add 4 object")
}
else if (img5.image == nil)
{
img5str = InterstArr[indexPath.row]
img5IP = indexPath
img5.image = UIImage(named: InterstArr[indexPath.row])
println("add 5 object")
}
selectedIndexPaths.addObject(indexPath)
counter++
}
else if (counter > 4)
{
println("you selected 5 already")
}
}
let cell = tableView.cellForRowAtIndexPath(indexPath)! as CustomCell
configure(cell, forRowAtIndexPath: indexPath)
}
Ok then .. the problem was how to check if the indexPath is shown, so here is my answer for those who have the same problem, as an example i posted only one part of the function and you can repeat if (tester == btn1 && img1.image != nil) for the other buttons .. the line to check if the indexPath is visible is this one if ((myTable.cellForRowAtIndexPath(img1IP)) != nil) :
#IBAction func btn1Clicked (sender : UIButton)
{
let tester = sender
if (tester == btn1 && img1.image != nil)
{
if ((myTable.cellForRowAtIndexPath(img1IP)) != nil)
{
println("1 exist")
let cell:CustomCell = myTable.cellForRowAtIndexPath(img1IP) as CustomCell!
cell.imgInCell.backgroundColor = UIColor.whiteColor()
img1.image = nil
selectedIndexPaths.removeObject(img1IP)
}
else
{
img1.image = nil
selectedIndexPaths.removeObject(img1IP)
}
}