Swift Tableview Refresh Error - swift

I get this error:
This is my code:
I am using refresh in the tableView section of the project. What could be causing this error during the refresh?
But in which phase it falls to the fault I could not solve that part
var kategoriId = ""
var refresher = UIRefreshControl()
var arrayKonularData = [konularData]()
let singleton = konularClass.sharedGlobal
override func viewDidLoad() {
super.viewDidLoad()
refresher.attributedTitle = NSAttributedString(string: "Yükleniyor")
refresher.addTarget(self, action: #selector(KonuDetayViewController.refresh), for: UIControlEvents.valueChanged)
self.tableview.addSubview(refresher)
KonulariGetir(sirala: "order by tarih desc")
navigationController?.delegate = self
tableview.layer.cornerRadius = 10
}
func refresh()
{
DispatchQueue.main.async {
if self.segmentControl.selectedSegmentIndex == 0
{
self.arrayKonularData.removeAll()
self.KonulariGetir(sirala: "order by tarih desc")
}
if self.segmentControl.selectedSegmentIndex == 1
{
self.arrayKonularData.removeAll()
self.KonulariGetir(sirala: "order by indirimpuani desc")
}
}
DispatchQueue.main.async {
self.refresher.endRefreshing()
}
}
I am taking data from web service in this section
func KonulariGetir(sirala:String)
{
var request = URLRequest(url: URL(string:"http://212.xxx.xxx.xxx:7001/IndirimiKovala/KonuGetir")!)
request.httpMethod = "POST"
let postString = "filtre="+sirala
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil
{
print("error")
}
if let urlContent = data
{
do
{
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
if let gelenDizi = jsonResult as? NSArray
{
for i in 0..<gelenDizi.count
{
if let baslik = (gelenDizi[i] as? NSDictionary)?["baslik"] as? String
{
self.singleton.baslik = baslik
}
if let indirimPuani = (gelenDizi[i] as? NSDictionary)?["indirimpuani"] as? Int
{
self.singleton.indirimPuani = String(indirimPuani)
}
if let konuId = (gelenDizi[i] as? NSDictionary)?["id"] as? Int
{
self.singleton.konuId = String(konuId)
}
if let haberVeren = (gelenDizi[i] as? NSDictionary)?["uye"] as? String
{
self.singleton.haberVerenUye = haberVeren
}
if let gelenTarih = (gelenDizi[i] as? NSDictionary)?["tarih"] as? String
{
self.singleton.tarih = gelenTarih
}
if let gelenAktif = (gelenDizi[i] as? NSDictionary)?["aktif"] as? Int
{
self.singleton.aktif = gelenAktif
}
self.arrayKonularData.append(konularData.init(baslik: self.singleton.baslik, indirimPuani: self.singleton.indirimPuani, konuId: self.singleton.konuId,haberVeren:self.singleton.haberVerenUye , tarih:self.singleton.tarih,aktif:self.singleton.aktif))
}
}
DispatchQueue.main.async {
self.tableview.reloadData()
}
}
catch
{
print("server hatası")
}
}
}
task.resume()
}

I guess the problem comes from the part of code where you try to populate tableview. So the possible solution can be in tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) delegate methode check if arrayKonularData array is not empty like this
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: orderCell, for: indexPath)
if !arrayKonularData.isEmpty {
.....// Your code
}
return cell
}
Another solution (which I thing will be the right solution in your case) add completion function of
func KonulariGetir(sirala:String)
and reload tableview in the completion method

Related

Saving TableView cell using UserDefaults

