Custom UISearchBar using TextField - swift

I need to make custom UISearchBar using UITextField.
I try to make it myself, but nothing works. Please, write a code for UITextField, which will work like UISearchBar
It's code where I use UISearchBar, but I need to change to UITextField
class FoodViewController: UIViewController {
override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent }
let tableView = UITableView()
var foods = [FoodModel]()
var searchedFoods = [FoodModel]()
var searching = false
override func viewDidLoad() {
super.viewDidLoad()
fetchFoods()
self.modalPresentationCapturesStatusBarAppearance = true
self.view.backgroundColor = UIColor.white
let controller = UIViewController()
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
self.view.addSubview(self.tableView)
tableView.delegate = self
tableView.dataSource = self
let searchBar = UISearchBar(frame: CGRect(x: 0, y: 5, width: 350, height: 40))
searchBar.searchBarStyle = .minimal
searchBar.barStyle = .black
searchBar.delegate = self
self.view.addSubview(searchBar)
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.updateLayout(with: self.view.frame.size)
}
func updateLayout(with size: CGSize) {
self.tableView.frame = CGRect.init(x: 0, y: 45, width: size.width, height: 400)
}
func fetchFoods() {
Database.database().reference().child("food").observe(.childAdded) { (snapshot) in
if let dict = snapshot.value as? [String: AnyObject] {
let newTitle = dict["title"] as! String
let exCell = FoodModel(title: newTitle)
self.foods.append(exCell)
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
}
}
extension FoodViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
if searching {
let food = searchedFoods[indexPath.item]
cell.textLabel?.text = food.title
} else {
let food = foods[indexPath.item]
cell.textLabel?.text = food.title
}
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searching {
return searchedFoods.count
} else {
return foods.count
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var titleOfFood = String()
if searching == true {
titleOfFood = searchedFoods[indexPath.row].title
print(titleOfFood)
} else {
titleOfFood = foods[indexPath.row].title
print(titleOfFood)
}
let alertController = UIAlertController(title: "Hello", message: "Message", preferredStyle: .alert)
let cancel = UIAlertAction(title: "Cancel", style: .default)
let save = UIAlertAction(title: "Save", style: .cancel) { (action) in
self.dismiss(animated: true, completion: nil)
}
alertController.addTextField { (textField) in
textField.keyboardType = .numberPad
textField.borderStyle = .roundedRect
textField.layer.borderColor = UIColor.clear.cgColor
textField.addConstraint(textField.heightAnchor.constraint(equalToConstant: 50))
textField.font = UIFont(name: "Roboto-Medium", size: 30)
// textField.cornerRadius = 8
}
alertController.addAction(save)
alertController.addAction(cancel)
self.present(alertController, animated: true)
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
}
}
extension FoodViewController: UITableViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == self.tableView {
SPStorkController.scrollViewDidScroll(scrollView)
}
}
}
extension FoodViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchedFoods = foods.filter({ $0.title.lowercased().prefix(searchText.count) == searchText.lowercased() })
searching = true
tableView.isHidden = false
tableView.reloadData()
let transitionDelegate = SPStorkTransitioningDelegate()
transitionDelegate.customHeight = 620
transitionDelegate.showIndicator = false
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searching = false
searchBar.text = ""
tableView.reloadData()
}
}

Basically (if i'm understanding you correctly) after you add your UITextField to the view, all you need to have is some method to trigger whenever the value of the UITextField changes.
Something like this:
textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
And then:
func textFieldDidChange(_ textField: UITextField) {
let searchText = textField.text!
searchedFoods = foods.filter({ $0.title.lowercased().prefix(searchText.count) == searchText.lowercased() })
searching = true
tableView.isHidden = false
tableView.reloadData()
let transitionDelegate = SPStorkTransitioningDelegate()
transitionDelegate.customHeight = 620
transitionDelegate.showIndicator = false
}

Related

UITableView isn't appearing in view?

My tableview isn't loading once I press build, can anyone see what's wrong with the code as to why it's not showing up? In the console, it's printing the data from Firestore, but I can't see anything on the simulator but a white screen.
struct Posts {
var caption:String
}
class CoursesVC: UIViewController, UITableViewDelegate {
let tableView = UITableView()
var posts = [Posts]()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
self.tableView.dataSource = self
self.tableView.delegate = self
setupViews()
loadPosts()
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
func loadPosts() {
let dbUsers = Firestore.firestore().collection("Payouts")
dbUsers.addSnapshotListener { (querySnapshot, error) in
if let error = error {
print("\(error.localizedDescription)")
} else {
for document in (querySnapshot?.documents)! {
if let Caption = document.data()["amount"] as? String {
print(Caption)
var post = Posts(caption: "")
post.caption = Caption
self.posts.append(post)
}
}
DispatchQueue.main.async
{
self.tableView.reloadData()
}
print(self.posts)
}
}
}
private func setupViews() {
let stackView: UIStackView = {
let sv = UIStackView()
sv.translatesAutoresizingMaskIntoConstraints = false
sv.spacing = 28
sv.axis = .vertical
sv.distribution = .fill
sv.alignment = .fill
return sv
}()
view.addSubview(stackView)
view.addSubview(tableView)
}
}
extension CoursesVC: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let post = posts[indexPath.row]
cell.textLabel?.text = post.caption
return cell
}
}
You forgot to assign frame to your tableView. As you are adding your tableView programatically so, you have to set frame for your tableView. Write below code in your setupViews() method.
E.g. tableView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 450.0)
Change tableView frame as per your requirement.

