I have this UITableView that has xib files as cells and it all works as intended, however the last cell only when I scroll down doesn't have a background color. It only happens when I scroll down and then it pops back to normal position. I'm essentially wondering how I can change the color of that cell just to my background color. Thank you.
//
// BlogViewController.swift
// testAPI
//
// Created by Dilan Piscatello on 4/2/20.
// Copyright © 2020 Dilan Piscatello. All rights reserved.
//
import Foundation
import UIKit
import Firebase
class BlogViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
var x = 0
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0{
return 1
}else{
return posts.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0{
let cell = Bundle.main.loadNibNamed("QuestionTableViewCell", owner: self, options: nil)?.first as! QuestionTableViewCell
print("this is how many times it ran")
cell.setPost(question: self.question)
return cell
}
else{
let cell = tableView.dequeueReusableCell(withIdentifier: "postcell", for: indexPath) as! PostTableViewCell
cell.setPost(post: posts[indexPath.row])
return cell
}
}
var question = "sdfsdfs"
var tableView:UITableView!
var lastUploadPostID:String?
var discussion:UILabel! = UILabel()
var posts = [Post]()
var fetchingMore = false
var endReached = false
let leadingScreensForBatching:CGFloat = 3.0
var cellHeights: [IndexPath:CGFloat] = [:]
var refreshControl:UIRefreshControl!
var postRef:DatabaseReference{
return Database.database().reference().child("posts")
}
var oldPostQuery:DatabaseQuery{
var queryRef:DatabaseQuery
let lastPost = self.posts.last
if lastPost == nil{
queryRef = postRef.queryOrdered(byChild: "timestamp")
}else{
let lastTimestamp = lastPost!.createdAt.timeIntervalSince1970*1000
queryRef = postRef.queryOrdered(byChild: "timestamp").queryEnding(atValue: lastTimestamp)
}
return queryRef
}
var newPostQuery:DatabaseQuery{
var queryRef:DatabaseQuery
let firstPost = self.posts.first
if firstPost == nil{
queryRef = postRef.queryOrdered(byChild: "timestamp")
}else{
let firstTimestamp = firstPost!.createdAt.timeIntervalSince1970*1000
queryRef = postRef.queryOrdered(byChild: "timestamp").queryStarting(atValue: firstTimestamp)
}
return queryRef
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func hi(){
let db = Firestore.firestore()
db.collection("blog").document("question").getDocument { (document,error) in
if error != nil{
print("cant get data")
}
if document != nil && document!.exists{
if let documentdata = document?.data() {
self.question = documentdata["question"] as! String
self.tableView.reloadData()
}
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
discussion.text = "Discussion"
//longTitleLabel.font = ................
discussion.font = UIFont(name: "HelveticaNeue-Bold", size: 31)
discussion.translatesAutoresizingMaskIntoConstraints = false
if let navigationBar = self.navigationController?.navigationBar {
navigationBar.addSubview(discussion)
//navigationBar.shadowImage = UIImage()
// navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
// navigationBar.isTranslucent = true
navigationBar.barTintColor = UIColor( red: 128/255, green: 117/255, blue: 255/255, alpha: 1)
discussion.leftAnchor.constraint(equalTo: navigationBar.leftAnchor, constant: 22).isActive = true
discussion.widthAnchor.constraint(equalToConstant: 300).isActive = true
tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
self.tableView.separatorStyle = .none
view.addSubview(tableView)
hi()
print(question)
// Do any additional setup after loading the view.
let cellNib = UINib(nibName: "PostTableViewCell", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "postcell")
var layoutGuide:UILayoutGuide!
layoutGuide = view.safeAreaLayoutGuide
tableView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 10).isActive = true
tableView.topAnchor.constraint(equalTo: view.topAnchor, constant: 40).isActive = true
tableView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -10).isActive = true
tableView.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor).isActive = true
tableView.delegate = self
tableView.dataSource = self
tableView.tableFooterView = UIView()
tableView.reloadData()
refreshControl = UIRefreshControl()
tableView.refreshControl = refreshControl
refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
beginBatchFetch()
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// if let navigationController = navigationController as? ScrollingNavigationController {
// navigationController.followScrollView(tableView, delay: 0.0)
//}
listenForNewPosts()
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
stopListeningForNewPosts()
}
#objc func handleRefresh(){
print()
newPostQuery.queryLimited(toFirst: 20).observeSingleEvent(of: .value, with: { (snapshot) in
var tempPosts = [Post]()
let firstPost = self.posts.first
for child in snapshot.children{
if let childSnapshot = child as? DataSnapshot,
let dict = childSnapshot.value as? [String:Any],
let post = Post.parse(childSnapshot.key, dict),
childSnapshot.key != firstPost?.id{
tempPosts.insert(post, at: 0)
}
}
self.posts.insert(contentsOf: tempPosts, at: 0)
self.tableView.reloadData()
self.refreshControl.endRefreshing()
//let newIndexPaths = (1..<tempPosts.count).map { i in
// return IndexPath(row: i, section: 1)
//}
//self.tableView.insertRows(at: newIndexPaths, with: .top)
// self.refreshControl.endRefreshing()
// self.tableView.scrollToRow(at: IndexPath(row:0,section: 0), at: .top, //animated:true)
//self.listenForNewPosts()
//return completion(tempPosts)
//self.posts = tempPosts
//self.tableView.reloadData()
})
}
func fetchPosts(completion: #escaping(_ posts:[Post])->()){
oldPostQuery.queryLimited(toLast: 20).observeSingleEvent(of: .value, with: { (snapshot) in
var tempPosts = [Post]()
let lastPost = self.posts.last
for child in snapshot.children{
if let childSnapshot = child as? DataSnapshot,
let dict = childSnapshot.value as? [String:Any],
let post = Post.parse(childSnapshot.key, dict),
childSnapshot.key != lastPost?.id{
tempPosts.insert(post, at: 0)
}
}
return completion(tempPosts)
//self.posts = tempPosts
//Zself.tableView.reloadData()
})
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cellHeights[indexPath] = cell.frame.size.height
cell.selectionStyle = UITableViewCell.SelectionStyle.none
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return cellHeights[indexPath] ?? 72.0
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height
if offsetY > contentHeight - scrollView.frame.size.height * leadingScreensForBatching {
if !fetchingMore && !endReached {
beginBatchFetch()
}
}
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
func beginBatchFetch(){
fetchingMore = true
fetchPosts{ newPosts in
self.posts.append(contentsOf: newPosts)
self.endReached = newPosts.count == 0
self.fetchingMore = false
UIView.performWithoutAnimation {
self.tableView.reloadData()
self.listenForNewPosts()
}
}
//fetch the post
}
var postListenerHandle:UInt?
func listenForNewPosts(){
guard !fetchingMore else{ return}
//to avoid the listeners twice (duplicate)
stopListeningForNewPosts()
postListenerHandle = newPostQuery.observe(.childAdded) { (snapshot) in
if snapshot.key != self.posts.first?.id {
if let data = snapshot.value as? [String:Any],
//let post = Post.parse(snapshot.key,data)
let _ = Post.parse(snapshot.key,data){
self.stopListeningForNewPosts()
if snapshot.key == self.lastUploadPostID{
self.handleRefresh()
self.lastUploadPostID = nil
}else{
}
}
}
}
}
func stopListeningForNewPosts(){
if let handle = postListenerHandle{
newPostQuery.removeObserver(withHandle: handle)
postListenerHandle = nil
}
}
// func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
//if let navigationController = navigationController as? //ScrollingNavigationController {
// navigationController.showNavbar(animated: true, scrollToTop: true)
//}
// return true
//}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let newPostNavBar = segue.destination as? UINavigationController,
let newPostVC = newPostNavBar.viewControllers[0] as? WritePostViewController{
newPostVC.delegate = self
}
}
}
extension BlogViewController: NewPostVCDelegate{
func didUploadPost(withID id: String) {
print("what up this is the id \(id)")
self.lastUploadPostID = id
}
}
In the storyboard add inside the tableView as last element a transparent view with height equal to 1
Related
I have a tableview and inside one of my rows I have buttons. I want to deselect all buttons when one is selected and change the background color to the red when button is selected. I saw lots of example but I couldn't do it in my own code.
func configure(_ modelArray : [UnitAndColors], colorTitle:String, packingTitle:String) {
self.unitStackView.removeAllArrangedSubviews()
self.arrayUnitsAndColor?.removeAll()
self.arrayUnitsAndColor = modelArray
let filteredArray = self.arrayUnitsAndColor?.unique { $0.colorDesc }
var i : Int = 0
filteredArray?.forEach { units in
let vw = self.createUnits(units, tag: i)
self.unitStackView.addArrangedSubview(vw)
vw.snp.makeConstraints {
$0.size.equalTo(40.0)
}
i = i + 1
}
}
func createUnits(_ model : UnitAndColors, tag: Int) -> UIStackView {
let stackViewMain = UIStackView()
stackViewMain.axis = .horizontal
stackViewMain.spacing = 4
let labelPackingUnit = UIButton()
labelPackingUnit.backgroundColor = Colors().colorWhite
labelPackingUnit.tag = tag
labelPackingUnit.setTitleColor(Colors().colorRed, for: .normal)
labelPackingUnit.addTarget(self, action: #selector(selectUnit(_:)), for: .touchUpInside)
labelPackingUnit.titleLabel?.font = UIFont.fontBold16
labelPackingUnit.contentHorizontalAlignment = .center
labelPackingUnit.setBorder(width: 1, color: Colors().colorRed)
labelPackingUnit.setCornerRound(value: 20.0)
labelPackingUnit.setTitle(model.unitDesc, for: .normal)
stackViewMain.addArrangedSubview(labelPackingUnit)
labelPackingUnit.snp.makeConstraints {
$0.size.equalTo(40)
}
return stackViewMain
}
#objc private func selectButton(_ sender : UIButton) {
let tag : Int = sender.tag
guard let model : UnitAndColors = self.arrayUnitsAndColor?.filter({ $0.colorDesc == selectedColorName })[tag] else { return }
selectedUnit = model.unitDesc ?? ""
delegate?.changePrice(selectedPrice: model.modelPrice, arrayUnitsAndColor ?? [])
}
It's pretty frustrating to understand what's happening in your code, but I think that's what you're looking for:
#objc private func selectButton(_ sender : UIButton) {
let tag : Int = sender.tag
guard let model: UnitAndColors = self.arrayUnitsAndColor?.filter({ $0.colorDesc == selectedColorName })[tag] else { return }
selectedUnit = model.unitDesc ?? ""
for stackView in unitStackView.arrangedSubviews as? [UIStackView] ?? [] {
guard let button = stackView.arrangedSubviews.first as? UIButton else {
return
}
button.isSelected = false
button.backgroundColor = .clear
}
selectedUnit.isSelected = true
selectedUnit.backgroundColor = .red
delegate?.changePrice(selectedPrice: model.modelPrice, arrayUnitsAndColor ?? [])
}
var selectedRows: [Int] = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.allowMultipleSelection = true
}
func selectAll(){
for i in 0..<totalRows.count{
selectedRows.append(i)
let indexPath = IndexPath(row: i, section: 0)
self.tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
}
}
func deselectAll(){
for i in 0..<totalRows.count{
selectedRows.append(i)
let indexPath = IndexPath(row: i, section: 0)
self.tableView.deselectRow(at: indexPath, animated: true)
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
selectedRows.append(indexPath.row)
print(selectedRows)
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let index = selectedRows.firstIndex(of: indexPath.row) {
selectedRows.remove(at: index)
}
print(selectedRows)
if selectedRows.isEmpty{
}
}
}
class TableViewCell: UITableViewCell{
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
if (selected) {
print("selected")
contentView.backgroundColor = .red
} else {
contentView.backgroundColor = .red
}
}
}
I am creating an app in which i have a controller in which i have a tableview which will show data from previous screen when cell from c ategory section or cell from store section are selected or only one is selected then when i click the double arrow button shown in app then it should navigate to tableview screen and should show all the data from category or store or both into tableview. in tableview controller i have an API which is POST and has a body parameter of 'term_ids' which contains value as 556,574 which is comma seperated means the former one is for category and latter one is for store or both ids contains category data or store data. Means i have to pass two ids and make them comma seperated and then pass to tableview controller
lets say in category screenshot i have selected first two cells and when i tap on double arrow button the selected cell data should pass to another screen whose screenshot is as below:
api link for category data: https://api.myjson.com/bins/wggld
api link for store data: https://api.myjson.com/bins/1fc46p
api link for coupons which i need to populate into tableview based on ID from category and store api link: https://api.myjson.com/bins/1c4dip
my app screenshot for better understanding:
code for my category screen and main home view screen where i want to populate data is as below:
code for categoryViewController is as below:
class CategoryViewController: UIViewController {
//MARK: IBOutlets
#IBOutlet weak var store_bar: UIViewX!
#IBOutlet weak var store_title: UIButton!
#IBOutlet weak var category_title: UIButton!
#IBOutlet weak var category_bar: UIViewX!
#IBOutlet weak var categoryColView: UICollectionView!
var selectedBtnIndex:Int = 1
var selectedIndexPaths = [Int]()
var tempStoreIndexPaths = [Int]()
var categoryData = [ModelCategories]()
var storeData = [ModelStore]()
var arrCategoryImages = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
// register collectionview cell
self.categoryColView.register(UINib(nibName: "CategoryCell1", bundle: nil), forCellWithReuseIdentifier: "CategoryCell1")
self.categoryColView.register(UINib(nibName: "StoresCell", bundle: nil), forCellWithReuseIdentifier: "StoresCell")
self.store_bar.isHidden = true
self.getCategoriesList()
self.getStoreList()
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
#objc func click_Category(sender: UIButton!) {
if sender.isSelected == true {
selectedIndexPaths.append(sender.tag)
sender.setImage(#imageLiteral(resourceName: "image_checked"), for: .normal)
sender.isSelected = false
}else {
selectedIndexPaths = selectedIndexPaths.filter{ $0 != sender.tag }
sender.setImage(#imageLiteral(resourceName: "image_unchecked"), for: .normal)
sender.isSelected = true
}
}
#objc func click_store(sender: UIButton!) {
if sender.isSelected == true {
tempStoreIndexPaths.append(sender.tag)
sender.setImage(#imageLiteral(resourceName: "image_checked"), for: .normal)
sender.isSelected = false
}else {
tempStoreIndexPaths = tempStoreIndexPaths.filter{ $0 != sender.tag }
sender.setImage(#imageLiteral(resourceName: "image_unchecked"), for: .normal)
sender.isSelected = true
}
}
//MARK: IBActions
#IBAction func categoriesData(_ sender: UIButton) {
selectedBtnIndex = 1
self.categoryColView.isHidden = false
self.store_bar.isHidden = true
self.category_title.setTitleColor(UIColor.black, for: .normal)
self.category_bar.isHidden = false
self.store_title.setTitleColor(UIColor(rgb: 0xAAAAAA), for: .normal)
self.categoryColView.reloadData()
}
#IBAction func storeData(_ sender: UIButton) {
selectedBtnIndex = 2
self.categoryColView.isHidden = false
self.store_bar.isHidden = false
self.store_title.setTitleColor(UIColor.black, for: .normal)
self.category_bar.isHidden = true
self.category_title.setTitleColor(UIColor(rgb: 0xAAAAAA), for: .normal)
self.categoryColView.reloadData()
}
#IBAction func showHomeScreen(_ sender: UIButton) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
if selectedBtnIndex == 1 {
vc.couponId = categoryData[sender.tag].ID!
}else {
vc.couponId = storeData[sender.tag].ID!
}
self.navigationController?.pushViewController(vc, animated:true)
}
#IBAction func toSearchPage(_ sender: UIButton) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "SearchPageController") as! SearchPageController
self.navigationController?.pushViewController(vc, animated:true)
}
func getCategoriesList() {
if ApiUtillity.sharedInstance.isReachable() {
ApiUtillity.sharedInstance.StartProgress(view: self.view)
APIClient<ModelBaseCategoryList>().API_GET(Url: SD_GET_CategoriesList, Params: [:], Authentication: true, Progress: true, Alert: true, Offline: false, SuperVC: self, completionSuccess: { (modelResponse) in
ApiUtillity.sharedInstance.StopProgress(view: self.view)
if(modelResponse.success == true) {
self.categoryData.removeAll()
let resul_array_tmp_new = modelResponse.categories! as NSArray
if resul_array_tmp_new.count > 0 {
for i in modelResponse.categories! {
if i.count != 0 {
if let image = UIImage(named: "\(i.slug!.uppercased())") {
self.arrCategoryImages.append(image)
self.categoryData.append(i)
}else {
self.arrCategoryImages.append(UIImage(named: "tickets")!)
self.categoryData.append(i)
}
}
}
}
}
else {
self.view.makeToast(modelResponse.message)
}
ApiUtillity.sharedInstance.StopProgress(view: self.view)
self.categoryColView.reloadData()
}) { (failed) in
ApiUtillity.sharedInstance.StopProgress(view: self.view)
self.view.makeToast(failed.localizedDescription)
}
}
else
{
self.view.makeToast("No Internet Connection..")
}
}
func getStoreList() {
if ApiUtillity.sharedInstance.isReachable() {
ApiUtillity.sharedInstance.StartProgress(view: self.view)
APIClient<ModelBaseStoreList>().API_GET(Url: SD_GET_StoreList, Params: [:], Authentication: true, Progress: true, Alert: true, Offline: false, SuperVC: self, completionSuccess: { (modelResponse) in
ApiUtillity.sharedInstance.StopProgress(view: self.view)
if(modelResponse.success == true) {
self.storeData.removeAll()
let resul_array_tmp_new = modelResponse.store! as NSArray
if resul_array_tmp_new.count > 0 {
for i in modelResponse.store! {
if i.count != 0 {
self.storeData.append(i)
}
}
}
}
else {
self.view.makeToast(modelResponse.message)
}
ApiUtillity.sharedInstance.StopProgress(view: self.view)
self.categoryColView.reloadData()
}) { (failed) in
ApiUtillity.sharedInstance.StopProgress(view: self.view)
self.view.makeToast(failed.localizedDescription)
}
}
else
{
self.view.makeToast("No Internet Connection..")
}
}
}
//MARK: Delegate and Data Source Methods
extension CategoryViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if selectedBtnIndex == 1{
return categoryData.count
}else {
return storeData.count
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if selectedBtnIndex == 1{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CategoryCell1", for: indexPath) as! CategoryCell1
let dict = categoryData[indexPath.row]
if let catName = dict.name, catName.count != 0 {
cell.categoryName.text = catName
}
if let catOffersCount = dict.count {
if catOffersCount == 1 {
cell.catOfferCount.text = "\(catOffersCount)"+" "+"Offer"
}else {
cell.catOfferCount.text = "\(catOffersCount)"+" "+"Offers"
}
}
cell.categoryImage.image = arrCategoryImages[indexPath.row]
cell.btn_click.tag = indexPath.row
cell.btn_click.addTarget(self, action: #selector(self.click_Category), for: .touchUpInside)
if selectedIndexPaths.contains(indexPath.row) {
cell.btn_click.setImage(#imageLiteral(resourceName: "image_checked"), for: .normal)
cell.btn_click.isSelected = true
}else {
cell.btn_click.setImage(#imageLiteral(resourceName: "image_unchecked"), for: .normal)
cell.btn_click.isSelected = false
}
return cell
}else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "StoresCell", for: indexPath) as! StoresCell
let dict = storeData[indexPath.row]
if let storeName = dict.name, storeName.count != 0 {
cell.storeName.text = storeName
}
if let storeOfferCount = dict.count {
cell.storeOfferCount.text = "\(storeOfferCount)"+" "+"Offers"
}
cell.store_btn_click.tag = indexPath.row
cell.store_btn_click.addTarget(self, action: #selector(self.click_store), for: .touchUpInside)
if tempStoreIndexPaths.contains(indexPath.row) {
cell.store_btn_click.setImage(#imageLiteral(resourceName: "image_checked"), for: .normal)
cell.store_btn_click.isSelected = true
}else {
cell.store_btn_click.setImage(#imageLiteral(resourceName: "image_unchecked"), for: .normal)
cell.store_btn_click.isSelected = false
}
return cell
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if selectedBtnIndex == 1{
return CGSize(width: (UIScreen.main.bounds.width) / 3, height: 93)
}else {
return CGSize(width: (UIScreen.main.bounds.width) / 2, height: 48)
}
}
code for homeView COntroller is as below:
import UIKit
class HomeViewController: UIViewController {
var couponsData = [ModelCoupons]()
var couponId = Int()
#IBOutlet weak var homeTblView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.homeTblView.register(UINib(nibName: "HomeCell", bundle: nil), forCellReuseIdentifier: "HomeCell")
self.post_CouponsData()
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
//MARK: IBActions
#IBAction func toCategoryScreen(_ sender: UIButton) {
self.navigationController?.popViewController(animated: true)
}
#IBAction func toSearchPage(_ sender: UIButtonX) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "SearchPageController") as! SearchPageController
self.navigationController?.pushViewController(vc, animated: true)
}
func post_CouponsData() {
if ApiUtillity.sharedInstance.isReachable() {
var params = [String : String]()
params ["term_ids"] = "\(self.couponId)"
ApiUtillity.sharedInstance.StartProgress(view: self.view)
APIClient<ModelBaseCouponsList>().API_POST(Url: SD_POST_CouponsList, Params: params as [String:AnyObject], Authentication: true, Progress: true, Alert: true, Offline: false, SuperVC: self, completionSuccess: { (modelResponse) in
ApiUtillity.sharedInstance.StopProgress(view: self.view)
if(modelResponse.success == true) {
ApiUtillity.sharedInstance.StopProgress(view: self.view)
let dict = modelResponse.coupons
for i in dict! {
self.couponsData.append(i)
}
}else {
self.view.makeToast(modelResponse.message)
}
ApiUtillity.sharedInstance.StopProgress(view: self.view)
self.homeTblView.reloadData()
}) { (failed) in
self.view.makeToast(failed.localizedDescription)
ApiUtillity.sharedInstance.StopProgress(view: self.view)
}
}else {
self.view.makeToast("No internet connection...")
ApiUtillity.sharedInstance.StopProgress(view: self.view)
}
}
}
extension HomeViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return couponsData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeCell", for: indexPath) as! HomeCell
let dict = couponsData[indexPath.row]
if let postTitle = dict.postTitle, postTitle.count != 0 {
cell.ticket_postTitle.text = postTitle
}
if let postContent = dict.postContent, postContent.count != 0 {
cell.ticket_postContent.text = postContent
}
if let storeName = dict.stores, storeName.count != 0 {
cell.storename.text = storeName
}
let dateFormatterGet = DateFormatter()
dateFormatterGet.dateFormat = "yyyy-MM-dd"
let dateFormatterPrint = DateFormatter()
dateFormatterPrint.dateFormat = "dd MMMM yyyy"
let datee = ApiUtillity.sharedInstance.ConvertStingTodate(forApp: dict.validTill!)
cell.ticket_ValidDate.text = dateFormatterPrint.string(from: datee)
cell.ticketImageView.tintColor = .random()
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 339.0
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 339.0
}
}
This question already has an answer here:
Convert an array of Ints to a comma separated string [duplicate]
(1 answer)
Closed 3 years ago.
in my app i have taken an object, lets say var selectedIds = Int. i want this selectedIds to be comma seperated. because i need to send selectedids to next screen in which api calling has parameters which is comma seperated. i should get ids like 556,573 so that i can pass into parameters of receiving controller
the viewcontroller file from which i want to send selectedIds array:
class CategoryViewController: UIViewController {
//MARK: IBOutlets
#IBOutlet weak var store_bar: UIViewX!
#IBOutlet weak var store_title: UIButton!
#IBOutlet weak var category_title: UIButton!
#IBOutlet weak var category_bar: UIViewX!
#IBOutlet weak var categoryColView: UICollectionView!
var selectedBtnIndex:Int = 1
var selectedIds = [Int]()
var storeIds = [Int]()
var categoryData = [ModelCategories]()
var storeData = [ModelStore]()
var arrCategoryImages = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
// register collectionview cell
self.categoryColView.register(UINib(nibName: "CategoryCell1", bundle: nil), forCellWithReuseIdentifier: "CategoryCell1")
self.categoryColView.register(UINib(nibName: "StoresCell", bundle: nil), forCellWithReuseIdentifier: "StoresCell")
self.store_bar.isHidden = true
self.getCategoriesList()
self.getStoreList()
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
#objc func click_Category(sender: UIButton!) {
if sender.isSelected == true {
selectedIds.append(categoryData[sender.tag].ID!)
sender.setImage(#imageLiteral(resourceName: "image_checked"), for: .normal)
sender.isSelected = false
}else {
selectedIds = selectedIds.filter{ $0 != sender.tag }
sender.setImage(#imageLiteral(resourceName: "image_unchecked"), for: .normal)
sender.isSelected = true
}
}
#objc func click_store(sender: UIButton!) {
if sender.isSelected == true {
selectedIds.append(storeData[sender.tag].ID!)
sender.setImage(#imageLiteral(resourceName: "image_checked"), for: .normal)
sender.isSelected = false
}else {
selectedIds = selectedIds.filter{ $0 != sender.tag }
sender.setImage(#imageLiteral(resourceName: "image_unchecked"), for: .normal)
sender.isSelected = true
}
}
//MARK: IBActions
#IBAction func categoriesData(_ sender: UIButton) {
selectedBtnIndex = 1
self.categoryColView.isHidden = false
self.store_bar.isHidden = true
self.category_title.setTitleColor(UIColor.black, for: .normal)
self.category_bar.isHidden = false
self.store_title.setTitleColor(UIColor(rgb: 0xAAAAAA), for: .normal)
self.categoryColView.reloadData()
}
#IBAction func storeData(_ sender: UIButton) {
selectedBtnIndex = 2
self.categoryColView.isHidden = false
self.store_bar.isHidden = false
self.store_title.setTitleColor(UIColor.black, for: .normal)
self.category_bar.isHidden = true
self.category_title.setTitleColor(UIColor(rgb: 0xAAAAAA), for: .normal)
self.categoryColView.reloadData()
}
#IBAction func showHomeScreen(_ sender: UIButton) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
if selectedBtnIndex == 1 {
vc.selectedIds = self.selectedIds
// vc.couponId = categoryData[sender.tag].ID!
}else {
vc.selectedIds = self.selectedIds
}
self.navigationController?.pushViewController(vc, animated:true)
}
#IBAction func toSearchPage(_ sender: UIButton) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "SearchPageController") as! SearchPageController
self.navigationController?.pushViewController(vc, animated:true)
}
func getCategoriesList() {
if ApiUtillity.sharedInstance.isReachable() {
ApiUtillity.sharedInstance.StartProgress(view: self.view)
APIClient<ModelBaseCategoryList>().API_GET(Url: SD_GET_CategoriesList, Params: [:], Authentication: true, Progress: true, Alert: true, Offline: false, SuperVC: self, completionSuccess: { (modelResponse) in
ApiUtillity.sharedInstance.StopProgress(view: self.view)
if(modelResponse.success == true) {
self.categoryData.removeAll()
let resul_array_tmp_new = modelResponse.categories! as NSArray
if resul_array_tmp_new.count > 0 {
for i in modelResponse.categories! {
if i.count != 0 {
if let image = UIImage(named: "\(i.slug!.uppercased())") {
self.arrCategoryImages.append(image)
self.categoryData.append(i)
}else {
self.arrCategoryImages.append(UIImage(named: "tickets")!)
self.categoryData.append(i)
}
}
}
}
}
else {
self.view.makeToast(modelResponse.message)
}
ApiUtillity.sharedInstance.StopProgress(view: self.view)
self.categoryColView.reloadData()
}) { (failed) in
ApiUtillity.sharedInstance.StopProgress(view: self.view)
self.view.makeToast(failed.localizedDescription)
}
}
else
{
self.view.makeToast("No Internet Connection..")
}
}
func getStoreList() {
if ApiUtillity.sharedInstance.isReachable() {
ApiUtillity.sharedInstance.StartProgress(view: self.view)
APIClient<ModelBaseStoreList>().API_GET(Url: SD_GET_StoreList, Params: [:], Authentication: true, Progress: true, Alert: true, Offline: false, SuperVC: self, completionSuccess: { (modelResponse) in
ApiUtillity.sharedInstance.StopProgress(view: self.view)
if(modelResponse.success == true) {
self.storeData.removeAll()
let resul_array_tmp_new = modelResponse.store! as NSArray
if resul_array_tmp_new.count > 0 {
for i in modelResponse.store! {
if i.count != 0 {
self.storeData.append(i)
}
}
}
}
else {
self.view.makeToast(modelResponse.message)
}
ApiUtillity.sharedInstance.StopProgress(view: self.view)
self.categoryColView.reloadData()
}) { (failed) in
ApiUtillity.sharedInstance.StopProgress(view: self.view)
self.view.makeToast(failed.localizedDescription)
}
}
else
{
self.view.makeToast("No Internet Connection..")
}
}
}
//MARK: Delegate and Data Source Methods
extension CategoryViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if selectedBtnIndex == 1{
return categoryData.count
}else {
return storeData.count
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if selectedBtnIndex == 1{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CategoryCell1", for: indexPath) as! CategoryCell1
let dict = categoryData[indexPath.row]
if let catName = dict.name, catName.count != 0 {
cell.categoryName.text = catName
}
if let catOffersCount = dict.count {
if catOffersCount == 1 {
cell.catOfferCount.text = "\(catOffersCount)"+" "+"Offer"
}else {
cell.catOfferCount.text = "\(catOffersCount)"+" "+"Offers"
}
}
cell.categoryImage.image = arrCategoryImages[indexPath.row]
cell.btn_click.tag = indexPath.row
cell.btn_click.addTarget(self, action: #selector(self.click_Category), for: .touchUpInside)
if selectedIds.contains(categoryData[indexPath.row].ID!) {
cell.btn_click.setImage(#imageLiteral(resourceName: "image_checked"), for: .normal)
cell.btn_click.isSelected = true
}else {
cell.btn_click.setImage(#imageLiteral(resourceName: "image_unchecked"), for: .normal)
cell.btn_click.isSelected = false
}
return cell
}else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "StoresCell", for: indexPath) as! StoresCell
let dict = storeData[indexPath.row]
if let storeName = dict.name, storeName.count != 0 {
cell.storeName.text = storeName
}
if let storeOfferCount = dict.count {
cell.storeOfferCount.text = "\(storeOfferCount)"+" "+"Offers"
}
cell.store_btn_click.tag = indexPath.row
cell.store_btn_click.addTarget(self, action: #selector(self.click_store), for: .touchUpInside)
if selectedIds.contains(storeData[indexPath.row].ID!) {
cell.store_btn_click.setImage(#imageLiteral(resourceName: "image_checked"), for: .normal)
cell.store_btn_click.isSelected = true
}else {
cell.store_btn_click.setImage(#imageLiteral(resourceName: "image_unchecked"), for: .normal)
cell.store_btn_click.isSelected = false
}
return cell
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if selectedBtnIndex == 1{
return CGSize(width: (UIScreen.main.bounds.width) / 3, height: 93)
}else {
return CGSize(width: (UIScreen.main.bounds.width) / 2, height: 48)
}
}
The viewcontroller file in which i want selectedIds array:
class HomeViewController: UIViewController {
var couponsData = [ModelCoupons]()
var couponId = Int()
var selectedIds = [Int]()
#IBOutlet weak var homeTblView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.homeTblView.register(UINib(nibName: "HomeCell", bundle: nil), forCellReuseIdentifier: "HomeCell")
self.post_CouponsData()
print(selectedIds)
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
//MARK: IBActions
#IBAction func toCategoryScreen(_ sender: UIButton) {
self.navigationController?.popViewController(animated: true)
}
#IBAction func toSearchPage(_ sender: UIButtonX) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "SearchPageController") as! SearchPageController
self.navigationController?.pushViewController(vc, animated: true)
}
func post_CouponsData() {
if ApiUtillity.sharedInstance.isReachable() {
var params = [String : String]()
params ["term_ids"] = "\(self.selectedIds)"
ApiUtillity.sharedInstance.StartProgress(view: self.view)
APIClient<ModelBaseCouponsList>().API_POST(Url: SD_POST_CouponsList, Params: params as [String:AnyObject], Authentication: true, Progress: true, Alert: true, Offline: false, SuperVC: self, completionSuccess: { (modelResponse) in
ApiUtillity.sharedInstance.StopProgress(view: self.view)
if(modelResponse.success == true) {
ApiUtillity.sharedInstance.StopProgress(view: self.view)
let dict = modelResponse.coupons
for i in dict! {
self.couponsData.append(i)
}
}else {
self.view.makeToast(modelResponse.message)
}
ApiUtillity.sharedInstance.StopProgress(view: self.view)
self.homeTblView.reloadData()
}) { (failed) in
self.view.makeToast(failed.localizedDescription)
ApiUtillity.sharedInstance.StopProgress(view: self.view)
}
}else {
self.view.makeToast("No internet connection...")
ApiUtillity.sharedInstance.StopProgress(view: self.view)
}
}
}
extension HomeViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return couponsData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeCell", for: indexPath) as! HomeCell
let dict = couponsData[indexPath.row]
if let postTitle = dict.postTitle, postTitle.count != 0 {
cell.ticket_postTitle.text = postTitle
}
if let postContent = dict.postContent, postContent.count != 0 {
cell.ticket_postContent.text = postContent
}
if let storeName = dict.stores, storeName.count != 0 {
cell.storename.text = storeName
}
let dateFormatterGet = DateFormatter()
dateFormatterGet.dateFormat = "yyyy-MM-dd"
let dateFormatterPrint = DateFormatter()
dateFormatterPrint.dateFormat = "dd MMMM yyyy"
let datee = ApiUtillity.sharedInstance.ConvertStingTodate(forApp: dict.validTill!)
cell.ticket_ValidDate.text = dateFormatterPrint.string(from: datee)
cell.ticketImageView.tintColor = .random()
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 339.0
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 339.0
}
}
You can convert an array of Ints to an array of strings using
selectedIds.map(String.init)
and then convert that array of strings into a single string like this
selectedIds.map(String.init).joined(separator: ",")
You have to map the Int array to String array and then join the array with separator comma to get a comma separated string.
params["term_ids"] = self.selectedIds.map(String.init).joined(separator: ",")
I try to make a like button and unlike but I it gives me error when I try to press the button in the simulator .if you know any other code for the like button to be much easier will be helpful ( or some websites , yt vids)
#IBOutlet weak var postTextLabel: UILabel!
#IBOutlet weak var subtitleLabel: UILabel!
#IBOutlet weak var profileImageView: UIImageView!
#IBOutlet weak var usernameLabel: UILabel!
#IBOutlet weak var likeLabel : UILabel!
#IBOutlet weak var likeBtn: UIButton!
#IBOutlet weak var unlikeBtn: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
profileImageView.layer.cornerRadius = profileImageView.bounds.height / 2
profileImageView.clipsToBounds = true
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
weak var post:Post?
func set(post:Post) {
self.post = post
var postID : String!
self.profileImageView.image = nil
ImageService.getImage(withURL: post.author.photoURL) { image , url in
guard let _post = self.post else {return}
if _post.author.photoURL.absoluteString == url.absoluteString {
self.profileImageView.image = image
}else {
print("not the right image")
}
}
usernameLabel.text = post.author.username
postTextLabel.text = post.text
subtitleLabel.text = post.createdAt.calenderTimeSinceNow()
}
var postID : String!
#IBAction func likePressed(_ sender: Any) {
self.postID = "post_0"
let ref = Database.database().reference()
let keyToPost = ref.child("posts").childByAutoId().key
ref.child("posts").child(self.postID).observeSingleEvent(of: .value) { (snapshot) in
if let post = snapshot.value as? [String : AnyObject] {
let updateLikes : [ String : Any] = [ "peopleWhoLike/\(keyToPost)" : Auth.auth().currentUser!.uid ]
ref.child("posts").child(self.postID).updateChildValues(updateLikes, withCompletionBlock : {(error ,reff) in
if error == nil {
ref.child("posts").child(self.postID).observeSingleEvent(of : .value, with: { (snap) in
if let properties = snap.value as? [ String : AnyObject] {
if let likes = properties["peopleWhoLike"] as? [String: AnyObject] {
let count = likes.count
self.likeLabel.text = "\(count) Likes"
}
}
})
}
})
}
}
}
#IBAction func unlikedPressed(_ sender:Any) {
let ref = Database.database().reference()
ref.child("posts").child(self.postID).observeSingleEvent(of: .value, with: { (snapshot) in
if let properties = snapshot.value as? [String : AnyObject] {
if let peopleWhoLike = properties["peopleWhoLike"] as? [String: AnyObject] {
for (id,person) in peopleWhoLike {
if person as? String == Auth.auth().currentUser!.uid {
ref.child("posts").child(self.postID).child("peopleWhoLike").child(id).removeValue(completionBlock: {(error , reff)in
if error == nil {
ref.child("posts").child(self.postID).observeSingleEvent(of: .value, with: {(snap) in
if let prop = snap.value as? [String : AnyObject] {
if let likes = prop["peopleWhoLike"] as? [String: AnyObject] {
let count = likes.count
self.likeLabel.text = "\(count) Likes"
ref.child("posts").child(self.postID).updateChildValues(["likes" : count])
} else {
self.likeLabel.text = " 0 Likes"
ref.child("posts").child(self.postID).updateChildValues(["likes" : 0])
}
}
})
}
})
self.likeBtn.isHidden = false
self.unlikeBtn.isHidden = true
self.unlikeBtn.isEnabled = true
break
}
}
}
}
})
ref.removeAllObservers()
}
}
class HomeController: UIViewController, UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return posts.count
case 1:
return fetchingMore ? 1 : 0
default:
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
cell.set(post: posts[indexPath.row])
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "loadingCell", for: indexPath) as! LoadingCell
cell.spinner.startAnimating()
return cell
}
}
var tableView:UITableView!
var cellHeights: [IndexPath : CGFloat] = [:]
var posts = [Post]()
var fetchingMore = false
var endReached = false
let leadingScreensForBatching:CGFloat = 3.0
var refreshControl:UIRefreshControl!
var seeNewPostsButton:SeeNewPostsButton!
var seeNewPostsButtonTopAnchor:NSLayoutConstraint!
var lastUploadedPostID:String?
var postsRef:DatabaseReference {
return Database.database().reference().child("posts")
}
var oldPostsQuery:DatabaseQuery {
var queryRef:DatabaseQuery
let lastPost = posts.last
if lastPost != nil {
let lastTimestamp = lastPost!.createdAt.timeIntervalSince1970 * 1000
queryRef = postsRef.queryOrdered(byChild: "timestamp").queryEnding(atValue: lastTimestamp)
} else {
queryRef = postsRef.queryOrdered(byChild: "timestamp")
}
return queryRef
}
var newPostsQuery:DatabaseQuery {
var queryRef:DatabaseQuery
let firstPost = posts.first
if firstPost != nil {
let firstTimestamp = firstPost!.createdAt.timeIntervalSince1970 * 1000
queryRef = postsRef.queryOrdered(byChild: "timestamp").queryStarting(atValue: firstTimestamp)
} else {
queryRef = postsRef.queryOrdered(byChild: "timestamp")
}
return queryRef
}
#IBAction func handleLogoutButton(_ sender: Any) {
try! Auth.auth().signOut()
}
override func viewDidLoad() {
super.viewDidLoad()
tableView = UITableView(frame: view.bounds, style: .plain)
let cellNib = UINib(nibName: "PostTableViewCell", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "postCell")
tableView.register(LoadingCell.self, forCellReuseIdentifier: "loadingCell")
tableView.backgroundColor = UIColor(white: 0.90,alpha:1.0)
view.addSubview(tableView)
var layoutGuide:UILayoutGuide!
if #available(iOS 11.0, *) {
layoutGuide = view.safeAreaLayoutGuide
} else {
// Fallback on earlier versions
layoutGuide = view.layoutMarginsGuide
}
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor).isActive = true
tableView.topAnchor.constraint(equalTo: layoutGuide.topAnchor).isActive = true
tableView.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor).isActive = true
tableView.delegate = self
tableView.dataSource = self
tableView.reloadData()
refreshControl = UIRefreshControl()
if #available(iOS 10.0, *) {
tableView.refreshControl = refreshControl
} else {
// Fallback on earlier versions
tableView.addSubview(refreshControl)
}
refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
seeNewPostsButton = SeeNewPostsButton()
view.addSubview(seeNewPostsButton)
seeNewPostsButton.translatesAutoresizingMaskIntoConstraints = false
seeNewPostsButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
seeNewPostsButtonTopAnchor = seeNewPostsButton.topAnchor.constraint(equalTo: layoutGuide.topAnchor, constant: -44)
seeNewPostsButtonTopAnchor.isActive = true
seeNewPostsButton.heightAnchor.constraint(equalToConstant: 32.0).isActive = true
seeNewPostsButton.widthAnchor.constraint(equalToConstant: seeNewPostsButton.button.bounds.width).isActive = true
seeNewPostsButton.button.addTarget(self, action: #selector(handleRefresh), for: .touchUpInside)
//observePosts()
beginBatchFetch()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
listenForNewPosts()
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
stopListeningForNewPosts()
}
func toggleSeeNewPostsButton(hidden:Bool) {
if hidden {
// hide it
UIView.animate(withDuration: 0.5, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseOut, animations: {
self.seeNewPostsButtonTopAnchor.constant = -44.0
self.view.layoutIfNeeded()
}, completion: nil)
} else {
// show it
UIView.animate(withDuration: 0.5, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseOut, animations: {
self.seeNewPostsButtonTopAnchor.constant = 12
self.view.layoutIfNeeded()
}, completion: nil)
}
}
#objc func handleRefresh() {
print("Refresh!")
toggleSeeNewPostsButton(hidden: true)
newPostsQuery.queryLimited(toFirst: 20).observeSingleEvent(of: .value, with: { snapshot in
var tempPosts = [Post]()
let firstPost = self.posts.first
for child in snapshot.children {
if let childSnapshot = child as? DataSnapshot,
let data = childSnapshot.value as? [String:Any],
let post = Post.parse(childSnapshot.key, data),
childSnapshot.key != firstPost?.id {
tempPosts.insert(post, at: 0)
}
}
self.posts.insert(contentsOf: tempPosts, at: 0)
let newIndexPaths = (0..<tempPosts.count).map { i in
return IndexPath(row: i, section: 0)
}
self.refreshControl.endRefreshing()
self.tableView.insertRows(at: newIndexPaths, with: .top)
self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
self.listenForNewPosts()
})
}
func fetchPosts(completion:#escaping (_ posts:[Post])->()) {
oldPostsQuery.queryLimited(toLast: 20).observeSingleEvent(of: .value, with: { snapshot in
var tempPosts = [Post]()
let lastPost = self.posts.last
for child in snapshot.children {
if let childSnapshot = child as? DataSnapshot,
let data = childSnapshot.value as? [String:Any],
let post = Post.parse(childSnapshot.key, data),
childSnapshot.key != lastPost?.id {
tempPosts.insert(post, at: 0)
}
}
return completion(tempPosts)
})
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height
if offsetY > contentHeight - scrollView.frame.size.height * leadingScreensForBatching {
if !fetchingMore && !endReached {
beginBatchFetch()
}
}
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cellHeights[indexPath] = cell.frame.size.height
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return cellHeights[indexPath] ?? 72.0
}
func beginBatchFetch() {
fetchingMore = true
self.tableView.reloadSections(IndexSet(integer: 1), with: .fade)
fetchPosts { newPosts in
self.posts.append(contentsOf: newPosts)
self.fetchingMore = false
self.endReached = newPosts.count == 0
UIView.performWithoutAnimation {
self.tableView.reloadData()
self.listenForNewPosts()
}
}
}
var postListenerHandle:UInt?
func listenForNewPosts() {
guard !fetchingMore else { return }
// Avoiding duplicate listeners
stopListeningForNewPosts()
postListenerHandle = newPostsQuery.observe(.childAdded, with: { snapshot in
if snapshot.key != self.posts.first?.id,
let data = snapshot.value as? [String:Any],
let post = Post.parse(snapshot.key, data) {
self.stopListeningForNewPosts()
if snapshot.key == self.lastUploadedPostID {
self.handleRefresh()
self.lastUploadedPostID = nil
} else {
self.toggleSeeNewPostsButton(hidden: false)
}
}
})
}
func stopListeningForNewPosts() {
if let handle = postListenerHandle {
newPostsQuery.removeObserver(withHandle: handle)
postListenerHandle = nil
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let newPostNavBar = segue.destination as? UINavigationController,
let newPostVC = newPostNavBar.viewControllers[0] as? NewPostViewController {
newPostVC.delegate = self
}
}
}
extension HomeController: NewPostVCDelegate {
func didUploadPost(withID id: String) {
self.lastUploadedPostID = id
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
I try to make a like button and unlike but I it gives me error when I try to press the button in the simulator .if you know any other code for the like button to be much easier will be helpful ( or some websites , yt vids)
On this line
ref.child("posts").child(self.postID)
the postID is undefined which is causing the crash. In the comments you state you assign a value to it, but the code in the question doesn't include how that's being done so there's a high likelyhood that value is not being assigned.
The fix would be to assign a value to that class var before that line, like this
#IBAction func likePressed(_ sender: Any) {
self.postID = "post_0" //or however you determine which post it is
// e.g. self.postID = getCurrentPostId()
let ref = Database.database().reference()
let keyToPost = ref.child("posts").childByAutoId().key
ref.child("posts").child(self.postID)...
You may also want to implement some basic error checking as well to ensure the postID is not nil before trying to call the Firebase function.
if let postID = getCurrentPostID() {
//perform the firebase function using postID
} else {
//display an error 'not post selected'
}
recently in the search VC of my app I have been having a major problem with the contraints for weeks. I've redone them 4 times now with no improvement. My tableview cell is not complex -- an imageView located at the left and two labels on top of each other. Most cells size fine. The only thing is that(without pattern) two cells are randomly messed up(the labels and imageView move way out of place). You can see here:
Here is a picture of the constraints for the vc:
The strange thing is that this sometimes occurs when I toggle the scopeButtons up top. I looked in my code to see if I could fix this when the scopeButton reloads the tableview, but I could not find a problematic instance. My code is below:
import UIKit
import Firebase
import Kingfisher
class SearchPostsController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet weak var tableView: UITableView!
var idArray:[String] = []
var detailViewController: DetailViewController? = nil
var candies = [Person]()
var filteredCandies = [Person]()
let searchController = UISearchController(searchResultsController: nil)
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if #available(iOS 11.0, *) {
navigationItem.hidesSearchBarWhenScrolling = false
//initiate the search bar that appears up top when view is segued to
}
if let selectionIndexPath = self.tableView.indexPathForSelectedRow {
self.tableView.deselectRow(at: selectionIndexPath, animated: animated)
}
self.tableView.reloadData()
super.viewWillAppear(animated)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if #available(iOS 11.0, *) {
navigationItem.hidesSearchBarWhenScrolling = true
}
}
override func viewDidLoad() {
super.viewDidLoad()
Database.database().reference()
.child("\(UserData().mySchool!)/posts")
.queryOrderedByKey()//keys were out of order, so we have to use this to help
.observeSingleEvent(of: .value, with: { (snapshot) in
print(snapshot.childrenCount)
for child in snapshot.children.allObjects as! [DataSnapshot] {
print(child.key)
self.idArray.append(child.key)
}
var reversedNames = [String]()
for arrayIndex in 0..<self.idArray.count {
reversedNames.append(self.idArray[(self.idArray.count - 1) - arrayIndex])
//reverse names so we dont have to sort the cells by date
}
for x in reversedNames{
self.searchNames(id: x)//get names from the ids here, tada!!!
self.tableView.reloadData()
}
})
//self.tableView.reloadData()//without this, the results wouldnt show up right away
searchController.searchBar.setScopeBarButtonTitleTextAttributes([NSAttributedStringKey.foregroundColor.rawValue: UIColor.white], for: .normal)
searchController.searchBar.scopeButtonTitles = ["Posts", "Users"]
searchController.searchBar.delegate = self
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search posts or usernames"
searchController.searchBar.showsScopeBar = true
navigationItem.searchController = searchController
definesPresentationContext = true
if let splitViewController = splitViewController {
let controllers = splitViewController.viewControllers
detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
}
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 74
}
// override func viewWillDisappear(_ animated: Bool) {
// candies.removeAll()
// }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DAY69:GRADUATION DAY", for: indexPath) as! SeachCell
cell.cellImageVIew.frame.size.width = 48
cell.cellImageVIew.frame.size.height = 48
let personUser: Person
if isFiltering() {
personUser = filteredCandies[indexPath.row]
} else {
personUser = candies[indexPath.row]
}
//PERSON USER IS IMPORTANT!!!!! ^^^
cell.nameLabel.text = personUser.name.removingPercentEncoding
cell.messageLabel.text = personUser.category.removingPercentEncoding
let name = personUser.name
Database.database().reference().child("users/\(name)/profileImageURL").observe(.value, with: { (snapshot) in
let profURL = "\(snapshot.value!)"
let profIRL = URL(string: profURL)
//set up imageview
cell.cellImageVIew.layer.borderWidth = 1
cell.cellImageVIew.layer.masksToBounds = false
cell.cellImageVIew.layer.borderColor = UIColor.black.cgColor
cell.cellImageVIew.layer.cornerRadius = cell.cellImageVIew.frame.height/2
cell.cellImageVIew.clipsToBounds = true
cell.cellImageVIew.contentMode = .scaleAspectFill
cell.cellImageVIew.kf.indicatorType = .activity
cell.cellImageVIew.kf.setImage(with: profIRL)
})
//TODO: make an extension of imageview to do all this for me. It's getting to be ridiculous
return cell
}
func searchNames(id: String){
// var message = String()
// var name = String()
Database.database().reference().child("\(UserData().mySchool!)/posts/\(id)/message").observe(.value, with: { (snapshot) in
// message = snapshot.value as! String
Database.database().reference().child("\(UserData().mySchool!)/posts").child("\(id)/username").observe(.value, with: { (username) in
// name = username.value as! String
let user = Person(category: "\(snapshot.value!)", name: "\(username.value!)", id: id)
self.candies.append(user)
print( "\(snapshot.value!)", "\(username.value!)")
self.tableView.reloadData()
})
})
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isFiltering() {
return filteredCandies.count
}
return candies.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
tableView.estimatedRowHeight = 74.0
tableView.rowHeight = UITableViewAutomaticDimension
return UITableViewAutomaticDimension
}
// func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
// return 74
// }
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "DAY69:GRADUATION DAY", for: indexPath) as! SeachCell
cell.cellImageVIew.frame.size.width = 48
cell.cellImageVIew.frame.size.height = 48
let searchBar = searchController.searchBar
let scope = searchBar.scopeButtonTitles?[searchBar.selectedScopeButtonIndex]
if scope == "Users"{
let username = candies[indexPath.row].name
print(username)
self.tableView.deselectRow(at: indexPath, animated: true)
performSegue(withIdentifier: "userClicked", sender: username)
}
if scope == "Posts"{
let post = candies[indexPath.row].category
let user = candies[indexPath.row].name
let id = candies[indexPath.row].id
print(post)
let defaults = UserDefaults.standard
defaults.set(id, forKey: "ID")
let def2 = UserDefaults.standard
def2.set(post, forKey: "Post")
def2.set(user, forKey: "USER")
self.tableView.deselectRow(at: indexPath, animated: true)
performSegue(withIdentifier: "postCellTapped", sender: nil)
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
//__________tbv methods above________________________________________________
func searchBarIsEmpty() -> Bool {
// Returns true if the text is empty or nil
return searchController.searchBar.text?.isEmpty ?? true
}
func filterContentForSearchText(_ searchText: String, scope: String = "All") {
filteredCandies = candies.filter({(candy : Person) -> Bool in
let doesCategoryMatch = (scope == "Posts") || (scope == "Users")
print(searchText)
if searchBarIsEmpty() {
return doesCategoryMatch
}
if scope == "Users"{
return doesCategoryMatch && candy.name.lowercased().contains(searchText.addingPercentEncoding(withAllowedCharacters: .alphanumerics)!.lowercased())
}
else{
return doesCategoryMatch && candy.category.lowercased().contains(searchText.addingPercentEncoding(withAllowedCharacters: .alphanumerics)!.lowercased())
}
})
tableView.reloadData()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
if let indexPath = tableView.indexPathForSelectedRow {
let personalUser: Person
if isFiltering() {
personalUser = filteredCandies[indexPath.row]
} else {
personalUser = candies[indexPath.row]
}
}
}
if segue.identifier == "userClicked" {
if let nextView = segue.destination as? UserProfileController {
nextView.selectedUser = "\(sender!)"
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func isFiltering() -> Bool {
let searchBarScopeIsFiltering = searchController.searchBar.selectedScopeButtonIndex != 0
return searchController.isActive && (!searchBarIsEmpty() || searchBarScopeIsFiltering)
}
}
extension SearchPostsController: UISearchResultsUpdating {
// MARK: - UISearchResultsUpdating Delegate
func updateSearchResults(for searchController: UISearchController) {
let searchBar = searchController.searchBar
let scope = searchBar.scopeButtonTitles![searchBar.selectedScopeButtonIndex]
filterContentForSearchText(searchController.searchBar.text!, scope: scope)
}
}
extension SearchPostsController: UISearchBarDelegate {
// MARK: - UISearchBar Delegate
func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
filterContentForSearchText(searchBar.text!, scope: searchBar.scopeButtonTitles![selectedScope])
}
}
Any help would be greatly appreciated in trying to fix the constraints! Thanks!