I'm trying to get cell of tableView using UserDefaults, but after i reload app it is always empty
This is my Model:
struct Note: Codable {
var title: String
var description: String
}
class Notes {
var stock: [Note] = []
}
View contoller
var model = Notes()
This is how i get data
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "TableViewCell")
tableView.reloadData()
if let fetchedData = UserDefaults.standard.data(forKey: "notes") {
let fetchedBookies = try! PropertyListDecoder().decode([Note].self, from: fetchedData)
print(fetchedBookies)
} else {
model.stock = []
}
}
This is my cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
cell.titleOutlet.text = self.model.stock[indexPath.row].title
cell.descriptionOutlet?.text = self.model.stock[indexPath.row].description
return cell
}
How i save data
#IBAction func check(_ sender: Any) {
let newstock = Note(title: "check", description: "check2")
model.stock.append(newstock)
print(model.stock.count)
let bookiesData = try! PropertyListEncoder().encode(model.stock)
UserDefaults.standard.set(bookiesData, forKey: "notes")
tableView.reloadData()
}
Thank you very much!
I recommend you to use Json Encoder/Deocder.
First set your Notes class to conform to Codable:
class Notes: Codable {
var stock: [Note] = []
}
Here is an example of how to use Json Encoder / Decoder:
func save(notes: Notes) throws {
let encoder = JSONEncoder()
do {
let data = try encoder.encode(notes)
UserDefaults.standard.set(data, forKey: "notes")
} catch let error {
throw error
}
}
func load() -> Notes {
guard let data = UserDefaults.standard.data(forKey: "notes") else {
return Notes() // Default
}
let decoder = JSONDecoder()
do {
let object = try decoder.decode(Notes.self, from: data)
return object
} catch {
return Notes() // Default
}
}
In your code just call load() to get your notes from User Defaults
And save(notes:) to save them into User Defaults.

Using Firebase to populate TableviewCell with Collectionview inside

I can populate my TableviewCell with images and upload them to Firebase successfully but not to my CollectionView inside the cell. However, I can upload them to a CollectionView on another ViewController as long as it's not inside a TableViewCell. I experimented with reloading the data but nothing appears and isn't required by the one on the other ViewController. I'm trying to get the "showcaseImages" to appear in the collectionView.
This is what I have to save the data in my structure:
func save ( userInfo: UserInfo, completion: #escaping (Result < Bool, NSError>) -> Void) {
var showcaseImagesDict = [String : String]()
userInfo.showcaseImages.forEach { showcaseImagesDict[UUID().uuidString] = $0 }
userReference.addDocument(data: ["profileImage": userInfo.profileImage, "profileName": userInfo.profileName, "showcaseImages": showcaseImagesDict
]) { (error) in
if let unwrappedError = error {
completion(.failure(unwrappedError as NSError))
}else {
completion(.success(true))
}
}
}
This is what I have to Listen:
func listen (completion : #escaping ([UserInfo]) -> Void) {
userReference.addSnapshotListener { (snapshot, error) in
guard let unwrappedSnapshot = snapshot else {return}
let documents = unwrappedSnapshot.documents
var usersInfo = [UserInfo]()
for document in documents {
let documentData = document.data()
guard
let profileImage = documentData["profileImage"] as? String,
let profileName = documentData["profileName"] as? String,
let showcaseImagesDict = documentData["showcaseImages"] as? [String : String]
else {continue}
let showcaseImages = showcaseImagesDict.map {$0.value}
let userInfo = UserInfo(profileImage: profileImage, profileName: profileName, showcaseImages: showcaseImages)
usersInfo.append(userInfo)
}
completion(usersInfo)
}
}
Heres what I have to populate the TableviewCell:
func populate(with user: UserInfo){
profileName.text = user.profileName
imageCache2?.getImage(named: user.profileImage,completion: { [weak self](image) in
self?.userImage.image = image
//self?.user = user
})
}
This is to populate CollectionViewCell:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CVCell", for: indexPath)
let collectionViewCell1 = cell as? CollectionViewCell
collectionViewCell1?.imageCache4 = imageCache3
let imagePath = showcaseImages[indexPath.item]
collectionViewCell1?.populate(with: imagePath)
return cell
}

using UISegmentedControl in show data tableview

