UIStackViews are collapsing inside of another UIStackView and TableView - ios

Pretty new to this so I appreciate any and all help here.
I've spent a lot of time perusing the web and trying different solutions but I'm at a loss.
I'm using tableView to populate events within a view. These events can have multiple participants (2 - 8) The participants (and other objects) are represented by sub-stackviews and I control whether or not to display stackView7, stackView8, etc. based on the count of an array of participants.
For some reason, sometimes, one or a few of the participant stackViews is being crushed to a smaller size.
I'm sorry there's so much code attached but I'm really not sure what will be relevant.
Thank you in advance and let me know if different code is needed for context
Image with error
Image as it should be
Example of stackView layout
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "challengeCell", for: indexPath)
let participant1Photo = cell.viewWithTag(10) as! UIImageView
let participant1Name = cell.viewWithTag(11) as! UILabel
let participant2Photo = cell.viewWithTag(20) as! UIImageView
let participant2Name = cell.viewWithTag(21) as! UILabel
let participant3Stack = cell.viewWithTag(3)
let participant3Photo = cell.viewWithTag(30) as! UIImageView
let participant3Name = cell.viewWithTag(31) as! UILabel
let participant4Stack = cell.viewWithTag(4)
let participant4Photo = cell.viewWithTag(40) as! UIImageView
let participant4Name = cell.viewWithTag(41) as! UILabel
let participant5Stack = cell.viewWithTag(5)
let participant5Photo = cell.viewWithTag(50) as! UIImageView
let participant5Name = cell.viewWithTag(51) as! UILabel
let participant6Stack = cell.viewWithTag(6)
let participant6Photo = cell.viewWithTag(60) as! UIImageView
let participant6Name = cell.viewWithTag(61) as! UILabel
let participant7Stack = cell.viewWithTag(7)
let participant7Photo = cell.viewWithTag(70) as! UIImageView
let participant7Name = cell.viewWithTag(71) as! UILabel
let participant8Stack = cell.viewWithTag(8)
let participant8Photo = cell.viewWithTag(80) as! UIImageView
let participant8Name = cell.viewWithTag(81) as! UILabel
//set up stacks
participant3Stack?.isHidden = true
participant4Stack?.isHidden = true
participant5Stack?.isHidden = true
participant6Stack?.isHidden = true
participant7Stack?.isHidden = true
participant8Stack?.isHidden = true
//MARK: participant1
if challenges[indexPath.row].confirmed?.contains(challenges[indexPath.row].participants![0]) == true {
participant1Accepted.image = UIImage(systemName: "person.fill.checkmark")
participant1Accepted.tintColor = UIColor.systemGreen
} else if challenges[indexPath.row].denied?.contains(challenges[indexPath.row].participants![0]) == true {
participant1Accepted.image = UIImage(systemName: "person.fill.xmark")
participant1Accepted.tintColor = UIColor.systemRed
}
if currUserID == challenges[indexPath.row].participants![0] {
participant1Name.text = "You"
} else {
participant1Name.text = challenges[indexPath.row].senderUserName
}
UserActivityService.getUserActivity(userActivityID: String(challenges[indexPath.row].senderUserID! + challenges[indexPath.row].activity!)) { (userActivity) in
participant1Average.text = String((userActivity?.averageScore)!)
participant1Best.text = String((userActivity?.bestScore)!)
if (userActivity?.played)! < 1 {
participant1Win.text = "0%"
} else {
participant1Win.text = String("\((((userActivity?.wins)! / (userActivity?.played)!) * 1000).rounded() / 10)%")
}
}
//MARK: participant2
if challenges[indexPath.row].confirmed?.contains(challenges[indexPath.row].participants![1]) == true {
participant2Accepted.image = UIImage(systemName: "person.fill.checkmark")
participant2Accepted.tintColor = UIColor.systemGreen
} else if challenges[indexPath.row].denied?.contains(challenges[indexPath.row].participants![1]) == true {
participant2Accepted.image = UIImage(systemName: "person.fill.xmark")
participant2Accepted.tintColor = UIColor.systemRed
}
if currUserID == challenges[indexPath.row].participants![1] {
participant2Name.text = "You"
} else {
participant2Name.text = challenges[indexPath.row].receiverUserName
}
UserActivityService.getUserActivity(userActivityID: String(challenges[indexPath.row].receiverUserID! + challenges[indexPath.row].activity!)) { (userActivity) in
participant2Average.text = String((userActivity?.averageScore)!)
participant2Best.text = String((userActivity?.bestScore)!)
if (userActivity?.played)! < 1 {
participant2Win.text = "0%"
} else {
participant2Win.text = String("\((((userActivity?.wins)! / (userActivity?.played)!) * 1000).rounded() / 10)%")
}
}
//MARK: participant3
if challenges[indexPath.row].participants!.count > 2 {
if currUserID == challenges[indexPath.row].participants![2] {
participant3Name.text = "You"
} else {
UserService.getUserName(userID: challenges[indexPath.row].participants![2]) { (userNameData) in
participant3Name.text = userNameData
}
}
if challenges[indexPath.row].confirmed?.contains(challenges[indexPath.row].participants![2]) == true {
participant3Accepted.image = UIImage(systemName: "person.fill.checkmark")
participant3Accepted.tintColor = UIColor.systemGreen
} else if challenges[indexPath.row].denied?.contains(challenges[indexPath.row].participants![2]) == true {
participant3Accepted.image = UIImage(systemName: "person.fill.xmark")
participant3Accepted.tintColor = UIColor.systemRed
}
participant3Stack?.isHidden = false
UserActivityService.getUserActivity(userActivityID: String(challenges[indexPath.row].participants![2] + challenges[indexPath.row].activity!)) { (userActivity) in
participant3Average.text = String((userActivity?.averageScore)!)
participant3Best.text = String((userActivity?.bestScore)!)
if (userActivity?.played)! < 1 {
participant3Win.text = "0%"
} else {
participant3Win.text = String("\((((userActivity?.wins)! / (userActivity?.played)!) * 1000).rounded() / 10)%")
}
}
//MARK: participant4
if challenges[indexPath.row].participants!.count > 3 {
if currUserID == challenges[indexPath.row].participants![3] {
participant4Name.text = "You"
} else {
UserService.getUserName(userID: challenges[indexPath.row].participants![3]) { (userNameData) in
participant4Name.text = userNameData
}
}
if challenges[indexPath.row].confirmed?.contains(challenges[indexPath.row].participants![3]) == true {
participant4Accepted.image = UIImage(systemName: "person.fill.checkmark")
participant4Accepted.tintColor = UIColor.systemGreen
} else if challenges[indexPath.row].denied?.contains(challenges[indexPath.row].participants![3]) == true {
participant4Accepted.image = UIImage(systemName: "person.fill.xmark")
participant4Accepted.tintColor = UIColor.systemRed
}
participant4Stack?.isHidden = false
UserActivityService.getUserActivity(userActivityID: String(challenges[indexPath.row].participants![3] + challenges[indexPath.row].activity!)) { (userActivity) in
participant4Average.text = String((userActivity?.averageScore)!)
participant4Best.text = String((userActivity?.bestScore)!)
if (userActivity?.played)! < 1 {
participant4Win.text = "0%"
} else {
participant4Win.text = String("\((((userActivity?.wins)! / (userActivity?.played)!) * 1000).rounded() / 10)%")
}
}
//MARK: participant5
if challenges[indexPath.row].participants!.count > 4 {
if currUserID == challenges[indexPath.row].participants![4] {
participant5Name.text = "You"
} else {
UserService.getUserName(userID: challenges[indexPath.row].participants![4]) { (userNameData) in
participant5Name.text = userNameData
}
}
if challenges[indexPath.row].confirmed?.contains(challenges[indexPath.row].participants![4]) == true {
participant5Accepted.image = UIImage(systemName: "person.fill.checkmark")
participant5Accepted.tintColor = UIColor.systemGreen
} else if challenges[indexPath.row].denied?.contains(challenges[indexPath.row].participants![4]) == true {
participant5Accepted.image = UIImage(systemName: "person.fill.xmark")
participant5Accepted.tintColor = UIColor.systemRed
}
participant5Stack?.isHidden = false
UserActivityService.getUserActivity(userActivityID: String(challenges[indexPath.row].participants![4] + challenges[indexPath.row].activity!)) { (userActivity) in
participant5Average.text = String((userActivity?.averageScore)!)
participant5Best.text = String((userActivity?.bestScore)!)
if (userActivity?.played)! < 1 {
participant5Win.text = "0%"
} else {
participant5Win.text = String("\((((userActivity?.wins)! / (userActivity?.played)!) * 1000).rounded() / 10)%")
}
}
//MARK: participant6
if challenges[indexPath.row].participants!.count > 5 {
if currUserID == challenges[indexPath.row].participants![5] {
participant6Name.text = "You"
} else {
UserService.getUserName(userID: challenges[indexPath.row].participants![5]) { (userNameData) in
participant6Name.text = userNameData
}
}
if challenges[indexPath.row].confirmed?.contains(challenges[indexPath.row].participants![5]) == true {
participant6Accepted.image = UIImage(systemName: "person.fill.checkmark")
participant6Accepted.tintColor = UIColor.systemGreen
} else if challenges[indexPath.row].denied?.contains(challenges[indexPath.row].participants![5]) == true {
participant6Accepted.image = UIImage(systemName: "person.fill.xmark")
participant6Accepted.tintColor = UIColor.systemRed
}
participant6Stack?.isHidden = false
UserActivityService.getUserActivity(userActivityID: String(challenges[indexPath.row].participants![5] + challenges[indexPath.row].activity!)) { (userActivity) in
participant6Average.text = String((userActivity?.averageScore)!)
participant6Best.text = String((userActivity?.bestScore)!)
if (userActivity?.played)! < 1 {
participant6Win.text = "0%"
} else {
participant6Win.text = String("\((((userActivity?.wins)! / (userActivity?.played)!) * 1000).rounded() / 10)%")
}
}
//MARK: participant7
if challenges[indexPath.row].participants!.count > 6 {
if currUserID == challenges[indexPath.row].participants![6] {
participant7Name.text = "You"
} else {
UserService.getUserName(userID: challenges[indexPath.row].participants![6]) { (userNameData) in
participant7Name.text = userNameData
}
}
if challenges[indexPath.row].confirmed?.contains(challenges[indexPath.row].participants![6]) == true {
participant7Accepted.image = UIImage(systemName: "person.fill.checkmark")
participant7Accepted.tintColor = UIColor.systemGreen
} else if challenges[indexPath.row].denied?.contains(challenges[indexPath.row].participants![6]) == true {
participant7Accepted.image = UIImage(systemName: "person.fill.xmark")
participant7Accepted.tintColor = UIColor.systemRed
}
participant7Stack?.isHidden = false
UserActivityService.getUserActivity(userActivityID: String(challenges[indexPath.row].participants![6] + challenges[indexPath.row].activity!)) { (userActivity) in
participant7Average.text = String((userActivity?.averageScore)!)
participant7Best.text = String((userActivity?.bestScore)!)
if (userActivity?.played)! < 1 {
participant7Win.text = "0%"
} else {
participant7Win.text = String("\((((userActivity?.wins)! / (userActivity?.played)!) * 1000).rounded() / 10)%")
}
}
//MARK: participant8
if challenges[indexPath.row].participants!.count > 7 {
if currUserID == challenges[indexPath.row].participants![7] {
participant8Name.text = "You"
} else {
UserService.getUserName(userID: challenges[indexPath.row].participants![7]) { (userNameData) in
participant8Name.text = userNameData
}
}
if challenges[indexPath.row].confirmed?.contains(challenges[indexPath.row].participants![7]) == true {
participant8Accepted.image = UIImage(systemName: "person.fill.checkmark")
participant8Accepted.tintColor = UIColor.systemGreen
} else if challenges[indexPath.row].denied?.contains(challenges[indexPath.row].participants![7]) == true {
participant8Accepted.image = UIImage(systemName: "person.fill.xmark")
participant8Accepted.tintColor = UIColor.systemRed
}
participant8Stack?.isHidden = false
UserActivityService.getUserActivity(userActivityID: String(challenges[indexPath.row].participants![7] + challenges[indexPath.row].activity!)) { (userActivity) in
participant8Average.text = String((userActivity?.averageScore)!)
participant8Best.text = String((userActivity?.bestScore)!)
if (userActivity?.played)! < 1 {
participant8Win.text = "0%"
} else {
participant8Win.text = String("\((((userActivity?.wins)! / (userActivity?.played)!) * 1000).rounded() / 10)%")
}
}
}
return cell
}

The problem was that subviews within the TableView cell were being resized by the system.
The solution was to set hugging priorities and compression resistance priorities on each of the stack views that were affected. This prevented any system resizing that was occurring.

Related

How to change multiple table height dynamically as per array data count

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

How to show corrected and incorrected count of card swiped either right or left from one view to another

In my app, i have implemented card swipe feature using ZLSwipeable library. Now when i swipe right, means the answer is correct and swipe left then answer is incorrect. Lets suppose, i am having 5 cards then if i swipe 2 left and 3 right, then the corrected count should be 2 and incorrect count should be 3 which should be displayed on another screen named as Score VC which has 2 labels for corrected and incorrected count. When i swipe the last card, then it should navigate to Score VC, how do i implement it. the card first is flipped and then swiped or clicked. Means the flipped card also have two buttons on it , either you swipe left or click tick button, it does the same functionality and same goes for right swipe
My Flipcard VC code where the card swipe feature reside:
class FlipCardVC: UIViewController, UIGestureRecognizerDelegate, AVSpeechSynthesizerDelegate
{
#IBOutlet weak var exitTapPopup: UIView!
#IBOutlet weak var cardFlipPopup: UIView!
#IBOutlet weak var savePopup: UIView!
#IBOutlet var hideCardPopup: UIView!
#IBOutlet var audioAllowPopup: UIView!
#IBOutlet weak var switchState: UISwitch!
#IBOutlet weak var progressViewBar: UIProgressView!
#IBOutlet weak var cardOuterView: UIView!
var wordsData = [ModelResult]()
var cardId = Int()
var cardSoundIndex = 0
//MARK: ZLSwipeableView Properties
#IBOutlet weak var SwipeCardOuterView: UIView!
var swipeableView: ZLSwipeableView!
var colorIndex = 0
var cardIndex = 0
var loadCardsFromXib = false
let speechSynthesizer = AVSpeechSynthesizer()
var isCorrect: Bool = true
var correctAnswerArr = [String]()
var incorrectAnswerArr = [String]()
var cardView:CardView?
var trueCounter = 0
var falseCounter = 0
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
constrain(SwipeCardOuterView, view) { view1, view2 in
view1.left == view2.left
view1.top == view2.top
view1.width == view.bounds.width
view1.height == view.bounds.height
}
}
// MARK: CARD VIEW
func cardInit()
{
wordsData.shuffle()
swipeableView = ZLSwipeableView()
view.addSubview(swipeableView)
swipeableView.numberOfActiveView = 2
swipeableView.didStart = {view, location in
print("Did start swiping view at location: \(location)")
}
swipeableView.swiping = {view, location, translation in
print("Swiping at view location: \(location) translation: \(translation)")
}
swipeableView.didEnd = {view, location in
self.progressViewBar.progress = (Float(self.cardIndex + 1) / Float(self.wordsData.count))
self.cardIndex += 1
if self.swipeableView.direction == .Left
{
self.isCorrect = true
self.correctAnswerArr.append("\(self.isCorrect)")
print(self.correctAnswerArr.count)
if self.colorIndex == self.wordsData.count
{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
vc.tempCorrectAnswer = "\(self.correctAnswerArr.count)"
self.navigationController?.pushViewController(vc, animated: true)
}
}
else
{
self.isCorrect = false
self.incorrectAnswerArr.append("\(self.isCorrect)")
print(self.incorrectAnswerArr.count)
if self.colorIndex == self.wordsData.count
{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
vc.tempincorrectAnswer = "\(self.incorrectAnswerArr.count)"
self.navigationController?.pushViewController(vc, animated: true)
}
}
}
swipeableView.didSwipe = {view, direction, vector in
print("Did swipe view in direction: \(direction), vector: \(vector)")
if direction.description == "Right"
{
// self.UserObject = self.UserData[view.tag]
// self.API_POST_Favorite()
}
else
{
// self.UserObject = self.UserData[view.tag]
// self.API_POST_UNFavorite()
}
}
swipeableView.didCancel = {view in
print("Did cancel swiping view")
}
swipeableView.didTap = {view, location in
let cv = view as! CardView
if cv.contentview.tag == 0 {
cv.contentview.tag = 1
UIView.transition(with: view, duration: 0.7, options: .transitionFlipFromRight, animations: {
if self.wordsData.count > cv.tag
{
let data = self.wordsData[cv.tag] as ModelResult
let tempLangChanged = UserDefaults.standard.bool(forKey: "isLangChanged")
if tempLangChanged != false
{
if let englishName = data.cardWordEnglish, englishName.count != 0
{
cv.contentview.wordLabel.text = englishName
}
cv.contentview.wordImage.isHidden = true
cv.contentview.yesNoBtnView.isHidden = false
cv.contentview.wordLabel.isUserInteractionEnabled = true
let tap:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.labelAction(gr:)))
cv.contentview.wordLabel.addGestureRecognizer(tap)
tap.delegate = self
cv.contentview.yesBtn.tag = cv.tag
cv.contentview.noBtn.tag = cv.tag
cv.contentview.yesBtn.addTarget(self, action: #selector(self.yesBtnSwipeLeft), for: .touchUpInside)
cv.contentview.noBtn.addTarget(self, action: #selector(self.noBtnSwipeRight), for: .touchUpInside)
let speechUtterance: AVSpeechUtterance = AVSpeechUtterance(string: data.cardWordEnglish!)
speechUtterance.rate = 0.3
speechUtterance.volume = 1.0
speechUtterance.voice = AVSpeechSynthesisVoice(language: "en-US")
self.speechSynthesizer.speak(speechUtterance)
}
else
{
if let spanishName = data.cardWordSpanish, spanishName.count != 0
{
cv.contentview.wordLabel.text = spanishName
}
cv.contentview.wordImage.isHidden = true
cv.contentview.yesNoBtnView.isHidden = false
cv.contentview.wordLabel.isUserInteractionEnabled = true
let tap:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.labelAction(gr:)))
cv.contentview.wordLabel.addGestureRecognizer(tap)
tap.delegate = self
cv.contentview.yesBtn.tag = cv.tag
cv.contentview.noBtn.tag = cv.tag
cv.contentview.yesBtn.addTarget(self, action: #selector(self.yesBtnSwipeLeft), for: .touchUpInside)
cv.contentview.noBtn.addTarget(self, action: #selector(self.noBtnSwipeRight), for: .touchUpInside)
let speechUtterance: AVSpeechUtterance = AVSpeechUtterance(string: data.cardWordSpanish!)
speechUtterance.rate = 0.3
speechUtterance.volume = 1.0
speechUtterance.voice = AVSpeechSynthesisVoice(language: "es")
self.speechSynthesizer.speak(speechUtterance)
}
}
}, completion: { (complete) in
})
}
}
swipeableView.didDisappear = { view in
print("Did disappear swiping view")
}
constrain(swipeableView, view) { view1, view2 in
view1.left == view2.left+5
view1.right == view2.right-5
view1.top == view2.top + 50
view1.bottom == view2.bottom - 16 + (IS_IPHONE_X() ? -24 : 0)
// view1.left == view2.left+50
// view1.right == view2.right-50
// view1.top == view2.top + 120
// view1.bottom == view2.bottom - 100
// view1.left == view2.left+16
// view1.right == view2.right-16
// view1.top == view2.top + 83 + (IS_IPHONE_X() ? 24 : 0)
// view1.bottom == view2.bottom - 16 + (IS_IPHONE_X() ? -24 : 0)
}
self.loadCardsFromXib = true
self.colorIndex = 0
self.swipeableView.discardViews()
self.swipeableView.loadViews()
}
override func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews()
if let swview = swipeableView
{
swview.nextView = {
return self.nextCardView()
}
}
}
#objc func yesBtnSwipeLeft(sender: UIButton) {
self.progressViewBar.progress = (Float(self.cardIndex + 1) / Float(self.wordsData.count))
self.cardIndex += 1
self.swipeableView.swipeTopView(inDirection: .Left)
trueCounter = trueCounter + 1
if colorIndex == self.wordsData.count{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
UserDefaults.standard.set(trueCounter, forKey: "trueCounter")
self.navigationController?.pushViewController(vc, animated: true)
}
}
#objc func noBtnSwipeRight(sender: UIButton) {
self.progressViewBar.progress = (Float(self.cardIndex + 1) / Float(self.wordsData.count))
self.cardIndex += 1
self.swipeableView.swipeTopView(inDirection: .Right)
falseCounter = falseCounter + 1
print("THIS IS my counter: (falseCounter)")
if colorIndex == self.wordsData.count {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
UserDefaults.standard.set(falseCounter, forKey: "falseCounter")
self.navigationController?.pushViewController(vc, animated: true)
}
}
#objc func soundBtn(sender: UIButton)
{
ApiUtillity.sharedInstance.AddSubViewtoParentView(parentview: self.view, subview: self.audioAllowPopup)
}
#objc func hideCard(sender: UIButton)
{
ApiUtillity.sharedInstance.AddSubViewtoParentView(parentview: self.view, subview: self.hideCardPopup)
}
func nextCardView() -> UIView?
{
let arrayData = wordsData
if (self.colorIndex >= arrayData.count)
{
return nil
}
self.cardView = CardView(frame: swipeableView.bounds)
if loadCardsFromXib
{
self.cardView!.contentview = Bundle.main.loadNibNamed("CardContentView", owner: self, options: nil)?.first! as? CardView
self.cardView!.contentview.superVC = self
self.cardView!.contentview.translatesAutoresizingMaskIntoConstraints = false
self.cardView!.contentview.backgroundColor = self.cardView!.backgroundColor
self.cardView!.addSubview(self.cardView!.contentview)
let data = arrayData[(self.colorIndex)] as ModelResult
self.cardView!.contentview.wordModel = data
self.cardView!.contentview.currentCardCountLbl.text = "\(self.colorIndex + 1)"+" "+"of"+" "+"\(wordsData.count)"
let tempLangChanged = UserDefaults.standard.bool(forKey: "isLangChanged")
if tempLangChanged == false
{
if let dict = data.cardWordImage, dict.count != 0
{
let url = WS_wordIconUrl + dict
self.cardView!.contentview.wordImage.kf.indicatorType = .activity
self.cardView!.contentview.wordImage.kf.setImage(with: URL(string: url))
}
if let englishName = data.cardWordEnglish, englishName.count != 0
{
self.cardView!.contentview.wordLabel.text = englishName
}
cardView?.contentview.yesNoBtnView.isHidden = true
}
else
{
if let dict = data.cardWordImage, dict.count != 0
{
let url = WS_wordIconUrl + dict
self.cardView!.contentview.wordImage.kf.indicatorType = .activity
self.cardView!.contentview.wordImage.kf.setImage(with: URL(string: url))
}
if let spanishName = data.cardWordSpanish, spanishName.count != 0
{
self.cardView!.contentview.wordLabel.text = spanishName
}
cardView?.contentview.yesNoBtnView.isHidden = true
}
self.cardView!.contentview.soundBtn.addTarget(self, action:#selector(self.soundBtn(sender:)), for: .touchUpInside)
self.cardView!.contentview.hideCard.addTarget(self, action:#selector(self.hideCard(sender:)), for: .touchUpInside)
self.cardView!.contentview.soundBtn.tag = self.colorIndex
self.cardView!.contentview.hideCard.tag = self.colorIndex
self.cardView!.tag = self.colorIndex
constrain(self.cardView!.contentview, self.cardView!) { view1, view2 in
view1.left == view2.left
view1.top == view2.top
view1.width == self.cardView!.bounds.width
view1.height == self.cardView!.bounds.height
}
}
colorIndex += 1
return cardView
}
//MARK: API Parsing for deck words data
func WS_GetWords()
{
if ApiUtillity.sharedInstance.isReachable()
{
ApiUtillity.sharedInstance.StartProgress(view: self.view)
let url = "\(WS_GetWordsAPI)/\(cardId)"
APIClient<ModelBaseGetWordsData>().API_GET(Url: url, Params: [:], Authentication: true, Progress: true, Alert: true, Offline: false, SuperVC: self, completionSuccess: { (modelResponse) in
if(modelResponse.success == true)
{
ApiUtillity.sharedInstance.StopProgress(view: self.view)
self.colorIndex = 0
self.wordsData.removeAll()
if let array = modelResponse.result, array.count != 0
{
for data in array
{
self.wordsData.append(data)
}
self.cardInit()
}
else
{
self.colorIndex = 0
self.wordsData.removeAll()
DispatchQueue.main.asyncAfter(deadline: .now(), execute:
{
if self.swipeableView != nil
{
self.swipeableView.removeFromSuperview()
}
self.cardInit()
})
}
}
else
{
self.showToast(message: modelResponse.message!)
ApiUtillity.sharedInstance.StopProgress(view: self.view)
}
if self.wordsData.count == 0
{
self.setNoDataMessage(message: modelResponse.message)
}
}) { (failed) in
self.showToast(message: failed.localizedDescription)
ApiUtillity.sharedInstance.StopProgress(view: self.view)
}
}
else
{
self.showToast(message: "No internet connection...")
}
}
my score vc code:
class ScoreVC: UIViewController {
#IBOutlet weak var progressScoreView: MBCircularProgressBarView!
#IBOutlet weak var correctAnswerLbl: UILabel!
#IBOutlet weak var incorrectAnswerLbl: UILabel!
var tempCorrectAnswer = String()
var tempincorrectAnswer = String()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.progressScoreView.value = 0.0
let correct = UserDefaults.standard.string(forKey: "trueCounter")
let incorrect = UserDefaults.standard.string(forKey: "falseCounter")
self.correctAnswerLbl.text = correct
self.incorrectAnswerLbl.text = incorrect
}
override func viewWillAppear(_ animated: Bool) {
self.setCounterToZero()
UIView.animate(withDuration: 10.0) {
self.progressScoreView.value = 50.0
}
}
func setCounterToZero(){
correctAnswerLbl.text = ""
incorrectAnswerLbl.text = ""
}
create 2 var variables to increase the value
var trueCounter = 0
var falseCounter = 0
Set a function in your ViewWillAppear for every time your screen reloads the counter do it aswell
override func viewWillAppear(_ animated: Bool) {
setCounterToZero()
}
func setCounterToZero(){
correctAnswerLbl.text = ""
incorrectAnswerLbl.text = ""
}
so in your swipe functions set the variables to increase
for false:
falseCounter = falseCounter + 1
for true
trueCounter = trueCounter + 1
when the game ends and sends the user to the ScoreVC
UserDefaults.standard.set(trueCounter, forKey: "trueCounter")
UserDefaults.standard.set(falseCounter, forKey: "falseCounter")
flipcardVC
class FlipCardVC: UIViewController, UIGestureRecognizerDelegate, AVSpeechSynthesizerDelegate
{
#IBOutlet weak var exitTapPopup: UIView!
#IBOutlet weak var cardFlipPopup: UIView!
#IBOutlet weak var savePopup: UIView!
#IBOutlet var hideCardPopup: UIView!
#IBOutlet var audioAllowPopup: UIView!
#IBOutlet weak var switchState: UISwitch!
#IBOutlet weak var progressViewBar: UIProgressView!
#IBOutlet weak var cardOuterView: UIView!
var wordsData = [ModelResult]()
var cardId = Int()
var cardSoundIndex = 0
//MARK: ZLSwipeableView Properties
#IBOutlet weak var SwipeCardOuterView: UIView!
var swipeableView: ZLSwipeableView!
var colorIndex = 0
var cardIndex = 0
var loadCardsFromXib = false
let speechSynthesizer = AVSpeechSynthesizer()
var isCorrect: Bool = true
var correctAnswerArr = [String]()
var incorrectAnswerArr = [String]()
var trueCounter = 0
var falseCounter = 0
var cardView:CardView?
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
constrain(SwipeCardOuterView, view) { view1, view2 in
view1.left == view2.left
view1.top == view2.top
view1.width == view.bounds.width
view1.height == view.bounds.height
}
}
// MARK: CARD VIEW
func cardInit()
{
wordsData.shuffle()
swipeableView = ZLSwipeableView()
view.addSubview(swipeableView)
swipeableView.numberOfActiveView = 2
swipeableView.didStart = {view, location in
print("Did start swiping view at location: \(location)")
}
swipeableView.swiping = {view, location, translation in
print("Swiping at view location: \(location) translation: \(translation)")
}
swipeableView.didEnd = {view, location in
self.progressViewBar.progress = (Float(self.cardIndex + 1) / Float(self.wordsData.count))
self.cardIndex += 1
if self.swipeableView.direction == .Left
{
self.isCorrect = true
self.correctAnswerArr.append("\(self.isCorrect)")
print(self.correctAnswerArr.count)
if self.colorIndex == self.wordsData.count
{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
vc.tempCorrectAnswer = "\(self.correctAnswerArr.count)"
self.navigationController?.pushViewController(vc, animated: true)
}
}
else
{
self.isCorrect = false
self.incorrectAnswerArr.append("\(self.isCorrect)")
print(self.incorrectAnswerArr.count)
if self.colorIndex == self.wordsData.count
{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
vc.tempincorrectAnswer = "\(self.incorrectAnswerArr.count)"
self.navigationController?.pushViewController(vc, animated: true)
}
}
}
swipeableView.didSwipe = {view, direction, vector in
print("Did swipe view in direction: \(direction), vector: \(vector)")
if direction.description == "Right"
{
// self.UserObject = self.UserData[view.tag]
// self.API_POST_Favorite()
}
else
{
// self.UserObject = self.UserData[view.tag]
// self.API_POST_UNFavorite()
}
}
swipeableView.didCancel = {view in
print("Did cancel swiping view")
}
swipeableView.didTap = {view, location in
let cv = view as! CardView
if cv.contentview.tag == 0 {
cv.contentview.tag = 1
UIView.transition(with: view, duration: 0.7, options: .transitionFlipFromRight, animations: {
if self.wordsData.count > cv.tag
{
let data = self.wordsData[cv.tag] as ModelResult
let tempLangChanged = UserDefaults.standard.bool(forKey: "isLangChanged")
if tempLangChanged != false
{
if let englishName = data.cardWordEnglish, englishName.count != 0
{
cv.contentview.wordLabel.text = englishName
}
cv.contentview.wordImage.isHidden = true
cv.contentview.yesNoBtnView.isHidden = false
cv.contentview.wordLabel.isUserInteractionEnabled = true
let tap:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.labelAction(gr:)))
cv.contentview.wordLabel.addGestureRecognizer(tap)
tap.delegate = self
cv.contentview.yesBtn.tag = cv.tag
cv.contentview.noBtn.tag = cv.tag
cv.contentview.yesBtn.addTarget(self, action: #selector(self.yesBtnSwipeLeft), for: .touchUpInside)
cv.contentview.noBtn.addTarget(self, action: #selector(self.noBtnSwipeRight), for: .touchUpInside)
let speechUtterance: AVSpeechUtterance = AVSpeechUtterance(string: data.cardWordEnglish!)
speechUtterance.rate = 0.3
speechUtterance.volume = 1.0
speechUtterance.voice = AVSpeechSynthesisVoice(language: "en-US")
self.speechSynthesizer.speak(speechUtterance)
}
else
{
if let spanishName = data.cardWordSpanish, spanishName.count != 0
{
cv.contentview.wordLabel.text = spanishName
}
cv.contentview.wordImage.isHidden = true
cv.contentview.yesNoBtnView.isHidden = false
cv.contentview.wordLabel.isUserInteractionEnabled = true
let tap:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.labelAction(gr:)))
cv.contentview.wordLabel.addGestureRecognizer(tap)
tap.delegate = self
cv.contentview.yesBtn.tag = cv.tag
cv.contentview.noBtn.tag = cv.tag
cv.contentview.yesBtn.addTarget(self, action: #selector(self.yesBtnSwipeLeft), for: .touchUpInside)
cv.contentview.noBtn.addTarget(self, action: #selector(self.noBtnSwipeRight), for: .touchUpInside)
let speechUtterance: AVSpeechUtterance = AVSpeechUtterance(string: data.cardWordSpanish!)
speechUtterance.rate = 0.3
speechUtterance.volume = 1.0
speechUtterance.voice = AVSpeechSynthesisVoice(language: "es")
self.speechSynthesizer.speak(speechUtterance)
}
}
}, completion: { (complete) in
})
}
}
swipeableView.didDisappear = { view in
print("Did disappear swiping view")
}
constrain(swipeableView, view) { view1, view2 in
view1.left == view2.left+5
view1.right == view2.right-5
view1.top == view2.top + 50
view1.bottom == view2.bottom - 16 + (IS_IPHONE_X() ? -24 : 0)
// view1.left == view2.left+50
// view1.right == view2.right-50
// view1.top == view2.top + 120
// view1.bottom == view2.bottom - 100
// view1.left == view2.left+16
// view1.right == view2.right-16
// view1.top == view2.top + 83 + (IS_IPHONE_X() ? 24 : 0)
// view1.bottom == view2.bottom - 16 + (IS_IPHONE_X() ? -24 : 0)
}
self.loadCardsFromXib = true
self.colorIndex = 0
self.swipeableView.discardViews()
self.swipeableView.loadViews()
}
override func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews()
if let swview = swipeableView
{
swview.nextView = {
return self.nextCardView()
}
}
}
#objc func yesBtnSwipeLeft(sender: UIButton) {
self.progressViewBar.progress = (Float(self.cardIndex + 1) / Float(self.wordsData.count))
self.cardIndex += 1
self.swipeableView.swipeTopView(inDirection: .Left)
var finalTrue = 0
trueCounter = trueCounter + 1
print("THE USER SWIPE TO left")
print("///////////////////////////////////////////")
print(trueCounter)
print("///////////////////////////////////////////")
finalTrue = trueCounter
if colorIndex == self.wordsData.count{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
UserDefaults.standard.set(finalTrue, forKey: "trueCounter")
self.navigationController?.pushViewController(vc, animated: true)
}
}
#objc func noBtnSwipeRight(sender: UIButton) {
self.progressViewBar.progress = (Float(self.cardIndex + 1) / Float(self.wordsData.count))
self.cardIndex += 1
self.swipeableView.swipeTopView(inDirection: .Right)
var finalFlase = 0
falseCounter = falseCounter + 1
print("THE USER SWIPE TO right")
print("///////////////////////////////////////////")
print(falseCounter)
print("///////////////////////////////////////////")
var finalFlase = falseCounter
print("THIS IS my counter: (falseCounter)")
if colorIndex == self.wordsData.count {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ScoreVC") as! ScoreVC
UserDefaults.standard.set(finalFlase, forKey: "falseCounter")
self.navigationController?.pushViewController(vc, animated: true)
}
}
#objc func soundBtn(sender: UIButton)
{
ApiUtillity.sharedInstance.AddSubViewtoParentView(parentview: self.view, subview: self.audioAllowPopup)
}
#objc func hideCard(sender: UIButton)
{
ApiUtillity.sharedInstance.AddSubViewtoParentView(parentview: self.view, subview: self.hideCardPopup)
}
func nextCardView() -> UIView?
{
let arrayData = wordsData
if (self.colorIndex >= arrayData.count)
{
return nil
}
self.cardView = CardView(frame: swipeableView.bounds)
if loadCardsFromXib
{
self.cardView!.contentview = Bundle.main.loadNibNamed("CardContentView", owner: self, options: nil)?.first! as? CardView
self.cardView!.contentview.superVC = self
self.cardView!.contentview.translatesAutoresizingMaskIntoConstraints = false
self.cardView!.contentview.backgroundColor = self.cardView!.backgroundColor
self.cardView!.addSubview(self.cardView!.contentview)
let data = arrayData[(self.colorIndex)] as ModelResult
self.cardView!.contentview.wordModel = data
self.cardView!.contentview.currentCardCountLbl.text = "\(self.colorIndex + 1)"+" "+"of"+" "+"\(wordsData.count)"
let tempLangChanged = UserDefaults.standard.bool(forKey: "isLangChanged")
if tempLangChanged == false
{
if let dict = data.cardWordImage, dict.count != 0
{
let url = WS_wordIconUrl + dict
self.cardView!.contentview.wordImage.kf.indicatorType = .activity
self.cardView!.contentview.wordImage.kf.setImage(with: URL(string: url))
}
if let englishName = data.cardWordEnglish, englishName.count != 0
{
self.cardView!.contentview.wordLabel.text = englishName
}
cardView?.contentview.yesNoBtnView.isHidden = true
}
else
{
if let dict = data.cardWordImage, dict.count != 0
{
let url = WS_wordIconUrl + dict
self.cardView!.contentview.wordImage.kf.indicatorType = .activity
self.cardView!.contentview.wordImage.kf.setImage(with: URL(string: url))
}
if let spanishName = data.cardWordSpanish, spanishName.count != 0
{
self.cardView!.contentview.wordLabel.text = spanishName
}
cardView?.contentview.yesNoBtnView.isHidden = true
}
self.cardView!.contentview.soundBtn.addTarget(self, action:#selector(self.soundBtn(sender:)), for: .touchUpInside)
self.cardView!.contentview.hideCard.addTarget(self, action:#selector(self.hideCard(sender:)), for: .touchUpInside)
self.cardView!.contentview.soundBtn.tag = self.colorIndex
self.cardView!.contentview.hideCard.tag = self.colorIndex
self.cardView!.tag = self.colorIndex
constrain(self.cardView!.contentview, self.cardView!) { view1, view2 in
view1.left == view2.left
view1.top == view2.top
view1.width == self.cardView!.bounds.width
view1.height == self.cardView!.bounds.height
}
}
colorIndex += 1
return cardView
}
//MARK: API Parsing for deck words data
func WS_GetWords()
{
if ApiUtillity.sharedInstance.isReachable()
{
ApiUtillity.sharedInstance.StartProgress(view: self.view)
let url = "\(WS_GetWordsAPI)/\(cardId)"
APIClient<ModelBaseGetWordsData>().API_GET(Url: url, Params: [:], Authentication: true, Progress: true, Alert: true, Offline: false, SuperVC: self, completionSuccess: { (modelResponse) in
if(modelResponse.success == true)
{
ApiUtillity.sharedInstance.StopProgress(view: self.view)
self.colorIndex = 0
self.wordsData.removeAll()
if let array = modelResponse.result, array.count != 0
{
for data in array
{
self.wordsData.append(data)
}
self.cardInit()
}
else
{
self.colorIndex = 0
self.wordsData.removeAll()
DispatchQueue.main.asyncAfter(deadline: .now(), execute:
{
if self.swipeableView != nil
{
self.swipeableView.removeFromSuperview()
}
self.cardInit()
})
}
}
else
{
self.showToast(message: modelResponse.message!)
ApiUtillity.sharedInstance.StopProgress(view: self.view)
}
if self.wordsData.count == 0
{
self.setNoDataMessage(message: modelResponse.message)
}
}) { (failed) in
self.showToast(message: failed.localizedDescription)
ApiUtillity.sharedInstance.StopProgress(view: self.view)
}
}
else
{
self.showToast(message: "No internet connection...")
}
}
and in your score labels score vc
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.progressScoreView.value = 0.0
let correct = UserDefaults.standard.string(forKey: "trueCounter")
let incorrect = UserDefaults.standard.string(forKey: "falseCounter")
self.correctAnswerLbl.text = correct
self.incorrectAnswerLbl.text = incorrect
}
override func viewWillAppear(_ animated: Bool) {
//don't add setCounterToZero()
UIView.animate(withDuration: 10.0) {
self.progressScoreView.value = 50.0
}
}
plz rate if was useful

Swift 3: Removing Duplicates / group them as 1 in uitableviewcell

I am trying to either remove the duplicate entries fetched from the external database /group them as one. Initially, my sql query had a group clause. When I used it as group clause, the query was working, but not appropriately. I then removed the group clause from the query, it now shows the duplicate entries.
I have four regions: - North, East, South,West and ALL
By default it shows all region. Now there could be a profile that appears in more than one region. So when it loads as default - all regions, the profile should only appear once there, but when we tab on the regions, the profile should also show up there if the profile belongs in that region.
At them moment, it is showing all random. Some profiles that are available in more than one region, they do appear and some they dont. Some profile that is meant to be only in one region, do appear in 2 regions.
I dont know how can I share the code or screenshots, but happy to provide more details to look at the call.
Thanks
My code:
func removeDuplicate (sourceArray: [String]) -> [String] {
var uniqueArray:[String] = []
for object in sourceArray {
if !uniqueArray.contains(object)
{
uniqueArray.append(object)
}
}
return uniqueArray
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0
{
let cell = self.bussinessTableView.dequeueReusableCell(withIdentifier: "bussinessCell", for: indexPath) as! BussinessCell
let tableObjects:StorageSubCatagoriezTwo = subCatagorizeDataTwo[indexPath.row]
let testing = removeDuplicate(sourceArray: [tableObjects.nameString])
print(testing.description)
//let charCheck = (tableObjects.address).replacingOccurrences(of: " ", with: "")
if reg == "North"
{
cell.bussinessName.text = " "
cell.addLabel.text = " "
cell.telLabel.text = " "
cell.emailLabel.text = " "
cell.webLabel.text = " "
let tableObjects:StorageSubCatagoriezTwoNorth = subCatagorizeDataTwoN[indexPath.row]
if tableObjects.address.characters.isEmpty != true
{
cell.addLabel.text = tableObjects.address
}
else
{
//nothing
}
if tableObjects.telephone.characters.isEmpty != true
{
cell.telLabel.text = tableObjects.telephone
}
else
{
}
if tableObjects.email.characters.isEmpty != true
{
cell.emailLabel.text = tableObjects.email
}
else
{
}
if tableObjects.website.characters.isEmpty != true{
cell.webLabel.text = tableObjects.website
}
else{
}
}
else if reg == "East"
{
cell.bussinessName.text = " "
let tableObjects:StorageSubCatagoriezTwoEast = subCatagorizeDataTwoE[indexPath.row]
cell.bussinessName.text = tableObjects.nameString
if tableObjects.address.characters.isEmpty != true
{
cell.addLabel.text = tableObjects.address
}
else
{
//nothing
}
if tableObjects.telephone.characters.isEmpty != true
{
cell.telLabel.text = tableObjects.telephone
}
else
{
}
if tableObjects.email.characters.isEmpty != true
{
cell.emailLabel.text = tableObjects.email
}
else
{
}
if tableObjects.website.characters.isEmpty != true
{
cell.webLabel.text = tableObjects.website
}
else{
}
}
else if reg == "South"
{
cell.bussinessName.text = " "
let tableObjects:StorageSubCatagoriezTwoSouth = subCatagorizeDataTwoS[indexPath.row]
cell.bussinessName.text = tableObjects.nameString
if tableObjects.address.characters.isEmpty != true
{
cell.addLabel.text = tableObjects.address
}
else
{
//nothing
}
if tableObjects.telephone.characters.isEmpty != true
{
cell.telLabel.text = tableObjects.telephone
}
else
{
}
if tableObjects.email.characters.isEmpty != true
{
cell.emailLabel.text = tableObjects.email
}
else
{
}
if tableObjects.website.characters.isEmpty != true{
cell.webLabel.text = tableObjects.website
}
else{
}
}
else if reg == "West"
{
cell.bussinessName.text = " "
let tableObjects:StorageSubCatagoriezTwoWest = subCatagorizeDataTwoW[indexPath.row]
cell.bussinessName.text = tableObjects.nameString
if tableObjects.address.characters.isEmpty != true
{
cell.addLabel.text = tableObjects.address
}
else
{
//nothing
}
if tableObjects.telephone.characters.isEmpty != true
{
cell.telLabel.text = tableObjects.telephone
}
else
{
}
if tableObjects.email.characters.isEmpty != true
{
cell.emailLabel.text = tableObjects.email
}
else
{
}
if tableObjects.website.characters.isEmpty != true{
cell.webLabel.text = tableObjects.website
}
}
else{
let tableObjects:StorageSubCatagoriezTwo = subCatagorizeDataTwo[indexPath.row]
cell.bussinessName.text = tableObjects.nameString
let charCheck = (tableObjects.address).replacingOccurrences(of: " ", with: "")
cell.bussinessName.text = tableObjects.nameString
cell.addLabel.text = tableObjects.address
cell.telLabel.text = tableObjects.telephone
cell.emailLabel.text = tableObjects.email
cell.webLabel.text = tableObjects.website
}
return cell
}
else if indexPath.section == 1
{
let cell = self.bussinessTableView.dequeueReusableCell(withIdentifier: "bussinessCell2")
cell?.textLabel?.textAlignment = .center
switch regId
{
case 0:
if subCatagorizeDataTwo.count != forAll
{
cell?.textLabel?.text = "Load More Data"
cell?.textLabel?.textColor = Color.whiteColor
cell?.backgroundColor = UIColor.darkGray
}else{
cell?.textLabel?.text = "No More Data Found"
cell?.textLabel?.textColor = UIColor.darkGray
cell?.backgroundColor = UIColor.gray
cell?.selectionStyle = UITableViewCellSelectionStyle.none
}
case 1:
if subCatagorizeDataTwoN.count != forN
{
cell?.textLabel?.text = "Load More Data"
cell?.textLabel?.textColor = Color.whiteColor
cell?.backgroundColor = UIColor.darkGray
}else{
cell?.textLabel?.text = "No More Data Found"
cell?.textLabel?.textColor = UIColor.darkGray
cell?.backgroundColor = UIColor.gray
cell?.selectionStyle = UITableViewCellSelectionStyle.none
}
case 2:
if subCatagorizeDataTwoE.count != forE
{
cell?.textLabel?.text = "Load More Data"
cell?.textLabel?.textColor = Color.whiteColor
cell?.backgroundColor = UIColor.darkGray
}else{
cell?.textLabel?.text = "No More Data Found"
cell?.textLabel?.textColor = UIColor.darkGray
cell?.backgroundColor = UIColor.gray
cell?.selectionStyle = UITableViewCellSelectionStyle.none
}
case 3:
if subCatagorizeDataTwoS.count != forS
{
cell?.textLabel?.text = "Load More Data"
cell?.textLabel?.textColor = Color.whiteColor
cell?.backgroundColor = UIColor.darkGray
}else{
cell?.textLabel?.text = "No More Data Found"
cell?.textLabel?.textColor = UIColor.darkGray
cell?.backgroundColor = UIColor.gray
cell?.selectionStyle = UITableViewCellSelectionStyle.none
}
case 4:
if subCatagorizeDataTwoW.count != forW
{
cell?.textLabel?.text = "Load More Data"
cell?.textLabel?.textColor = Color.whiteColor
cell?.backgroundColor = UIColor.darkGray
}else{
cell?.textLabel?.text = "No More Data Found"
cell?.textLabel?.textColor = UIColor.darkGray
cell?.backgroundColor = UIColor.gray
cell?.selectionStyle = UITableViewCellSelectionStyle.none
}
default:break
}
return cell!
}
else
{
let tableObjects:StorageSubCatagoriez3rd = SubCatagoriez3rd[indexPath.row]
let cell = self.bussinessTableView.dequeueReusableCell(withIdentifier: "bussinessCell3")
cell?.textLabel?.text = tableObjects.nameString
return cell!
}
}
As per my knowledge if you want to remove duplicate from array then use below logic with your datatype
func removeDublicate (sourceArray: [Int]) -> [Int] {
var uniqueArray:[Int] = []
for object in sourceArray {
if !uniqueArray.contains(object)
{
uniqueArray.append(object)
}
}
return uniqueArray
}
let testing = removeDublicate(sourceArray: [1,2,2,5,1,8,3,1,2,8,5])
print(testing)
OUTPUT
[1, 2, 5, 8, 3]
Replace this line
let tableObjects:StorageSubCatagoriezTwoNorth = subCatagorizeDataTwoN[indexPath.row]
With this
var tableObjects:StorageSubCatagoriezTwoNorth = subCatagorizeDataTwoN[indexPath.row]
tableObjects = removeDuplicate(sourceArray: [tableObjects.nameString ])
Do it for all regions
In swift 3 you can use this code for removing duplicate from array. Only this much code is needed. Try this code..
import UIKit
class ViewController2: UIViewController {
var myArray: [Int] = [1,2,3,4,3,2,5,7,5,8]
override func viewDidLoad()
{
super.viewDidLoad()
let uniqueArray = Array(Set(self.myArray))
print(uniqueArray) // This print result will be [2, 4, 5, 7, 1, 8]
}
}
OUTPUT
[2, 4, 5, 7, 1, 8]

Pushing and popping NavigationController in Swift

I have an issue.
I get an error below in the code saying: "Cannot convert value type 'Node' to expected argument type 'UIViewController' How to solve this?
the code for the document view controller is below:
import UIKit
import WebKit
import AEXML
import STPopup
import Kanna
import DropDownMenuKit
import Toaster
typealias DocumentOpenAction = (_ node: Node) -> ()
class DocumentViewController: BaseViewController {
var currentNode:Node! {
didSet {
if popupController == nil {
navigationItem.titleView = UILabel.forTitleView(withText: currentNode.title)
if titleView != nil {
navigationItem.titleView = titleView
}
} else {
navigationItem.titleView = UILabel.forTitleView(withText: currentNode.title)
}
}
}
//ausgegebene HTML's
var sections:[[String:String]] = []
var changeMarksVisible:Bool? {
didSet {
self.updateChangeMarking()
}
}
var nightModeOn:Bool? {
didSet {
self.updateNightMode()
}
}
var readAccessFolder:URL?
lazy var statusBarHeight: CGFloat = {
let statusBarSize = UIApplication.shared.statusBarFrame.size
return min(statusBarSize.width, statusBarSize.height)
}()
//
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(DocumentViewController.taskGotDeleted(withNotification:)), name: PackageManager.shared.tasksDeletedNotification, object: nil)
contentSizeInPopup = CGSize(width: 600, height: 500)
landscapeContentSizeInPopup = CGSize(width: 600, height: 500)
changeMarksVisible = UserDefaults.standard.bool(forKey: "ChangeMarkings")
nightModeOn = UserDefaults.standard.bool(forKey: "nightTheme")
if popupController == nil {
PackageManager.shared.setCurrentNodeAndAddToHistory(currentNode)
setupNavBar()
// create the drop down menu
createDropDownMenu()
//
jumpToGraphicsViewButton.addTarget(self, action: #selector(DocumentViewController.showGraphicsView), for: .touchUpInside)
jumpToGraphicsViewButtonLeadingConstraint.constant = 8.0
jumpToGraphicsViewButtonWidthConstraint.constant = 48.0
jumpToGraphicsViewButton.isEnabled = false
jumpToGraphicsViewButton.isHidden = false
} else {
setupNavBarForPreview()
//
jumpToGraphicsViewButton.isHidden = true
jumpToGraphicsViewButtonLeadingConstraint.constant = 0.0
jumpToGraphicsViewButtonWidthConstraint.constant = 0.0
}
// webview
setupWebview()
// process html of current node
splitHTML(forCurrentNode: currentNode)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
PackageManager.shared.currentDisplayedModuleNode = currentNode
navigationBarMenu?.container = view
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { (ctx) in
self.show3dModelButtonLeadConstraint?.constant = self.view.frame.width - 50
self.show3dModelButton?.updateConstraintsIfNeeded()
self.webview?.scrollView.updateConstraintsIfNeeded()
// If we put this only in -viewDidLayoutSubviews, menu animation is
// messed up when selecting an item
self.updateMenuContentOffsets()
}) { (ctx) in
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
URLCache.shared.removeAllCachedResponses()
}
deinit {
NotificationCenter.default.removeObserver(self)
webview?.scrollView.delegate = nil
}
func showListOfContent(_ sender: AnyObject) {
_ = navigationController?.popViewController(animated: true)
}
}
// MARK: - UI
extension DocumentViewController {
func setupWebview() {
//Content Controller object
let controller = WKUserContentController()
//Add message handler reference
controller.add(self, name: "shoppingcart")
//Create configuration
let configuration = WKWebViewConfiguration()
configuration.userContentController = controller
var f = webViewView.frame
f.origin.y = 0
webview = WKWebView(frame: f, configuration: configuration)
webview?.configuration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs")
webview?.backgroundColor = .white
webview?.scrollView.bounces = true
webview?.scrollView.delegate = self
webview?.navigationDelegate = self
webview?.uiDelegate = self
webViewView.addSubview(webview!)
webview?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
func setupNavBar() {
//loads nav bar if not presented in popup
settingsButton = UIBarButtonItem(image: UIImage(named: "Settings"), style: .plain, target: self, action: #selector(DocumentViewController.showSettings(_:)))
navigationItem.rightBarButtonItems = [noticeButton,settingsButton]
listOfContentButton = UIBarButtonItem(image: UIImage(named: "List"), style: .plain, target: self, action: #selector(DocumentViewController.showListOfContent(_:)))
shoppingCartButton = UIBarButtonItem(image: UIImage(named: "Checkout"), style: .plain, target: self, action: #selector(DocumentViewController.shoppingCartButtonPressed(_:)))
taskListButton = ZABarButtonItem(image: UIImage(named: "TaskList"), style: .plain, target: self, action: #selector(DocumentViewController.taskListButtonPressed(_:)))
taskListButton.isSelected = PackageManager.shared.nodeIsInTasks(currentNode)
taskListButton.tintColor = taskListButton.isSelected ? navigationController?.navigationBar.tintColor : .lightGray
favoritesButton = ZABarButtonItem(image: UIImage(named: "Star"), style: .plain, target: self, action: #selector(DocumentViewController.favoritesButtonPressed(_:)))
favoritesButton.isSelected = PackageManager.shared.nodeIsInFavorites(currentNode)
let img = favoritesButton.isSelected ? UIImage(named: "StarFilled"): UIImage(named: "Star")
favoritesButton.image = img
backToManualStructure = UIBarButtonItem(image: UIImage(named: "List"), style: .plain, target: self, action: #selector(DocumentViewController.structureButtonPressed(_:)))
var items:[UIBarButtonItem] = [backToManualStructure,shoppingCartButton, favoritesButton]
if currentNode.canBeAddedToTasks() {
items.append(taskListButton)
}
navigationItem.leftBarButtonItems = items
}
func setupNavBarForPreview() {
//loads nav bar if presented in popup
closeButton = UIBarButtonItem(title: NSLocalizedString("Close", tableName: "Localizable", bundle: Bundle.main, value: "", comment: ""), style: .plain, target: self, action: #selector(DocumentViewController.cancel))
navigationItem.leftBarButtonItems = [closeButton]
navigationItem.leftItemsSupplementBackButton = false
openButton = UIBarButtonItem(title: NSLocalizedString("Open in new tab", tableName: "Localizable", bundle: Bundle.main, value: "", comment: ""), style: .plain, target: self, action: #selector(DocumentViewController.openDocument))
navigationItem.rightBarButtonItems = [openButton]
}
}
// MARK: - DropDownMenu
extension DocumentViewController {
func createDropDownMenu() {
// create the drop down menu
let title = prepareNavigationBarMenuTitleView()
prepareNavigationBarMenu(title)
updateMenuContentOffsets()
}
func prepareNavigationBarMenuTitleView() -> String {
// Both title label and image view are fixed horizontally inside title
// view, UIKit is responsible to center title view in the navigation bar.
// We want to ensure the space between title and image remains constant,
// even when title view is moved to remain centered (but never resized).
titleView = DropDownTitleView(frame: CGRect(x: 0, y: 0, width: 150, height: 40))
titleView.addTarget(self,
action: #selector(DocumentViewController.willToggleNavigationBarMenu(_:)),
for: .touchUpInside)
titleView.addTarget(self,
action: #selector(DocumentViewController.didToggleNavigationBarMenu(_:)),
for: .valueChanged)
titleView.titleLabel.textColor = UIColor.black
titleView.title = currentNode.title
navigationItem.titleView = titleView
return titleView.title!
}
func prepareNavigationBarMenu(_ currentChoice: String) {
navigationBarMenu = DropDownMenu(frame: view.bounds)
navigationBarMenu?.delegate = self
var cells:[DropDownMenuCell] = []
for (index, doc) in PackageManager.shared.openNodes.enumerated() {
let cell = DropDownMenuCell()
cell.textLabel!.text = doc.title
cell.tag = index
cell.menuAction = #selector(DocumentViewController.choose(_:))
cell.menuTarget = self
if currentChoice == doc.title {
cell.accessoryType = .checkmark
}
cells.append(cell)
}
navigationBarMenu?.menuCells = cells
// If we set the container to the controller view, the value must be set
// on the hidden content offset (not the visible one)
navigationBarMenu?.visibleContentOffset = (navigationController?.navigationBar.frame.size.height ?? 44.0) + statusBarHeight
// For a simple gray overlay in background
navigationBarMenu?.backgroundView = UIView(frame: view.bounds)
navigationBarMenu?.backgroundView!.backgroundColor = UIColor.black
navigationBarMenu?.backgroundAlpha = 0.7
}
func updateMenuContentOffsets() {
navigationBarMenu?.visibleContentOffset = (navigationController?.navigationBar.frame.size.height ?? 44.0) + statusBarHeight
}
#IBAction func choose(_ sender: AnyObject) {
let cell = (sender as! DropDownMenuCell)
titleView.title = cell.textLabel!.text
let index = cell.tag
let node = PackageManager.shared.openNodes[index]
if node != currentNode {
initalSegment = 0
currentNode = node
setupNavBar()
splitHTML(forCurrentNode: currentNode)
}
if let menu = navigationBarMenu {
didTapInDropDownMenuBackground(menu)
}
}
#IBAction func willToggleNavigationBarMenu(_ sender: DropDownTitleView) {
sender.isUp ? navigationBarMenu?.hide() : navigationBarMenu?.show()
}
#IBAction func didToggleNavigationBarMenu(_ sender: DropDownTitleView) {
}
}
// MARK: - DropDownMenuDelegate
extension DocumentViewController : DropDownMenuDelegate {
func didTapInDropDownMenuBackground(_ menu: DropDownMenu) {
if menu == navigationBarMenu {
titleView.toggleMenu()
}
else {
menu.hide()
}
}
}
// MARK: - data module
extension DocumentViewController {
func splitHTML(forCurrentNode node:Node) {
node.deleteTemporaryHtmls()
if let nodePath = node.path {
let pathComponents = URL(fileURLWithPath: nodePath).pathComponents
if pathComponents.count >= 2 {
let rootFolder = "\(pathComponents[1])"
readAccessFolder = URL(fileURLWithPath: "\(PackageManager.shared.packageFolder)\(rootFolder)")
}
}
// segmented control
segmentedControl.removeAllSegments()
// process html of current node
do {
sections = try node.processHTMLSections()
if sections.count > 0 {
var index = 0
for sec in sections {
segmentedControl.insertSegment(withTitle: sec["title"], at: index, animated: false)
index += 1
}
//
let hasWCN = sections.first(where: { (sec) -> Bool in
return sec["contenttype"] == "safety"
})
if let _ = hasWCN {
} else {
let index = sections.index(where: { (sec) -> Bool in
return sec["contenttype"] == "container"
})
if let i = index {
initalSegment = i
}
}
//
if initalSegment > 5 {
initalSegment = 0
loadHTML(forSection: initalSegment)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
self.show3DModel(self.show3dModelButton as Any)
})
}
else {
if initalSegment > sections.count {
initalSegment = 0
}
loadHTML(forSection: initalSegment)
}
segmentedControl.selectedSegmentIndex = initalSegment
// configure show 3d model button
let button = UIButton(forAutoLayout: ())
button.imageView?.contentMode = .scaleAspectFit
button.imageView?.tintColor = .gray
button.setImage(UIImage(named: "Next"), for: .normal)
button.backgroundColor = UIColor.lightGray.withAlphaComponent(0.3)
button.borderColor = .black
button.borderWidth = 1.0
button.addTarget(self, action: #selector(DocumentViewController.show3DModel(_:)), for: .touchUpInside)
webViewView.addSubview(button)
button.autoAlignAxis(.horizontal, toSameAxisOf: webViewView)
button.autoSetDimension(.height, toSize: 150.0)
button.autoSetDimension(.width, toSize: 50.0)
show3dModelButtonLeadConstraint = button.autoPinEdge(.trailing, to: .trailing, of: webViewView, withOffset: 0)
show3dModelButton = button
// we dont need the button any longer
show3dModelButton?.isHidden = true
}
} catch {
loadPDF()
segmentedControlHeight.constant = 0
segmentedControlMarginTop.constant = 0
segmentedControlMarginBottom.constant = 0
}
if let dmc = node.moduleCode {
dmcLabel.text = dmc
}
if let issno = node.issueNumber {
issnoLabel.text = issno
}
if let issdate = node.issueDate {
issdateLabel.text = DateFormatter.stringFromDate(issdate, format: "yyyy-MM-dd")
}
let edgePan = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(returnToGraphicView))
edgePan.edges = .right
view.addGestureRecognizer(edgePan)
}
func loadHTML(forSection section: Int) {
URLCache.shared.removeAllCachedResponses()
URLCache.shared.diskCapacity = 0
URLCache.shared.memoryCapacity = 0
if section > sections.count {
return
}
if webview?.isLoading == true {
webview?.stopLoading()
}
if let urlString = sections[section]["url"], let contenttype = sections[section]["contenttype"], let readAccessFolder = readAccessFolder {
var url = URL(fileURLWithPath: urlString)
if var components = URLComponents(url: url, resolvingAgainstBaseURL: false), contenttype == "requirements" {
let sc = URLQueryItem(name: "shoppingcart", value: "true")
let domain = URLQueryItem(name: "domain", value: "*")
components.queryItems = [sc, domain]
if let newUrl = components.url {
url = newUrl
}
}
_ = webview?.loadFileURL(url, allowingReadAccessTo: readAccessFolder)
}
}
func loadPDF() {
URLCache.shared.removeAllCachedResponses()
URLCache.shared.diskCapacity = 0
URLCache.shared.memoryCapacity = 0
if webview?.isLoading == true {
webview?.stopLoading()
}
let fileStr = "\(PackageManager.shared.packageFolder)\(currentNode.path ?? "")"
let url = URL(fileURLWithPath: fileStr)
let request = URLRequest(url: url)
if let readAccessFolder = readAccessFolder {
_ = webview?.loadFileURL(url, allowingReadAccessTo: readAccessFolder)
} else {
_ = webview?.load(request)
}
}
}
// MARK: - Illustrations
extension DocumentViewController {
func showFullscreenFigure(with boardNo: String, and components: URLComponents?) {
if let gv = self.storyboard?.instantiateViewController(withIdentifier: "GraphicsViewController") as? GraphicsViewController {
gv.url = URL(fileURLWithPath: "\(PackageManager.shared.packageFolder)\(currentNode.path ?? "").\(boardNo).$tmp.htm")
gv.caption = components?.queryItems?.filter({ (item) in item.name == "caption"}).first?.value
gv.javascript = components?.queryItems?.filter({ (item) in item.name == "javascript"}).first?.value
gv.readAccessFolder = readAccessFolder
graphicsView = gv
}
if popupController != nil {
popupController?.push(graphicsView!, animated: true)
} else {
navigationController?.pushViewController(graphicsView!, animated: true)
}
}
func showGraphicsView() {
if let graphicsView = graphicsView {
if popupController != nil {
popupController?.push(graphicsView, animated: true)
} else {
navigationController?.pushViewController(graphicsView, animated: true)
}
}
}
func returnToGraphicView(_ recognizer: UIScreenEdgePanGestureRecognizer) {
if recognizer.state == .recognized {
showGraphicsView()
}
}
}
// MARK: - Preview
extension DocumentViewController {
func cancel() {
onClose?()
}
func openDocument() {
onOpen?(currentNode)
}
func showPreview(for node:Node) {
let onOpen:DocumentOpenAction = { node in
self.currentNode = node
PackageManager.shared.setCurrentNodeAndAddToHistory(self.currentNode)
self.initalSegment = 0
self.splitHTML(forCurrentNode: self.currentNode)
self.createDropDownMenu()
}
let contentView = self.storyboard?.instantiateViewController(withIdentifier: "DocumentViewController") as! DocumentViewController
contentView.initalSegment = 0
contentView.currentNode = node
//
if popupController != nil {
contentView.onOpen = self.onOpen
contentView.onClose = self.onClose
self.popupController?.push(contentView, animated: true)
} else {
let popup = STPopupController(rootViewController: contentView)
popup.style = .formSheet
popup.hidesCloseButton = false
popup.backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
popup.containerView.layer.cornerRadius = 4
contentView.onOpen = { node in
popup.dismiss(completion: {
onOpen(node)
})
}
contentView.onClose = {
popup.dismiss(completion: {
// we dont need to split the html again for now
// self.splitHTML(forCurrentNode: self.currentNode)
})
}
popup.present(in: self, completion: nil)
}
contentView.navigationItem.titleView = UILabel.forTitleView(withText: node.title)
}
func showProcedureStepCheckboxes() {
if popupController == nil {
self.webview?.evaluateJavaScript("showProcedureStepCheckboxes()", completionHandler: {(result, error) in
guard let err = error else {return}
print(err)
})
}
}
func setLastScrollingPosition() {
if let code = currentNode.contentobjectcode {
webview?.restoreContentOffset(forKey: code)
}
}
}
// MARK: - Settings
extension DocumentViewController {
func showSettings(_ sender: AnyObject) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "SetSettingsViewController") as! SetSettingsViewController
vc.modalPresentationStyle = .popover
vc.onChange = {
self.changeMarksVisible = (UserDefaults.standard.bool(forKey: "ChangeMarkings"))
self.nightModeOn = (UserDefaults.standard.bool(forKey: "nightTheme"))
}
if let popover = vc.popoverPresentationController {
popover.barButtonItem = settingsButton
popover.permittedArrowDirections = .any
}
present(vc, animated: true, completion: nil)
}
func updateChangeMarking() {
if (self.changeMarksVisible ?? false) {
self.webview?.evaluateJavaScript("handleChangemarks()", completionHandler: {(result, error) in
})
}
else {
self.webview?.evaluateJavaScript("deleteChangemarks()", completionHandler: {(result, error) in
})
}
}
func updateNightMode() {
let mode = self.nightModeOn ?? false
self.webview?.evaluateJavaScript("s1000d.setNightMode(\(mode))", completionHandler: {(result, error) in
})
}
}
// Mark: - Structure Manual
extension DocumentViewController {
func structureButtonPressed(_ sender: AnyObject) {
PackageManager.shared.structureButtonPressed(currentNode)
if let root = self.parent?.parent as? RootTabBarViewController {
root.selectedIndex = 0
if let navController = root.viewControllers?.first as? UINavigationController, let firstController = navController.viewControllers.first as? ManualsViewController {
PackageManager.shared.strucutreArrayNode.removeLast()
for var i in PackageManager.shared.strucutreArrayNode {
print("\(i.title)")
// get next child node
if let next = i.nextChild() {
i = next
}
if i.type == "document" || i.subnodes.count == 0 {
firstController.showDocumentViewController(for: i)
} else {
firstController.navigationController?.pushViewController(i, animated: false)
}
}
}
}
}
}

Update TableViewCell with Asynchronous data

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!

Resources