at first sorry for my bad english.
My problem is that my tableview will be misrepresented as soon as I save a new file in Firebase.
When saving, a new AddViewController is called.
After saving is automatically returned to the TableviewController.
However, if I stop and restart the app so that the TableviewController is recreated, my tableview will be displayed correctly.
I create a header from an array.
Then I create the cell from another array.
I do not understand why my tableview is displayed incorrectly when I return after saving, but when I recreate the view after the app has finished everything is shown correctly.
My sample pictures:
that's right:
that's bad
My Code from TableViewController:
override func viewDidLoad() {
super.viewDidLoad()
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "Pull to refresh")
refresher.addTarget(self, action: #selector(TagebuchViewController.refresh), for: UIControlEvents.valueChanged)
tableView.addSubview(refresher)
loadTableview()
}
Load data from Firebase, loadTableView():
func loadTableview(){
let userID = Firebase.Auth.auth().currentUser?.uid
databaseRef = Database.database().reference().child("DiabetesIOS").child(userID!)
databaseRef.observe(.value, with: {(snapshot) in
var newItems = [Post]()
var newItemsDate = [String]()
var aNewTime = [String]()
var aNewBl = [String]()
var aNewK = [String]()
var aNewBo = [String]()
var aNewBa = [String]()
var aNewBlu = [String]()
var aNewP = [String]()
var aNewN = [String]()
var dimArrayNewTime = [[String]]()
var dimArrayNewBl = [[String]]()
var dimArrayNewK = [[String]]()
var dimArrayNewBo = [[String]]()
var dimArrayNewBa = [[String]]()
var dimArrayNewBlu = [[String]]()
var dimArrayNewP = [[String]]()
var dimArrayNewN = [[String]]()
for year in snapshot.children.allObjects as! [DataSnapshot] {
for month in year.children.allObjects as! [DataSnapshot] {
for day in month.children.allObjects as! [DataSnapshot] {
for date in day.children.allObjects as! [DataSnapshot] {
for time in date.children.allObjects as! [DataSnapshot] {
let newPost = Post(snapshot: time)
newItems.append(newPost)
let newDate = Post(snapshot: time)
newItemsDate.append(newDate.snap6Date!)
if self.snapshotCheck == 0{
self.snapshotCheckDate = newDate.snap6Date
self.snapshotCheck += 1
}
else{
}
if self.snapshotCheckDate == newDate.snap6Date{
aNewTime.append(newDate.time)
aNewBl.append(newDate.blutzucker)
aNewKe.append(newDate.ke)
aNewBo.append(newDate.bolusInsulin)
aNewBa.append(newDate.basalInsulin)
aNewBlu.append(newDate.blutdruck)
aNewP.append(newDate.puls)
aNewN.append(newDate.notiz)
}
else{
dimArrayNewTime.append(aNewTime)
dimArrayNewBl.append(aNewBlutzucker)
dimArrayNewK.append(aNewKe)
dimArrayNewBo.append(aNewBolusinsulin)
dimArrayNewBa.append(aNewBasalinsulin)
dimArrayNewBlu.append(aNewBlutdruck)
dimArrayNewP.append(aNewPuls)
dimArrayNewN.append(aNewNotiz)
aNewTime.removeAll()
aNewBl.removeAll()
aNewK.removeAll()
aNewBo.removeAll()
aNewBa.removeAll()
aNewBlu.removeAll()
aNewP.removeAll()
aNewN.removeAll()
aNewTime.append(newDate.time)
aNewBl.append(newDate.blutzucker)
aNewK.append(newDate.ke)
aNewBo.append(newDate.bolusInsulin)
aNewBa.append(newDate.basalInsulin)
aNewBlu.append(newDate.blutdruck)
aNewP.append(newDate.puls)
aNewN.append(newDate.notiz)
self.snapshotCheckDate = newDate.snap6Date
}
}
}
}
}
}
self.postArrayValue = newItems
self.aHeaderDate = newItemsDate
self.aHeaderDate = self.uniq(source: self.aHeaderDate)
dimArrayNewTime.append(aNewTime)
dimArrayNewBl.append(aNewBl)
dimArrayNewK.append(aNewK)
dimArrayNewBo.append(aNewBo)
dimArrayNewBa.append(aNewBa)
dimArrayNewBlu.append(aNewBlu)
dimArrayNewP.append(aNewP)
dimArrayNewN.append(aNewN)
self.dimArrayTime = dimArrayNewTime
self.dimArrayBl = dimArrayNewBl
self.dimArrayK = dimArrayNewK
self.dimArrayBo = dimArrayNewBo
self.dimArrayBa = dimArrayNewBa
self.dimArrayBlu = dimArrayNewBlu
self.dimArrayP = dimArrayNewP
self.dimArrayN = dimArrayNewN
newItems.removeAll()
newItemsDate.removeAll()
aNewTime.removeAll()
aNewBl.removeAll()
aNewK.removeAll()
aNewBo.removeAll()
aNewBa.removeAll()
aNewBlu.removeAll()
aNewP.removeAll()
aNewN.removeAll()
dimArrayNewTime.removeAll()
dimArrayNewBl.removeAll()
dimArrayNewK.removeAll()
dimArrayNewBo.removeAll()
dimArrayNewBa.removeAll()
dimArrayNewBlu.removeAll()
dimArrayNewP.removeAll()
dimArrayNewN.removeAll()
self.tableView.reloadData()
}){
(error) in
print(error.localizedDescription)
}
}
For my Header:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = Bundle.main.loadNibNamed("TableViewCell1", owner: self, options: nil)?.first as! TableViewCell1
headerView.date.text = aHeaderDate[section]
headerView.backgroundColor = UIColor.white
return headerView
}
NumberOfRows:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dimArrayTime[section].count
}
Number of Headers:
override func numberOfSections(in tableView: UITableView) -> Int {
return aHeaderDate.count
}
Number of Cells:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dimArrayTime[section].count
}
Section:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell2 = Bundle.main.loadNibNamed("TableViewCell2", owner: self, options: nil)?.last as! TableViewCell2
let sectionTime = dimArrayTime[indexPath.section][indexPath.row]
let sectionBl = dimArrayBl[indexPath.section][indexPath.row]
let sectionK = dimArrayK[indexPath.section][indexPath.row]
let sectionBo = dimArrayBo[indexPath.section][indexPath.row]
let sectionBa = dimArrayBa[indexPath.section][indexPath.row]
let sectionBlu = dimArrayBlu[indexPath.section][indexPath.row]
let sectionP = dimArrayP[indexPath.section][indexPath.row]
let sectionN = dimArrayN[indexPath.section][indexPath.row]
cell2.time.text = sectionTime
cell2.bl.text = sectionBl
cell2.k.text = sectionK
cell2.bo.text = sectionBo
cell2.ba.text = sectionBa
cell2.blu.text = sectionBlu
cell2.p.text = sectionP
cell2.n.text = sectionN
return cell2
}
addViewController:
#IBAction func saveInDatabaseFirebase(_ sender: Any) {
let userID = Firebase.Auth.auth().currentUser?.uid
let postRef = dataRef.child("DIOS").child(userID!).child(stringForDbYear).child(stringForDbMonth).child(stringForDbDay).child(stringForDbDate).child(stringForDbTime)
sDate = tFDate.text!
if tFBl.text == "" {
sBl = "-"
}
else{
sBl = tFBl.text!
}
if tFK.text == "" {
sK = "-"
}
else{
sK = tFK.text!
}
if tFBo.text == "" {
sBo = "-"
}
else{
sBo = tFBo.text!
}
if tFBa.text == "" {
sBa = "-"
}
else{
sBa = tFBa.text!
}
if tfBlu.text == "" {
sBlu = "-"
}
else{
sBlu = tfBlu.text!
}
if tFP.text == "" {
sP = "-"
}
else{
sP = tFP.text!
}
if tFN.text == "" {
sN = "-"
}
else{
sN = tFN.text!
}
let post = Post (date: stringForDbDate, time: stringForDbTime, day: stringForDbDay, bl: sBl, k: sK, bo: sBo, ba: sBa, blu: sBlu, p: sP, n: sN, snap1DIOS: "DIOS", snap2UserID: userID!, snap3Year: stringForDbYear, snap4Month: stringForDbMonth, snap5Day: stringForDbDay, snap6Date: stringForDbDate, snap7Time: stringForDbTime)
postRef.setValue(post.toAnyObject())
self.dismiss(animated: true, completion: nil);
}
Thank you very much for help
Related
I have added chatting/messaging to my application. I can go to a users profile, select message and message them.
I also added a tab that show all the users I messaged which is in a table view and you can click a user and see messages between you and them.
The issue happens when I open this tab to see the users Ive messaged when I've messaged more than 10 users. The simulator crashes and I get this error:
"Thread 1: Exception: "Invalid Query. 'in' filters support a maximum of 10 elements in the value array."
here is my code:
import UIKit
import FirebaseFirestore
class MessagingVC: UIViewController {
#IBOutlet weak var tableView: UITableView! { didSet {
tableView.tableFooterView = UIView()
tableView.contentInset.top = 10
}}
#IBOutlet weak var noDataLabel: UILabel!
private let db = Firestore.firestore()
var users = [AppUser]()
var user: AppUser {
return UserManager.currentUser!
}
private var lastMessageDict: [String: Date]?
private var unreadMessageDict: [String: Bool]?
var chatListener: ListenerRegistration?
override func viewDidLoad() {
super.viewDidLoad()
getChats()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
noDataLabel.isHidden = true
// remove any blocked users when entering the screen.
users.removeAll() { self.user.blockedUsers?.contains($0.uid) == true }
// filter hidden users
users = users.filter { $0.isHidden ?? false == false }
tableView.reloadData()
// getChats()
}
// Get all users id that the current user has been chating with.
func getChats() {
let chatCollection = db.collection("chat")
chatListener = chatCollection.whereField("participants", arrayContains: user.uid).addSnapshotListener { [unowned self] (querySnapshot, error) in
guard error == nil else {
print(error!.localizedDescription)
return
}
var userChatIds = [String]()
self.lastMessageDict = [String: Date]()
self.unreadMessageDict = [String: Bool]()
for chat in querySnapshot?.documents ?? [] {
let chatData = chat.data()
if let participants = chatData["participants"] as? [String] {
for particiant in participants {
if particiant != self.user.uid,
!(self.user.blockedUsers?.contains(particiant) == true),
!userChatIds.contains(particiant) {
userChatIds.append(particiant)
if let lastMessageDate = chatData["last message"] as? Timestamp {
self.lastMessageDict![particiant] = lastMessageDate.dateValue()
}
if let unreadMessageDict = chatData["unread message"] as? [String: Bool],
let unreadMesage = unreadMessageDict[self.user.uid] {
self.unreadMessageDict![particiant] = unreadMesage
}
}
}
}
}
if !userChatIds.isEmpty {
self.getChatsInfo(chatIds: userChatIds)
} else {
self.tableView.reloadData()
self.noDataLabel.isHidden = self.users.count > 0
}
}
}
func getChatsInfo(chatIds: [String]) {
getUsersForChat(chatIds) { (users, error) in
guard error == nil else {
print(error?.localizedDescription ?? "")
return
}
for user in users {
if let index = self.users.firstIndex(of: user) {
self.users[index] = user
} else {
self.users.append(user)
}
}
// self.users = users
self.users.sort { (first, second) -> Bool in
let firstDate = self.lastMessageDict?[first.uid]
let secondDate = self.lastMessageDict?[second.uid]
if firstDate == nil { return false }
else if secondDate == nil { return true }
else {
return firstDate! > secondDate!
}
}
self.users = self.users.filter { $0.isHidden ?? false == false }
self.tableView.reloadData()
self.noDataLabel.isHidden = self.users.count > 0
}
}
func getUsersForChat(_ ids: [String], completion:#escaping (_ users: [AppUser], _ error: Error?)->()) {
var allUsers = [AppUser]()
let allids = self.users.map { $0.uid }
let ids = ids.filter { !allids.contains($0) }
if ids.count == 0 {
completion(allUsers, nil)
return
}
var error: Error?
let userCollection = db.collection("users")
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
userCollection.whereField("uid", in: ids).getDocuments {querySnapshot,err in
error = err
var users = [AppUser]()
for document in querySnapshot?.documents ?? [] {
if let restaurant = Restaurant(snapshot: document) {
users.append(restaurant)
}
}
allUsers.append(contentsOf: users)
dispatchGroup.leave()
}
dispatchGroup.enter()
let userCollection2 = db.collection("users2")
userCollection2.whereField("uid", in: ids).getDocuments {querySnapshot,err in
error = err
var users = [AppUser]()
for document in querySnapshot?.documents ?? [] {
if let user = AppUser(snapshot: document) {
users.append(user)
}
}
allUsers.append(contentsOf: users)
dispatchGroup.leave()
}
dispatchGroup.notify(queue: DispatchQueue.main) {
completion(allUsers, error)
}
}
deinit {
chatListener?.remove()
}
}
extension MessagingVC: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return users.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell", for: indexPath) as! MessagingTableViewCell
let user = users[indexPath.row]
cell.nameLabel.text = user.firstName + " " + user.lastName
if let unreadMessage = unreadMessageDict?[user.uid],
unreadMessage == true {
cell.unreadMessageIndicatorLabel.isHidden = false
} else {
cell.unreadMessageIndicatorLabel.isHidden = true
}
cell.photoImageView.image = nil
user.getProfileImage { (image) in
DispatchQueue.main.async {
if let cell = tableView.cellForRow(at: indexPath) as? MessagingTableViewCell {
cell.photoImageView.image = image
}
}
}
if let rest = user as? Restaurant {
cell.categoryImageView.image = UIImage(named: rest.Categories1)
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let user = users[indexPath.row]
// unreadMessageDict?[user.uid] = false
performSegue(withIdentifier: "messagingToChatSegue", sender: user)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "messagingToChatSegue" {
let chatVC = segue.destination as! ChatViewController
let otherUser = sender as! AppUser
chatVC.currentUser = user
chatVC.otherUser = otherUser
chatVC.channelId = ClickedResturantVC.generateIdForMessages(user1Id: user.uid, user2Id: otherUser.uid)
}
}
}
Here is a picture of the error I am getting
Here is a picture of my Firestore database
The error message is telling you that Firestore doesn't support more than 10 items in the ids array that you pass to this query filter:
userCollection.whereField("uid", in: ids)
According to the documentation for this sort of query:
Note the following limitations for in and array-contains-any:
in and array-contains-any support up to 10 comparison values.
If you need more than 10, you will need to batch them into multiple queries.
“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
I am using collection view for displaying result.I want to delete particular cell when that cell is selected. To keep record of selected cell, i am using struct.Everything is working perfectly. But when i click delete button selected cell are not getting deleted.Some other cell gets deleted. But when i go back to the previous screen and come back again ,the cell which i wanted to be deleted is actually removed. I don't know why and how this is happening?
import UIKit
import GRDBCipher
class AdvisoryViewController:
UIViewController,UICollectionViewDelegate,UICollectionViewDataSource {
#IBOutlet weak var new_advisory_label: UILabel!
var getname=String()
var array=[String]()
var date_array=[String]()
var crop_code:String=""
var dbQueue:DatabaseQueue? = nil
var ss = [Int]()
var struct_array :[myObject] = []
var msg_stat:[oldMsg] = []
var msg_count_array=[Int]()
var msg_array=[String]()
var selected_date_array=[String]()
var srno_array=[String]()
var selected_srno_array=[String]()
#IBOutlet weak var collection_view: UICollectionView!
struct myObject
{
var date: String
var advisory:String
var status: String
var srno: String
}
struct oldMsg
{
var is_checked: Bool
}
override func viewDidLoad() {
super.viewDidLoad()
do{
let longpress1=UILongPressGestureRecognizer(target: self, action: #selector(longpress))
// longpress1.minimumPressDuration=1
collection_view.addGestureRecognizer(longpress1)
let
path=NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,
true).first!
dbQueue = try DatabaseQueue(path: "\(path)/pest_messenger.sqlite")
try dbQueue?.inDatabase { db in
let crop_sursor = try Row.fetchCursor(db, "SELECT * FROM crop_master where crop_name='\(getname)'")
while let row = try crop_sursor.next() {
let title: String = row.value(named: "srno")
crop_code=title
}
let rows = try Row.fetchCursor(db, "SELECT distinct brief_advisory,advisory_date,srno FROM crop_insect_advisory_issued where crop_code='\(crop_code)'")
while let row = try rows.next() {
let title: String = row.value(named: "brief_advisory")
let da:String=row.value(named:"advisory_date")
let srno:Int = row.value(named:"srno")
let date_f=DateFormatter()
date_f.dateFormat="yyyy-MM-dd"
let d=date_f.date(from: da)
date_f.dateFormat="dd-MM-yyyy"
let dd=date_f.string(from: d!)
array.append(title)
date_array.append(dd)
srno_array.append("\(srno)")
}
}
for i in 0 ..< array.count
{
struct_array.append(myObject(date:date_array[i],advisory:array[i],
status:"N",srno:srno_array[i]))
}
for i in 0 ..< array.count
{
msg_stat.append(oldMsg(is_checked: false))
}
collection_view.delegate = self
collection_view.dataSource = self
}catch{
print(error)
}
}
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return array.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt
indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier:
"AdvisoryCollectionViewCell", for: indexPath) as!
AdvisoryCollectionViewCell
cell.msg_label.text = struct_array[indexPath.item].advisory
cell.date_label.text = struct_array[indexPath.item].date
let imagee = UIImage.init(named: "rsz_tick")
cell.check_image.image = imagee
cell.check_image.isHidden = true
if( msg_stat[indexPath.row].is_checked == false){
cell.check_image.isHidden = true
}
else if(msg_stat[indexPath.row].is_checked == true)
{
cell.check_image.isHidden = false
}
else{
}
return cell
}
func longpress(gestureRecognizer: UIGestureRecognizer)
{
let righbarButton = UIBarButtonItem(image: UIImage(named:
"rsz_delete")?.withRenderingMode(.alwaysOriginal), style:
UIBarButtonItemStyle.plain, target: self, action:
#selector(myRightTapped(sender:)))
self.navigationItem.rightBarButtonItem = righbarButton
let longpress = gestureRecognizer as! UILongPressGestureRecognizer
let state = longpress.state
let locationInview = longpress.location(in: collection_view)
var indexpath=collection_view.indexPathForItem(at: locationInview)
if(gestureRecognizer.state == UIGestureRecognizerState.began)
{
let cell = collection_view.cellForItem(at: indexpath!) as!
AdvisoryCollectionViewCell
cell.check_image.isHidden = false
msg_stat[(indexpath?.row)!].is_checked = true
ss.append((indexpath?.item)!)
print("index of deleting = \(indexpath?.item)")
msg_count_array.append((indexpath?.item)!)
msg_array.append(struct_array[(indexpath?.item)!].advisory)
selected_date_array.append(struct_array[(indexpath?.item)!].date)
selected_srno_array.append(struct_array[(indexpath?.item)!].srno)
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt
indexPath: IndexPath) {
let cell = collection_view.cellForItem(at: indexPath)
as!AdvisoryCollectionViewCell
if(!(ss.isEmpty)){
cell.check_image.isHidden = !cell.check_image.isHidden
if(cell.check_image.isHidden == true)
{
msg_stat[indexPath.row].is_checked = false
print("why removing.....")
if(!(msg_count_array.isEmpty)){
msg_count_array.remove(at: (indexPath.item))}
if(!(msg_array.isEmpty)){
msg_array.remove(at: (indexPath.item))
}
if(!(selected_srno_array.isEmpty))
{
selected_srno_array.remove(at: (indexPath.item))
}
if(!(selected_date_array.isEmpty))
{
selected_date_array.remove(at: (indexPath.item))
}
}
else{
msg_stat[indexPath.row].is_checked = true
msg_count_array.append((indexPath.item))
msg_array.append(array[(indexPath.item)])
selected_srno_array.append(struct_array[(indexPath.item)].srno)
}
}
}
func myRightTapped(sender:UIBarButtonItem!)
{
do{
for i in 0 ..< msg_count_array.count
{
struct_array.remove(at: i)
msg_stat.remove(at: i)
}
msg_count_array.removeAll()
for i in 0 ..< msg_array.count
{
var msg = msg_array[i]
var srno = selected_srno_array[i]
let
path=NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,
true).first!
let dbQueue = try DatabaseQueue(path: "\(path)/pest_messenger.sqlite")
try dbQueue.inDatabase { db in
try db.execute("DELETE FROM crop_insect_advisory_issued where srno='\
(srno)'")
}
}
msg_array.removeAll()
array.removeAll()
date_array.removeAll()
srno_array.removeAll()
// let dbQueue = try DatabaseQueue(path: "\(path)/p_messenger.sqlite")
try dbQueue?.inDatabase { db in
let rows = try Row.fetchCursor(db, "SELECT distinct brief_advisory,advisory_date,srno FROM crop_insect_advisory_issued where crop_code='\(crop_code)'")
while let row = try rows.next() {
let title: String = row.value(named: "brief_advisory")
let da:String=row.value(named:"advisory_date")
let srno:Int = row.value(named:"srno")
let date_f=DateFormatter()
date_f.dateFormat="yyyy-MM-dd"
let d=date_f.date(from: da)
date_f.dateFormat="dd-MM-yyyy"
let dd=date_f.string(from: d!)
array.append(title)
date_array.append(dd)
srno_array.append("\(srno)")
}
}
for i in 0 ..< array.count
{
struct_array.append(myObject(date:date_array[i],advisory:array[i],
status:"N",srno:srno_array[i]))
}
for i in 0 ..< array.count
{
msg_stat.append(oldMsg(is_checked: false))
}
collection_view.reloadData()
}
catch{
print(error)
}
}
}
I am making an app for smartsearch. I have implemented through making parameters into string then append the strings.Then for search i am implementing filter to search from the search. But its getting lengthy. I want it in compact using NSPredicate.
My code is here. Can anyone make it using NSPredicate and NSCompoundPredicate
import UIKit
struct Request{
var type:String!
var firstName:String!
var lastName:String!
var combineString:String {
get {
let text = "\(self.type!) \(self.firstName) \(self.lastName)"
return text
}
}
init() {
self.type = ""
self.firstName = ""
self.lastName = ""
}
init(_ type:String,_ firstName:String,_ lastName:String) {
self.type = type
self.firstName = firstName
self.lastName = lastName
}}
class ViewController: UIViewController,UITableViewDelegate, UITableViewDataSource {
#IBOutlet var searchbar:UISearchBar!
#IBOutlet var headline:UILabel!
#IBOutlet var table:UITableView!
var type:Array = [String]()
var firstName:Array = [String]()
var lastName:Array = [String]()
var tempResults = Array<[Request]>()
var requestArray = Array<Request>()
var filteredArray = Array<Request>()
var isSearching = false
type = [“4343”, “45450”, “68468”, “4686”, “56461”, “48661”]
firstName = [“Tom”, “Michel”, “Steve”, “Rahul”, “Iswar”, “Kuldeep”]
lastName = [“Moody”, “Clark”, “Smith”, “Kumar”, “Pandey”, “Yadav”]
for i in 0..<requestTypeArr.count {
let type = self.type[i]
let firstName = self.firstName[i]
let lastName = self.lastName[i]
var request = Request()
request.type = type
request.firstName = firstName
request.lastName = lastName
self.requestArray.append(request)
}
let string = String(format: "Total list No %ld", self.requestArray.count)
self.headline.text = string
self.table.delegate = self
self.table.dataSource = self
self.table.contentInset = UIEdgeInsets(top: 44, left: 0, bottom: 0, right: 0)
self.table.estimatedRowHeight = 44
self.table.rowHeight = UITableViewAutomaticDimension
self.searchbar.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.isSearching == true {
return self.filteredArray.count
}
return self.requestArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RquestDetailTableViewCell") as! RquestDetailTableViewCell
var request = self.requestArray[indexPath.row]
if self.isSearching == true {
request = self.filteredArray[indexPath.row]
}
cell.type.text = request.type
cell.firstName.text = request.firstName
cell.lastName.text = request.lastName
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}}
extension ViewController : UISearchBarDelegate {
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
self.isSearching = true
// self.table.reloadSections([0], with: .automatic)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
//Filter one
//print("Search Query:- \(searchText)")
if searchText.components(separatedBy: .whitespaces).joined(separator: "").characters.count == 0 {
if self.isSearching == true {
self.isSearching = false
self.filteredArray = Array<Request>()
self.tempResults = Array<[Request]>()
}
}else {
if self.isSearching == false {
self.isSearching = true
}
var temp = Array<Request>()
if self.tempResults.count == 0 {
temp = self.requestArray.filter({ (object) -> Bool in
//print("\nSearch Text = \(searchText.lowercased()) \nand Source Combine String = \(object.combineString.lowercased())")
let lowercaseInput = searchText.lowercased()
let lowercaseSource = object.combineString.lowercased()
let sourceComponents = lowercaseSource.components(separatedBy: .whitespaces)
let inputComponents = lowercaseInput.components(separatedBy: .whitespaces)
let sourceSet = Set(sourceComponents)
var inputSet = Set(inputComponents)
if let index = inputSet.index(of: ""){
_ = inputSet.remove(at: index)
}
var filtered = [String]()
inputSet.forEach({ (word) in
let temp = sourceSet.filter({$0.contains(word)})
//let temp2 = sourceSet.filter({$0.hasPrefix(word)})
filtered.append(contentsOf: temp)
// let temp2 = sourceSet.filter({$0.hasPrefix(word)})
//filtered.append(contentsOf: temp2)
})
let set = Set(filtered)
var isOK = set.isSubset(of: sourceSet)
if set.count == 0 {
isOK = false
}
return isOK
})
self.filteredArray = temp
}else {
if let last = self.tempResults.last {
temp = last.filter({ (object) -> Bool in
let lowercaseInput = searchText.lowercased()
let lowercaseSource = object.combineString.lowercased()
let lastInputWord = lowercaseInput.components(separatedBy: .whitespaces).last!
let sourceComponents = lowercaseSource.components(separatedBy: .whitespaces)
let inputComponents = [lastInputWord]
let sourceSet = Set(sourceComponents)
let inputSet = Set(inputComponents)
var filtered = [String]()
inputSet.forEach({ (word) in
let temp = sourceSet.filter({$0.contains(word)})
//let temp2 = sourceSet.filter({$0.hasPrefix(word)})
filtered.append(contentsOf: temp)
})
let set = Set(filtered)
var isOK = set.isSubset(of: sourceSet)
if set.count == 0 {
isOK = false
}
return isOK
})
self.filteredArray = temp
}
}
}
self.table.reloadSections([0], with: .automatic)
}
func searchBar(_ searchBar: UISearchBar, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == " " {
self.tempResults.append(self.filteredArray)
}
if range.length == 1 {
//Handle Backspace/delete
let string = searchBar.text! as NSString
let temp = string.substring(with: range) as String
let newRange = string.range(of: temp, options: .backwards)
let newText = string.replacingCharacters(in: newRange, with: "")
let words = newText.components(separatedBy: .whitespaces).count
if words > 1 {
print("word count = \(words)")
let count = self.tempResults.count
if count > words {
self.tempResults.removeLast()
}
}else {
self.tempResults = Array<[Request]>()
}
}
return true
}
}
Tried so many times to find out what causes the fatal error. But, still can't figure it out. The first table (result table) causes this error when I try to refresh the table with pull. The second table (favoriteProductTableView) works perfect, so I didn't put any code about the second one. Wondering why. Thank you for your help.
var followArray = [String]()
var resultsNameArray = [String]()
var resultsImageFiles = [PFFile?]()
var resultsDetailsArray = [String]()
var resultsDetailsImageFiles = [PFFile?]()
var resultsObjectID = [String]()
var resultsTitle = [String]()
var personPriceArray = [String]()
var personQuantityArray = [String]()
var personOrderTypeArray = [String]()
var refresher:UIRefreshControl!
override func viewDidLoad() {
super.viewDidLoad()
favoriteProductTableView.hidden = true
refresher = UIRefreshControl()
refresher.tintColor = UIColor.blackColor()
refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
self.resultsTable.addSubview(refresher)
}
override func viewDidAppear(animated: Bool) {
refreshResults()
}
func refresh(){
refreshResults()
}
func refreshResults(){
switch(segmentedControl.selectedSegmentIndex){
case 0:
followArray.removeAll(keepCapacity: false)
resultsNameArray.removeAll(keepCapacity: false)
resultsImageFiles.removeAll(keepCapacity: false)
resultsDetailsArray.removeAll(keepCapacity: false)
resultsDetailsImageFiles.removeAll(keepCapacity: false)
resultsObjectID.removeAll(keepCapacity: false)
resultsTitle.removeAll(keepCapacity: false)
personPriceArray.removeAll(keepCapacity: false)
personQuantityArray.removeAll(keepCapacity: false)
personOrderTypeArray.removeAll(keepCapacity: false)
let followQuery = PFQuery(className: "follow")
followQuery.whereKey("user", equalTo: (PFUser.currentUser()!.username)!)
followQuery.whereKey("userToFollow", notEqualTo: (PFUser.currentUser()!.username)!)
followQuery.findObjectsInBackgroundWithBlock { (objects:[PFObject]?, error: NSError?) -> Void in
if error != nil {
}
for object in objects! {
self.followArray.append(object.objectForKey("userToFollow") as! String)
}
let query = PFQuery(className: "products")
query.whereKey("userName", containedIn: self.followArray)
query.findObjectsInBackgroundWithBlock { (catchobjects:[PFObject]?, error:NSError?) -> Void in
if error != nil {
}
for catchobject in catchobjects! {
if catchobject.objectForKey("selling_price") != nil {
self.personPriceArray.append(catchobject.objectForKey("selling_price") as! String)
self.personOrderTypeArray.append("Selling")
} else {
self.personPriceArray.append(catchobject.objectForKey("buying_price") as! String)
self.personOrderTypeArray.append("Buying")
}
self.personQuantityArray.append(catchobject.objectForKey("quantity") as! String)
self.resultsNameArray.append(catchobject.objectForKey("unique_username") as! String)
self.resultsImageFiles.append(catchobject.objectForKey("profile_picture") as? PFFile)
self.resultsDetailsArray.append(catchobject.objectForKey("details") as! String)
self.resultsDetailsImageFiles.append(catchobject.objectForKey("detailsImage") as? PFFile)
self.resultsTitle.append(catchobject.objectForKey("title") as! String)
self.resultsObjectID.append(catchobject.objectId!)
}
dispatch_async(dispatch_get_main_queue()) {
self.resultsTable.reloadData()
}
self.loadEmptyLabel(self.resultsTable)
}
self.refresher.endRefreshing()
}
break
case 1:
...
break
default:
break
}
}
func loadEmptyLabel(tableView: UITableView) {
let emptyLabel = UILabel(frame: CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height))
emptyLabel.textAlignment = NSTextAlignment.Center
emptyLabel.textColor = UIColor.blackColor()
emptyLabel.text = "No matched result found."
tableView.backgroundView = emptyLabel
tableView.separatorStyle = UITableViewCellSeparatorStyle.None
var resultCount = Int()
if tableView == resultsTable {
resultCount = resultsNameArray.count
} else {
resultCount = resultsTitleArray.count
}
if resultCount == 0 {
tableView.reloadData()
emptyLabel.hidden = false
} else {
emptyLabel.hidden = true
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var numRow: Int = 0
switch(segmentedControl.selectedSegmentIndex){
case 0:
numRow = resultsNameArray.count
break
case 1:
numRow = resultsTitleArray.count
break
default:
break
}
return numRow
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView == resultsTable {
let cell:favoritedTableViewCell = resultsTable.dequeueReusableCellWithIdentifier("Cell") as! favoritedTableViewCell
cell.profileLbl.text = self.resultsNameArray[indexPath.row]
cell.messageTxt.text = self.resultsDetailsArray[indexPath.row]
cell.priceLabel.text = "\(self.personOrderTypeArray[indexPath.row]) \(self.personQuantityArray[indexPath.row]) for $\(self.personPriceArray[indexPath.row])"
cell.titleLabel.text = self.resultsTitle[indexPath.row]
if resultsImageFiles[indexPath.row] != nil {
resultsImageFiles[indexPath.row]!.getDataInBackgroundWithBlock { (imageData:NSData?, error:NSError?) -> Void in
if error == nil{
let image = UIImage(data: imageData!)
cell.imgView.image = image
}
}
} else {
cell.imgView.image = UIImage(named: "Profile Picture")
}
if resultsDetailsImageFiles[indexPath.row] != nil{
resultsDetailsImageFiles[indexPath.row]?.getDataInBackgroundWithBlock({ (imageData:NSData?, error:NSError?) -> Void in
if error == nil{
let image = UIImage(data: imageData!)
cell.detailsImg.image = image
}
})
} else {
cell.detailsImg.image = UIImage(named: "Profile Picture")
}
return cell
} else {
....
}
}
Your numberOfRowsInSection function returns one of two array lengths based on segmentedControl.selectedSegmentIndex, whereas cellForRowAtIndexPath indexes the arrays based on the tableView being displayed. This doesn't look right, especially given your referencing `` which doesn't appear to be populated anywhere - should it just be resultsTitle?.
Also, you're calling self.resultsTable.reloadData() from a background thread. This is bad - it must be called from the main thread using:
dispatch_async(dispatch_get_main_queue()) {
self.resultsTable.reloadData()
}
Nevertheless, it's not clear why you've got this inside the loop either.