Terminating app due to 'NSInternalInconsistencyException' error

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to insert section 50 but there are only 1 sections after the update'
Hey everyone I have been stuck on this error all day. It crashes the app after the set Batch Load Limit of 50 cells. I believe I am populating the tableView incorrectly. Here is a snippet of the code directly working with sections in the table.
import UIKit
import Firebase
import Foundation
class NotificationViewController: GradientViewController {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var GVX3: UIView!
var isVisible = false
var notifications: [GActionNotification] = []
//Pull to Refresh
lazy var refresher: UIRefreshControl = {
let refreshControl = UIRefreshControl()
refreshControl.tintColor = primaryColor
refreshControl.addTarget(self, action: #selector(requestData), for: .valueChanged)
return refreshControl
}()
//Pull to Refresh
#objc func requestData() {
print("requesting data")
let deadline = DispatchTime.now() + .milliseconds(856)
DispatchQueue.main.asyncAfter(deadline: deadline) {
self.refresher.endRefreshing()
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
isVisible = true
NotificationService.shared.setSeen(notifications: notifications)
setNotificationsBadge()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
isVisible = false
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
override func viewDidLoad() {
super.viewDidLoad()
configureTableView()
tableView.clipsToBounds = true
tableView.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]
if #available(iOS 13.0, *) {
tableView.backgroundColor = UIColor.systemBackground
} else {
// Fallback on earlier versions
tableView.backgroundColor = UIColor.white
}
tableView.allowsSelection = false
if #available(iOS 10.0, *) {
tableView.refreshControl = refresher
}else{
tableView.addSubview(refresher)
}
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
navigationController?.navigationBar.isTranslucent = true
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
observeNotifications()
}
var loader: BatchCollectionLoader?
func requestMoreNotifications() {
loader?.getNextSnapshot(completion: { [weak self] (snapshot) in
NotificationService.shared.process(snapshot: snapshot, completion: { (notifications) in
guard notifications.count > 0 else { return }
guard let strongSelf = self else { return }
var indexSet = IndexSet.init(integer: strongSelf.notifications.count)
if notifications.count > 1 {
let range = (strongSelf.notifications.count...(strongSelf.notifications.count + notifications.count - 1))
indexSet = IndexSet.init(integersIn: range)
}
let shouldUpdate = strongSelf.notifications.count == 0
strongSelf.notifications.append(contentsOf: notifications)
if shouldUpdate {
strongSelf.tableView.reloadData()
} else {
strongSelf.tableView.beginUpdates()
strongSelf.tableView.insertSections(indexSet, with: .bottom)
strongSelf.tableView.endUpdates()
}
})
})
}
func observeNotifications() {
guard let current = GUser.current else { return }
loader = BatchCollectionLoader.init(collection: NotificationService.shared.notificationReference.document(current.uid).collection("notifications"))
loader?.getNextSnapshot(completion: { [weak self] (snapshot) in
NotificationService.shared.process(snapshot: snapshot, completion: { (notifications) in
guard let strongSelf = self else { return }
strongSelf.notifications = notifications.sorted(by: {$0.time > $1.time})
DispatchQueue.main.async {
strongSelf.tableView.reloadData()
}
if strongSelf.isVisible && isInForeground {
NotificationService.shared.setSeen(notifications: notifications)
}
strongSelf.setNotificationsBadge()
})
})
}
func setNotificationsBadge() {
UIApplication.shared.applicationIconBadgeNumber = notifications.filter({!$0.isSeen}).count
if notifications.filter({!$0.isSeen}).count > 0 {
self.tabBarController?.tabBar.items?[2].badgeValue = "\(notifications.filter({!$0.isSeen}).count)"
} else {
self.tabBarController?.tabBar.items?[2].badgeValue = nil
}
}
func configureTableView() {
tableView.register(UINib.init(nibName: LaunchNotificationCell.identifier, bundle: nil), forCellReuseIdentifier: LaunchNotificationCell.identifier)
tableView.register(UINib.init(nibName: GNotificationCell.identifier, bundle: nil), forCellReuseIdentifier: GNotificationCell.identifier)
tableView.rowHeight = 70
tableView.delegate = self
tableView.dataSource = self
}
}
extension NotificationViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return notifications.count > 0 ? notifications.count : 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if notifications.count == 0 {
if let cell = tableView.dequeueReusableCell(withIdentifier: LaunchNotificationCell.identifier, for: indexPath) as? LaunchNotificationCell {
return cell
}
}
if let cell = tableView.dequeueReusableCell(withIdentifier: GNotificationCell.identifier, for: indexPath) as? GNotificationCell {
cell.configure(notification: notifications[indexPath.row])
cell.authorProfileTapped = { [weak self] uid in
guard let strongSelf = self else { return }
strongSelf.openProfile(id: uid)
}
cell.postTapped = { [weak self] postUid in
guard let strongSelf = self else { return }
let notification = strongSelf.notifications[indexPath.row]
if notification.action == .friendRequest {
strongSelf.openProfile(id: notification.user)
} else {
let alert = UIAlertController(title: nil, message: "Loading post...", preferredStyle: .alert)
let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.style = UIActivityIndicatorView.Style.gray
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
strongSelf.present(alert, animated: true, completion: nil)
PostService.shared.getPost(id: postUid, location: nil, completion: {post, err in
alert.dismiss(animated: true, completion: nil)
if let post = post {
guard let commentsVC = strongSelf.storyboard?.instantiateViewController(withIdentifier: "CommentsViewController") as? CommentsViewController else {return}
commentsVC.post = post
strongSelf.navigationController?.pushViewController(commentsVC, animated: true)
}
})
}
}
return cell
}
return UITableViewCell()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if notifications.count == 0 {
return view.frame.height
}
return 70
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if indexPath.section == tableView.numberOfSections - 1 &&
indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
requestMoreNotifications()
}
}
}
extension NotificationViewController: GPostHelperProtocol {}
extension NotificationViewController: ProfileHelperProtocol {}
Probably it was intended the following, but it would be better to describe what is supposed to be shown when there are notifications and not.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if notifications.count != 0 { // << here !!
if let cell = tableView.dequeueReusableCell(withIdentifier: LaunchNotificationCell.identifier, for: indexPath) as? LaunchNotificationCell {
return cell
}
}
return UITableViewCell() // << default ??
You are trying to insert 50 sections instead of 50 rows but your numberOfSections method claims there is only one section. That's why an exception is being thrown. Make sure you are inserting rows, not sections.