“I’m using segment control and I have two segments, one segment(Recipes) and second segment(Restaurant) click i should click first segment and data show first-array and second segment click second segment and data show secondary”
var dataArray = [FollowedData]()
var restdataArray = [RestaurantFollowed]()
#IBAction func btnActionSegmnet(_ sender: UISegmentedControl) {
switch (segmentSelect.selectedSegmentIndex) {
case 0:
dataArray.removeAll()
ShowPostRecipesData()
tableView.reloadData()
break
case 1:
restdataArray.removeAll()
ShowPostRestaurantsData()
tableView.reloadData()
break
default:
break
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch (segmentSelect.selectedSegmentIndex) {
case 0:
return dataArray.count
case 1:
return restdataArray.count
default:
return 0
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 430
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FollowedCell")as! FollowedCell
switch (segmentSelect.selectedSegmentIndex)
case 0:
cell.tittleLbl.text = dataArray[indexPath.row].postDetailsData.title
cell.descriptionLbl.text = dataArray[indexPath.row].postDetailsData.descriptions
let date = getDateFromTime(timeStanp: dataArray[indexPath.row].mbersdata.created)
cell.showDateLbl.text = date + "/ " + dataArray[indexPath.row].postDetailsData.viewscount + "views "
let urlString = "https://myfoodtalk.com:3001/storage/posts/\(dataArray[indexPath.row].postDetailsData.image1)"
let escapedString1 = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
print(escapedString1!)
if let imgurls = URL(string: escapedString1!) {
print(imgurls)
cell.recipesImage.sd_setImage(with:imgurls, placeholderImage: UIImage(named:"placeholder"))
}
let urlStrings = "https://myfoodtalk.com:3001/storage/members/\(dataArray[indexPath.row].mbersdata.photo)"
let escapedStrings = urlStrings.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
print(escapedStrings!)
if let imgurl = URL(string: escapedStrings!) {
print(imgurl)
cell.userImage.sd_setImage(with:imgurl, placeholderImage: UIImage(named:"placeholder"))
}
break
case 1:
cell.tittleLbl.text = restdataArray[indexPath.row].restaurantDetailsData.title
cell.descriptionLbl.text = restdataArray[indexPath.row].restaurantDetailsData.descriptions
let dates = getDateFromTime(timeStanp: restdataArray[indexPath.row].created)
cell.showDateLbl.text = dates + "/ " + restdataArray[indexPath.row].restaurantDetailsData.viewscount + "views "
let urls = "https://myfoodtalk.com:3001/storage/members/\(restdataArray[indexPath.row].mbersdata.photo)"
let escapedString2 = urls.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
print(escapedString2!)
if let imgurls = URL(string: escapedString2!) {
print(imgurls)
cell.userImage.sd_setImage(with:imgurls, placeholderImage: UIImage(named:"placeholder"))
}
let url = "https://myfoodtalk.com:3001/storage/restaurants/\(restdataArray[indexPath.row].restaurantDetailsData.image1)"
let escapedStrings3 = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
print(escapedStrings3!)
if let imgurl = URL(string: escapedStrings3!) {
print(imgurl)
cell.recipesImage.sd_setImage(with:imgurl, placeholderImage: UIImage(named:"placeholder"))
}
break
default:
break
}
return cell
}
func ShowPostRecipesData(){
let accessToken = UserDefaults.standard.value(forKey: "access_token")as! String
let userid = UserDefaults.standard.value(forKey: "userId")as! String
var mainString = ""
var url = ""
mainString = """
{"where":{"m_id":"\(userid)"},"include":[{"relation":"posts"},{"relation":"members"}]}
"""
url = "follow-posts?filter=\(mainString)&access_token=\(accessToken)"
let escapedString = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
print(escapedString!)
FTHelper.requestGETURLArray(escapedString!, isShowHud: true, headers: nil, success:
{ (response) in
let dataArray = response
if dataArray.isEmpty{
_ = presentAlertWithOptions("", message: "You have no recipes data ", controller: self, buttons: ["OK"], tapBlock:
{
(UIAlertAction, position) in
if position == 0{
}
})
}else{
let followObj = FollowedData()
self.dataArray = followObj.getfollowData(dataArray: dataArray)
self.tableView.reloadData()
}
})
{ (error) in
print(error)
}
}
func ShowPostRestaurantsData(){
let accessToken = UserDefaults.standard.value(forKey: "access_token")as! String
let mid = UserDefaults.standard.value(forKey: "userId")as! String
var mainString = ""
var url = ""
mainString = """
{"where":{"m_id": "\(mid)"},"include":[{"relation":"restaurants"},{"relation":"members"}]}
"""
url = "follow-restaurants?filter=\(mainString)&access_token=\(accessToken)"
let escapedString = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
print(escapedString!)
FTHelper.requestGETURLArray(escapedString!, isShowHud: true, headers: nil, success:
{ (response) in
let dataArray = response
if dataArray.isEmpty{
_ = presentAlertWithOptions("", message: "You have no recipes data ", controller: self, buttons: ["OK"], tapBlock:
{
(UIAlertAction, position) in
if position == 0{
}
})
}else{
let followObj = RestaurantFollowed()
self.restdataArray = followObj.getfollowData(dataArray: dataArray)
self.tableView.reloadData()
}
})
{ (error) in
print(error)
}
}
I am click first segment data show on tableview but I am click on second segment but data not show in tableview I can not understand what I can do

