In my tableview names and title are comes from server through xml parsing as soon below figure.
In this tableview list I want to use indexed search which are as shown in the image below. How can I do this?
You can have Array of dictionaries where each section will be represented by dictionary object. The key for the dictionary would be the section Title and the value would be an array of rows in section.
You can use NSPredicate to search the returned array from server and construct the data source array.
NSPredicate Programming Guide
iphone & Objective C - Filtering an array using NSPredicate
var arrData = Array<Any>()
var fromFilter:Bool = false
var arrStrData = Array<String>()
Step - 1 : Create UItableView in Your Story Board. - Datasource, Delegate
Step - 2 : import - UITableViewDelegate,UITableViewDataSource
Step - 3 : Implement methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.arr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "MainCell") as! MainCell
cell.selectionStyle = .none
var dictData: [String: AnyObject] = [String: AnyObject]()
dictData = self.arrData[indexPath.row] as! [String : AnyObject]
cell.lblName.text = dictData["name"] as? String ?? ""
cell.lblEmail.text = dictData["email"] as? String ?? ""
cell.lblAddress.text = dictData["address"] as? String ?? ""
let image = dictData[""] as? String ?? ""
cell.img?.sd_setImage(with: URL(string: image), placeholderImage: UIImage(named: "download.jpeg"), options: [.continueInBackground,.lowPriority], completed: {(image,error,cacheType,url) in
if error == nil
{
cell.img?.image = image
}
else
{
cell.img?.image = UIImage(named: "download.jpeg")
}
})
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
Related
I'm trying to hide cells from a UITableView. My codes are below.
When I open the app I see empty rows in my TableViewas you can see here
How can I hide or remove(not delete) empty cells from UITableView?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FeedTableViewCell
let row = self.items[indexPath.row]
cell.lblTitle.text = row.title
cell.isHidden = !checkCurrentUser(email: row.email)
return cell
}
I added filtered array but then I take different error like this. My new codes are below. How can I solve this problem?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FeedTableViewCell
let row = self.items[indexPath.row]
self.items = self.items.filter{checkCurrentUser(email: $0.email)}
cell.lblTitle.text = row.title
//cell.isHidden = !checkCurrentUser(email: row.email)
return cell
}
Whole codes are below
import UIKit
import Firebase
class OyuncularVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
var items = [ItemModel]()
#IBOutlet weak var tblView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tblView.tableFooterView = UITableViewHeaderFooterView()
retrieveItems()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FeedTableViewCell
let row = self.items[indexPath.row]
self.items = self.items.filter{checkCurrentUser(email: $0.email)} //bunu ekledim siliceksem bunu silicem aga
cell.lblTitle.text = row.title
//cell.isHidden = !checkCurrentUser(email: row.email)
return cell
}
/* Retriev Items */
func retrieveItems() {
DataService.dataService.ITEM_REF.observe(.value, with: { (snapshot: DataSnapshot?) in
if let snapshots = snapshot?.children.allObjects as? [DataSnapshot] {
self.items.removeAll()
print(snapshots.count)
for snap in snapshots {
if let postDic = snap.value as? Dictionary<String, AnyObject> {
let itemModel = ItemModel(key: snap.key, dictionary: postDic)
print(itemModel)
self.items.insert(itemModel, at: 0)
}
}
self.tblView.reloadData()
}
})
}
func checkCurrentUser(email: String) -> Bool {
let currentUser = Auth.auth().currentUser
return email == currentUser?.email
}
}
}
If you want to display only the emails of the current user what don't you filter the items in the database (applying a predicate) which is the most efficient way.
Or filter the items in the for snap in snapshots loop.
However if you want to keep the entire data set declare a second array
var items = [ItemModel]()
var filteredItems = [ItemModel]()
and replace
for snap in snapshots {
if let postDic = snap.value as? Dictionary<String, AnyObject> {
let itemModel = ItemModel(key: snap.key, dictionary: postDic)
print(itemModel)
self.items.insert(itemModel, at: 0)
}
}
with the following it performs the check in the loop
let currentUser = Auth.auth().currentUser
self.filteredItems.removeAll()
for snap in snapshots {
if let postDic = snap.value as? Dictionary<String, AnyObject> {
let itemModel = ItemModel(key: snap.key, dictionary: postDic)
print(itemModel)
self.items.insert(itemModel, at: 0)
if itemModel.email == currentUser?.email {
self.filteredItems.insert(itemModel, at: 0)
}
}
}
And replace also the two data source methods with
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredItems.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FeedTableViewCell
let row = self.filteredItems[indexPath.row]
cell.lblTitle.text = row.title
return cell
}
And delete the method checkCurrentUser
I am trying to pass tableview cell data on editing did end to a button. I have been using tags but I keep getting an error nil found. I think this is do to the amount of rows I have (over 500). Anyone know the best way to do this?
The Code below is what I use (tags). It only crashes (returns nil) when I have multiple tableviewcell rows and have to scroll off the page.
func numberOfSections(in tableView: UITableView) -> Int { return 1 }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return inventoryArray.count }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let code : String = (inventoryArray[indexPath.row] as AnyObject).value(forKey: "code") as! String
let name : String = (inventoryArray[indexPath.row] as AnyObject).value(forKey: "name") as! String
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! InventoryCell
cell.unitField.tag = indexPath.row
cell.unitField.addTarget(self, action: #selector(Inventory.submit(_:)), for: UIControl.Event.editingDidEnd)
return cell as InventoryCell
}
...
#IBAction func submit(_ sender: UIButton) {
let tag = sender.tag
let cell = tableView.cellForRow(at: IndexPath.init(row: tag, section: 0)) as! InventoryCell
var unitCount = Int(cell.unitField.text!)!
cell.count.text = String (unitCount)
}
I am new to the Swift language and just a beginner, I have created tableview. I want to show the data whereas when I'm running the code it shows me empty cells. I have checked the delegates and connections .
func numberOfSections(in dashboardtable: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 114
}
func tableView(_ dashboardtable: UITableView, numberOfRowsInSection section: Int) -> Int {
return toddler.count
}
func tableView(_ dashboardtable: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = dashboardtable.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! DashTableViewCell
cell.cname.text = toddler[indexPath.row]["ChildName"] as? String
cell.cage.text = toddler[indexPath.row]["Age"] as? String
cell.childc.text = toddler[indexPath.row]["Class"] as? String
if let base64 = toddler[indexPath.row]["Photo"] as? String,let data = Data.init(base64Encoded: base64), let image = UIImage.init(data: data){
cell.childimage.image = image
} else {
cell.childimage.image = UIImage.init(named: "")
}
cell.backgroundColor = UIColor.white
cell.layer.borderColor = UIColor.black.cgColor
cell.layer.borderWidth = 1
cell.layer.cornerRadius = 8
cell.clipsToBounds = true
//to display the whole details
print(indexPath.row)
return cell
}
If you want hide lines in blank tableView
use this:
tableView.separatorStyle = .none
be sure set delegate and datasource and call reloadData
I have two custom reusable table view cells in my table view. The first cell, I would like it to be present at all times. The second cell and beyond, are returning a count that is being passed from mysql database.
// return the amount of cell numbers
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
// cell config
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! InfoCell
//set the data here
return cell
} else {
let Postcell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostCell
let post = posts[indexPath.row]
let image = images[indexPath.row]
let username = post["user_username"] as? String
let text = post["post_text"] as? String
// assigning shortcuts to ui obj
Postcell.usernameLbl.text = username
Postcell.textLbl.text = text
Postcell.pictureImg.image = image
return Postcell
}
} // end of function
My first cell is there and so are the post.count, but for some reason the posts.count is missing one post and I believe this is because of the first cell. Can anybody help me with this? thanks in advance.
You need to adjust the value returned from numberOfRowsInSection to account for the extra row. And you would need to adjust the index used to access values from your posts array to deal with the extra row.
But a much better solution is to use two sections. The first section should be your extra row and the second section would be your posts.
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 = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! InfoCell
//set the data here
return cell
} else {
let Postcell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostCell
let post = posts[indexPath.row]
let image = images[indexPath.row]
let username = post["user_username"] as? String
let text = post["post_text"] as? String
// assigning shortcuts to ui obj
Postcell.usernameLbl.text = username
Postcell.textLbl.text = text
Postcell.pictureImg.image = image
return Postcell
}
}
below code supposed to call usernames from an array and user able to tap on the desired username. call to that array is a success and I can see the usernames but won't able to tap into it. and it don't even print "didSelectRowAt". appreciate your help. thanks.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath) as! MentionUserCell
cell.username!.text = autoComplete[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return autoComplete.count
}
func numberOfSections(in tableView: UITableView) -> Int
{
return 1
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let selectedCell: MentionUserCell = tableView.cellForRow(at: indexPath)! as! MentionUserCell
let selectedWord: String = selectedCell.username!.text! + " "
print("didSelectRowAt")
var string: NSString = NSString(string: self.commentTextView.text!)
string = string.replacingCharacters(in: otoCadang.sharedInstance.foundRange, with: selectedWord) as NSString
// change text field value
commentTextView.text = string as? String
// change cursor position
let positionOriginal = commentTextView.beginningOfDocument
if let cursorLocation: UITextPosition = self.commentTextView.position(from: positionOriginal, offset: otoCadang.sharedInstance.foundRange.location + selectedWord.characters.count)
{
self.commentTextView.selectedTextRange = self.commentTextView.textRange(from: cursorLocation, to: cursorLocation)
}
// remove suggestion
self.autoComplete.removeAll()
self.tableView.reloadData()
tableView.isHidden = true
}
Check List
tableview delegate is set properly
tableview selection mode == No Selection, then change to single selection
function name is correct func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
are you using any tap gesture on this view? remove it.
If you are editing UITextView will can't call to `didselectRowAt. Try to get the Your MentionUserCell, IndexPath in UITextView's methods and handle there. Example:
func textViewDidChange(_ textView: UITextView) {
var parentView = textView as UIView
while !(parentView is UITableViewCell) {
parentView = parentView.superview!
}
if let cell: MentionUserCell = parentView as? MentionUserCell {
if let indexPath = self.tableView.indexPath(for: cell) {
let yourIndexPath = indexPath
}
}
//your code
}
Hope it will help you.
When are using two or more cells the didSelectRow method is not working Well. You can use a button in cell.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifierName", for: indexPath) as! MentionUserCell
cell.username!.text = autoComplete[indexPath.row]
let button = cell.viewWithTag(101) as! UIButton
button.cellclick.addTarget(self, action: #selector(functionName(sender:)), for: .touchDown)
return cell
}
Now you get the indexPath:-
func functionName(sender:UIButton) {
let buttonPosition:CGPoint = sender.convert(CGPoint.zero, to:self.tableview)
let indexPath = self.tableview.indexPathForRow(at: buttonPosition)
print(indexPath.row)
}