UISearchController - search for users - tableview is blank? Firebase/Swift

i made a SearchViewController that searches for users, but then I started adding it so the tableview doesn't display until the user has typed at least two characters. For some odd reason, nothing shows up in the tableview when I type in two words.
Does anyone know why?
class FollowUsersTableViewController: UIViewController, UISearchBarDelegate {
#IBOutlet var tableView: UITableView!
private var viewIsHiddenObserver: NSKeyValueObservation?
let searchController = UISearchController(searchResultsController:
nil)
var usersArray = [UserModel]()
var filteredUsers = [UserModel]()
var loggedInUser: User?
//
var databaseRef = Database.database().reference()
//usikker på den koden over
override func viewDidLoad() {
super.viewDidLoad()
//large title
self.title = "Discover"
if #available(iOS 11.0, *) {
self.navigationController?.navigationBar.prefersLargeTitles =
true
} else {
// Fallback on earlier versions
}
self.tableView?.delegate = self
self.tableView?.dataSource = self
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
self.searchController.delegate = self;
definesPresentationContext = true
tableView.tableHeaderView = searchController.searchBar
//self.loadProfileData()
//self.searchBar(searchController.searchBar, textDidChange: searchController.searchBar.text)
}
func searchUsers(text: String) {
if text.count >= 2 {
self.usersArray = [] //clear the array each time
let endingText = text + "\u{f8ff}"
databaseRef.child("profile").queryOrdered(byChild: "username")
.queryStarting(atValue: text)
.queryEnding(atValue: endingText)
.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let childSnap = child as! DataSnapshot
let userObj = Mapper<UserModel>().map(JSONObject:
childSnap.value!)
userObj?.uid = childSnap.key
if childSnap.key != self.loggedInUser?.uid {
//ignore this user
self.usersArray.append(userObj!)
}
}
self.tableView.reloadData()
})
}
} //may need an else statement here to clear the array when there is
no text
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let dest = segue.destination as! UserProfileViewController
let obj = sender as! UserModel
let dict = ["uid": obj.uid!, "username": obj.username!,
"photoURL": obj.photoURL, "bio": obj.bio]
dest.selectedUser = dict as [String : Any]
}
}
// MARK: - tableview methods
extension FollowUsersTableViewController: UITableViewDataSource,
UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection
section: Int) -> Int {
return searchController.searchBar.text!.count >= 2 ?
filteredUsers.count : 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell",
for: indexPath) as! FollowTableViewCell
let user = filteredUsers[indexPath.row]
cell.title?.text = user.username
if let url = URL(string: user.photoURL ?? "") {
cell.userImage?.sd_setImage(with: url, placeholderImage: #imageLiteral(resourceName: "user_male"), options: .progressiveDownload, completed: nil)
cell.userImage.sd_setIndicatorStyle(.gray)
cell.userImage.sd_showActivityIndicatorView()
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath:
IndexPath) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "user", sender: self.filteredUsers[indexPath.row])
}
}
// MARK: - search methods
extension FollowUsersTableViewController:UISearchResultsUpdating,
UISearchControllerDelegate {
func updateSearchResults(for searchController: UISearchController) {
searchController.searchResultsController?.view.isHidden = false
filterContent(searchText: self.searchController.searchBar.text!)
searchUsers(text: self.searchController.searchBar.text!)
self.tableView.reloadData()
}
func filterContent(searchText:String){
if searchText.count >= 2{
self.filteredUsers = self.usersArray.filter{ user in
return(user.username!.lowercased().contains(searchText.lowercased()))
}
}
}
}
Also worth to mention:
I didn't create the searchcontroller using storyboards, I did it programmatically.
I got the error saying
firebase [MC] Invalidating cache
before I added .indexOn in my Firebase rules, now it doesn't show up anymore - weird.