strange tableView.reloadData() behavior

I am trying to make simple firebase realtime chat app in swift. I have node in my database where number of unread messages is stored/
I have custom tableview cell which has label for displaying number of unread messages
class UserCell: UITableViewCell {
var message: Message? {
didSet {
setNumberOfUnreadMessages()
}
fileprivate func setNumberOfUnreadMessages() {
if let partnerId = message?.chatPartnerId(), let selfId = message?.selfId() {
let unreadMessagesRef = Database.database().reference().child("unread-messages").child(selfId).child(partnerId).child("numberOfUnreadMessages")
unreadMessagesRef.observe(.value, with: { (snapshot) in
if let count = snapshot.value as? Int {
self.unreadMessagesCountLabel.isHidden = false
self.unreadMessagesCountLabel.text = String(count)
} else {
self.unreadMessagesCountLabel.isHidden = true
}
print(snapshot)
}, withCancel: nil)
}
}
My tableView
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as? UserCell
let message = messages[indexPath.row]
cell?.message = message
return cell!
}
func observeUserMessages() {
guard let uid = Auth.auth().currentUser?.uid else { return }
// getting reference to current user's node
let ref = Database.database().reference().child("user-messages").child(uid)
ref.observe(.childAdded, with: { (snapshot) in
let userId = snapshot.key
// getting reference to partners node in user's node
let userMessagesRef = Database.database().reference().child("user-messages").child(uid).child(userId)
userMessagesRef.observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String:AnyObject] {
let message = Message(dictionary: dictionary)
if let chatPartnerId = message.chatPartnerId() {
self.messagesDictionary[chatPartnerId] = message
}
self.attemptReloadOfTableView()
}
}, withCancel: nil)
}, withCancel: nil)
ref.observe(.childRemoved, with: { (snapshot) in
print(snapshot.key)
self.messagesDictionary.removeValue(forKey: snapshot.key)
self.attemptReloadOfTableView()
}, withCancel: nil)
}
// Big thank to Brian Woong)))))
var timer: Timer?
private func attemptReloadOfTableView() {
self.timer?.invalidate()
self.timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(self.handleReloadTableView), userInfo: nil, repeats: false)
}
#objc func handleReloadTableView() {
self.messages = Array(self.messagesDictionary.values)
self.messages.sort(by: { (message1, message2) -> Bool in
return (message1.timeStamp?.intValue)! > (message2.timeStamp?.intValue)!
})
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
When I start my app every tableView.cell shows correct number of unread messages from database. When I start to send messages, tableView reloads and begins to show the number of unread messages from sender not only on his cell, but on ALL cells. Moreover in console I see that it gets more and more snapshots from database with every upcoming message.
What happens? How to fix this strange bug?
let unreadMessagesRefHandle = unreadMessagesRef.observe(.value, with: { (snapshot) in
if let count = snapshot.value as? Int {
self.unreadMessagesCountLabel.isHidden = false
self.unreadMessagesCountLabel.text = String(count)
} else {
self.unreadMessagesCountLabel.isHidden = true
}
print(snapshot)
}, withCancel: nil)
unreadMessagesRef.removeObserver(withHandle: unreadMessagesRefHandle)