Swift: UIPanGesture on tableview cell not working

Heyy,
Hello I want to implement a gesture in a tableview cell but it does not work here is my code:
var panGesture: UIPanGestureRecognizer?
override func awakeFromNib() {
super.awakeFromNib()
panGesture = UIPanGestureRecognizer(target: self, action: #selector(detectPan(recognizer:)))
panGesture?.delaysTouchesBegan = false
panGesture?.delaysTouchesEnded = false
separatorView.addGestureRecognizer(panGesture!)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
#objc func detectPan(recognizer: UIPanGestureRecognizer) {
let translation = recognizer.translation(in: self.vc?.view)
switch recognizer.state {
case .began:
self.startingConstant = self.constantCenter.constant
case .changed:
self.constantCenter.constant = self.startingConstant + translation.x
case .ended:
if translation.x > 0 {
constantCenter.isActive = false
constanteGauche.isActive = false
constanteDroite.isActive = true
}else{
constantCenter.isActive = false
constanteGauche.isActive = true
constanteDroite.isActive = false
print("ok")
}
UIView.animate(withDuration: 0.2) {
self.vc?.view.layoutIfNeeded()
}
constantCenter.constant = separatorView.center.x - (self.vc?.view.center.x)!
constantCenter.isActive = true
constanteGauche.isActive = true
constanteDroite.isActive = true
default:
break
}
}
Do I have to fix something in my function tableview:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//On lien le TableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? FeedCell
cell?.selectionStyle = .none
cell?.vc = self
cell?.delegate = self
cell?.view(post: FeedPostController.posts[indexPath.row], user: FeedPostController.users[indexPath.row]); //On passe l'objet a l'index i a la fonction view du TableViewCell pour l'affichage
return cell!;
}
I tried a lot of possibilities but nothing works, the function of the gesture I need it in the uitableviewcell because I use constraints that are in the cell
UPDATE SOLUTION
override func awakeFromNib() {
super.awakeFromNib()
separatorView.isUserInteractionEnabled = true //THIS LINE ITS VERY IMPORTANT !!!!!!!!
panGesture = UIPanGestureRecognizer(target: self, action: #selector(detectPan(recognizer:)))
panGesture?.delaysTouchesBegan = false
panGesture?.delaysTouchesEnded = false
separatorView.addGestureRecognizer(panGesture!)
}
Here is the code example. 100% works. Hope, it'll help.
import UIKit
private let cellID = "cellID"
class ViewController: UIViewController {
// Setup Table View
private lazy var tableView: UITableView = {
let rect: CGRect = view.bounds
let tableView = UITableView(frame: rect, style: .grouped)
tableView.separatorStyle = .singleLine
tableView.backgroundColor = .white
tableView.dataSource = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellID)
// If you need to PAN the tableView, uncomment this line
// tableView.addGestureRecognizer(self.panGesture)
return tableView
}()
// Setup panGesture
private lazy var panGesture: UIPanGestureRecognizer = {
let pan = UIPanGestureRecognizer(target: self, action: #selector(didPan(sender:)))
// Set delegate
pan.delegate = self
return pan
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(tableView)
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath)
cell.backgroundColor = .red
// Add panGesture to first cell for example
if indexPath.section == 0, indexPath.row == 0 {
cell.addGestureRecognizer(self.panGesture)
cell.backgroundColor = .lightGray
cell.textLabel?.text = "You can drag a table for this cell"
}
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
}
extension ViewController: UIGestureRecognizerDelegate {
#objc fileprivate func didPan(sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: view)
switch sender.state {
case .began:
print("Began")
case .changed:
print("Canged \(translation.y)")
// This is just example to show you how that works. Dragging tableView.
tableView.frame.origin.y = translation.y
case .ended:
print("Ended")
default:
break
}
}
}
Link for short video how it works on device: https://www.dropbox.com/s/1lorvamynbwvyv7/TJCQ1216.MP4?dl=0
If you have any questions, just ask )

How do I filter data and return only the relevant users?

I have a tableView in my application that returns all of the users inside of my users node in my Firebase Database. I have a picture of my database tree below, along with the relevant code. How do I get the tableView to return only the users with the numberId set to 1. As I only have 2 users in my database, I want it to return that one user and not the user with the numberId set to 2. At the moment, it returns all of the users. I would appreciate any help. Thank you.
class User: NSObject {
var name: String?
var email: String?
var numberId: String?
var password: String?
var profileImageUrl: String?
}
class UsersController: UITableViewController {
let cellId = "cellId"
var users = [User]()
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(handleCancel))
tableView.register(UserCell.self, forCellReuseIdentifier: "cellId")
tableView.tableFooterView = UIView()
fetchUser()
}
func fetchUser() {
FIRDatabase.database().reference().child("users").observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = User()
user.setValuesForKeys(dictionary)
self.users.append(user)
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
}, withCancel: nil)
}
func handleCancel() {
dismiss(animated: true, completion: nil)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return users.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! UserCell
let user = users[indexPath.row]
cell.textLabel?.text = user.name
cell .detailTextLabel?.text = user.email
if let profileImageUrl = user.profileImageUrl {
cell.profileImageView.loadImageUsingCachWithUrlString(urlString: profileImageUrl)
}
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 56
}
}
class UserCell: UITableViewCell {
override func layoutSubviews() {
super.layoutSubviews()
textLabel?.frame = CGRect(x: 58, y: (textLabel?.frame.origin.y)! - 2, width: (textLabel?.frame.width)!, height: (textLabel?.frame.height)!)
detailTextLabel?.frame = CGRect(x: 58, y: (detailTextLabel?.frame.origin.y)! + 2, width: (detailTextLabel?.frame.width)!, height: (detailTextLabel?.frame.height)!)
}
let profileImageView: UIImageView = {
let image = UIImageView()
image.contentMode = .scaleAspectFill
image.layer.masksToBounds = true
image.layer.cornerRadius = 20
image.translatesAutoresizingMaskIntoConstraints = false
return image
}()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)
setupProfileImageView()
}
func setupProfileImageView() {
addSubview(profileImageView)
profileImageView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 8).isActive = true
profileImageView.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
profileImageView.widthAnchor.constraint(equalToConstant: 40).isActive = true
profileImageView.heightAnchor.constraint(equalToConstant: 40).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
You need to use queryOrderedByChild and queryEqualToValue.
func fetchUser() {
FIRDatabase.database().reference().child("users").queryOrderedByChild("numberId").queryEqualToValue(1).observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = User()
user.setValuesForKeys(dictionary)
self.users.append(user)
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
}, withCancel: nil)
}
You can have idea from here, I don't know about swift how to write code in but.. you can have idea and hope you can write code like wise.