Swift - No data displayed in TableView after Retrieving it from UserDefaults

I am trying to get the data I have saved and then load it into the TableView. Currently, if I am saving the object for the first time, the data gets encoded, saved, decoded, read and displayed correctly. However, if the key already exists and I am adding to the existing data, nothing gets displayed in the TableView.
This is currently how I am saving it in the first view controller:
let userEntry = UserEntries(date: String(todayDate), questions: [UserEntries.Question(question: q1Text, answer: q1Answer), UserEntries.Question(question: q2Text, answer: q2Answer)])
var allEntries : [UserEntries] = []
if doesKeyExist(key: "allEntries") == true {
let jsonDecoder = JSONDecoder()
if let data = UserDefaults.standard.data(forKey: "allEntries"),
let userEntries = try? jsonDecoder.decode(UserEntries.self, from: data) {
allEntries = [userEntries]
}
allEntries.insert(userEntry, at: 0)
let jsonEncoder = JSONEncoder()
if let value = try? jsonEncoder.encode(allEntries) {
UserDefaults.standard.set(value, forKey: "allEntries")
UserDefaults.standard.synchronize()
}
} else {
let jsonEncoder = JSONEncoder()
if let value = try? jsonEncoder.encode(userEntry) {
UserDefaults.standard.set(value, forKey: "allEntries")
UserDefaults.standard.synchronize()
}
}
let newViewController = storyboard?.instantiateViewController(withIdentifier: "tabViewController") as! UITabBarController
present(newViewController, animated: true, completion: nil)
}
This is how I'm displaying it in the TableView
var TableData : [UserEntries] = []
override func viewDidLoad() {
super.viewDidLoad()
let jsonDecoder = JSONDecoder()
if let data = UserDefaults.standard.data(forKey: "allEntries"),
let userEntries = try? jsonDecoder.decode(UserEntries.self, from: data) {
print(userEntries.date)
TableData = [userEntries]
}
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return TableData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "entryCell", for: indexPath)
cell.textLabel?.text = TableData[indexPath.row].date
cell.detailTextLabel?.text = TableData[indexPath.row].questions[0].answer
return cell
}
I have a feeling that this is a logic error, in getting/displaying the data in the TableView, but am unsure of what exactly it is/how to fix it. Thank you for your help!
I don't know what your doesKeyExists function does but you can improve your data manipulation by this way:
let userEntry = UserEntries(date: String(todayDate), questions: [UserEntries.Question(question: q1Text, answer: q1Answer), UserEntries.Question(question: q2Text, answer: q2Answer)])
var allEntries : [UserEntries] = []
let jsonDecoder = JSONDecoder()
if let data = UserDefaults.standard.data(forKey: "allEntries"),
let userEntries = try? jsonDecoder.decode([UserEntries].self, from: data) {
allEntries = userEntries
}
allEntries.insert(userEntry, at: 0)
let jsonEncoder = JSONEncoder()
if let value = try? jsonEncoder.encode(allEntries) {
UserDefaults.standard.set(value, forKey: "allEntries")
UserDefaults.standard.synchronize()
}
let newViewController = storyboard?.instantiateViewController(withIdentifier: "tabViewController") as! UITabBarController
present(newViewController, animated: true, completion: nil)
}
And the problem with your controller is that you are saving only one entry to UserDefaults. Try to change your code to
let jsonDecoder = JSONDecoder()
if let data = UserDefaults.standard.data(forKey: "allEntries"),
let userEntries = try? jsonDecoder.decode([UserEntries].self, from: data) {
print(userEntries)
TableData = userEntries
}