reloading table view when search bar is empty - swift

I am new in swift.I have implement the search operation for json show in table view about description field .
func updateSearchResults(for searchController: UISearchController) {
// If we haven't typed anything into the search bar then do not filter the results
if searchController.searchBar.text! == "" {
filteredsneakernews = [classObject.descriptionn]
self.results = self.placeHolderArray
self.DiscoveryNewsTableView.reloadData()
} else {
// Filter the results
//filteredsneakernews = [classObject.descriptionn].filter { $0.description.lowercased().contains(searchController.searchBar.text!.lowercased()) }
results = results.filter {
$0.description.lowercased().contains(searchController.searchBar.text!.lowercased()) }
// self.results = self.placeHolderArray
self.DiscoveryNewsTableView.reloadData()
}
// self.DiscoveryNewsTableView.reloadData()
}
Here is code for table view
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "discoveryNewscell") as! DiscoveryNewsTableViewCell
classObject.getDataForTableView(results: results, index: indexPath.row)
//let image_url = filteredsneakernews[indexPath.row].image
// cell.sneakerImageView.image=filteredsneakernews[indexPath.row].image
self.placeHolderArray = self.results
cell.newsTitle.text = classObject.descriptionn
let imageURLPathString = newsurl + classObject.image
let url1 = URL(string: imageURLPathString)
print("xyz", url1)
let data = try? Data(contentsOf: url1!)
if let imageData = data {
let image = UIImage(data: imageData)
cell.sneakerImageView.image = image
}
return cell
}
here is the class that i have made for getting data from json
class getData: NSObject {
var descriptionn : String = ""
var image : String = ""
// static let shared = getData()
func getDataForTableView(results: [[String:String]], index : Int){
var productArray = [String:String]()
productArray = results[index]
descriptionn = productArray["description"]!
image = productArray["images"]!
}
}
The search bar searching the result. when i finish the search when search bar is empty i want table view should reload the data .it should show the all record in table view when search bar is empty .but it is not reloading table view when search bar is empty .you can download the code from this link. https://drive.google.com/file/d/1G3QUYLgLDwIjNKb-HB-zO98l14HrcRVe/view?usp=sharing

#ajadka I have seen your code and there is small mistake ...just replace this line n it'll work correctly ..
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "discoveryNewscell") as! DiscoveryNewsTableViewCell
// self.placeHolderArray = self.results comment this line here
...... }
and put that line here
func single_news(userid: Int) {
.......
self.results = jsonValue.object(forKey: "data") as! [[String:String]]
self.placeHolderArray = self.results //put here that line
..........
}

Related

Swift - Search in UITableView [duplicate]

This question already has answers here:
Searchbar filtering issue
(3 answers)
Closed 3 years ago.
I'm trying to be able to search my Firebase data using a UISearchBar in my app & I am stuck. I am successfully receiving data from Firebase in a table view. I have a memories-writing app that the user can create memories (that are shown in a tableview from the firebase). memories has a title, description, a pic and a date and I want it to be able to search memories by the title.
I have a code here that doesn't work for some reason... il'l be glad if you could help me find out what's wrong in the code or find a replacement for this code :)
MemoryTitles class:
class MemoryTitles {
var title : String
init(withTitle: String) {
self.title = withTitle
}
}
MemoryViewController:
class MemoryViewController: UIViewController,UITableViewDelegate,UITableViewDataSource
// the filtered memories array for the search bar
var memoriesTitlesArr: [String] = []
var filteredDataa: [String] = []
// connections from storyboard to the code
#IBOutlet weak var tbl: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
// an array of memories
var memories : [Memory] = []
var ref = Database.database().reference()
let sref = Storage.storage().reference()
var lastIndex : Int = 0
var strMode : String = ""
// TableView functions
// Return the number of rows in section
// section - an index number identifying a section in tableView.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searching {
return filteredDataa.count
} else {
return memories.count
}
// return memories.count
}
// Return Cell for row function : an object inheriting from UITableViewCell
// indexPath - an index path locating a row in tableView.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "iden")
if searching {
cell?.textLabel?.text = filteredDataa[indexPath.row]
} else {
var cell : UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: "iden", for: indexPath)
if cell == nil
{
cell = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "iden")
}
let temp = memories[indexPath.row]
cell?.textLabel?.text = temp.title
cell?.imageView?.image = temp.image
return cell!
}
return cell!
}
// Can edit row : asks the data source to verify that the given row is editable.
// indexPath - an index path locating a row in tableView.
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true // true if the row indicated by indexPath is editable; otherwise, false.
}
// Asks the data source to commit the insertion or deletion of a specified row.
// indexPath - an index path locating a row in tableView.
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete // editingStyle - the cell editing style corresponding to a insertion or deletion requested for the row specified by indexPath.
{
let temp = self.memories[indexPath.row]
self.memories.remove(at: indexPath.row)
self.ref.child("MEmories/\(temp.key)").removeValue()
tableView.deleteRows(at: [indexPath as IndexPath], with: .fade)
}
}
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference()
let rightButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(MemoryViewController.barButtonItemClicked(_:)))
self.navigationItem.setRightBarButton(rightButton, animated: true)
// Do any additional setup after loading the view.
self.loadMemories()
self.tbl.delegate = self
self.tbl.dataSource = self
}
// click on bar-Button function
#objc func barButtonItemClicked(_ sender:UIBarButtonItem)
{
print("+ clicked") // writes "+ clicked"
let addMemoryViewController = self.storyboard?.instantiateViewController(withIdentifier: "AddMemoryViewController") as! AddMemoryViewController
self.strMode = "newMemory"
self.navigationController?.pushViewController(addMemoryViewController, animated: true)
}
// Reading from NSUserDefault (A class that provides simple storage of different data types solution.)
func readFromNSUserDefault()-> Memory?
{
let d : UserDefaults = UserDefaults.standard
let strTitle = d.object(forKey: "title") as? String
let strBody = d.object(forKey: "body") as? String
let strImageRef = d.object(forKey: "imageRef") as? String
let uid = d.object(forKey: "uid") as? String
let imageData = d.object(forKey: "imageData") as? Data
let key = d.object(forKey: "key") as? String
let date = d.object(forKey: "date") as? NSNumber
let m = Memory(title: strTitle!, body: strBody!, key: key!, uid: uid!, imageRef: strImageRef!, date: date!) // A variable from type memory
m.image = UIImage(data: imageData!)
m.key = key!
return m
}
override func viewDidAppear(_ animated: Bool) {
let d = UserDefaults.standard
let newMemory = readFromNSUserDefault()
let userAdded = d.bool(forKey: "userAdded") //key new user = true
let userEdited = d.bool(forKey: "userEdited")//key user edited = true
if self.strMode == "newMemory" && userAdded
{
self.memories.append(newMemory!)
self.tbl.reloadData()
}
else if self.strMode == "edit" && userEdited
{
memories[lastIndex] = newMemory!
self.tbl.reloadData()
}
d.set(false, forKey: "userAdded")
d.set(false, forKey: "userEdited")
d.synchronize()
self.strMode = " "
}
// loading the memories from the Database
func loadMemories()
{
let UID = Auth.auth().currentUser!.uid
self.ref.child("MEmories").queryOrdered(byChild: "uid").queryEqual(toValue: UID).observeSingleEvent(of: .value, with: {
snapShot in
if let dict = snapShot.value as? NSDictionary
{
for d in (dict as? Dictionary<String,AnyObject>)!
{
let title = d.value["title"] as?String
let body = d.value["body"] as? String
let uid = d.value["uid"] as? String
let imageRef = d.value["imageRef"] as? String
let date = d.value["date"] as? NSNumber
let m = Memory(title: title!, body: body!, uid: uid!,imageRef:imageRef!, date: date!)
m.key = d.key
let tempImageRef = self.sref.child(m.imageRef)
tempImageRef.getData(maxSize: 500*1024*1024, completion: {(data,error) in
if error == nil
{
if let imageData = data
{
m.image = UIImage(data: imageData)
self.memories.append(m)
self.tbl.reloadData()
}
}
})
self.memoriesTitlesArr.append(title!)
}
}//end of if
})
}
// Notifies the view controller that a segue is about to be performed.
// segue - The segue object containing information about the view controllers involved in the segue.
// senderThe object that initiated the segue.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let identifier = segue.identifier
{
if identifier == "goToEdit"
{
let indexPath = self.tbl.indexPathForSelectedRow
let addMemoryViewController = segue.destination as! AddMemoryViewController
self.strMode = "edit"
self.lastIndex = (indexPath?.row)!
addMemoryViewController.mode = self.strMode
addMemoryViewController.current = memories[(indexPath?.row)!]
}
}
}
var searching = false
}
extension MemoryViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredDataa = memoriesTitlesArr.filter({ $0.prefix(searchText.count)==searchText.lowercased()})
searching = true
tbl.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searching = false
searchBar.text = ""
tbl.reloadData()
}
}
Here is how you can get that working.
1. First of all, there is no need for searching to maintain the state of searching and not searching.
2. Secondly, use filteredData as the dataSource for tableView instead of memories. filteredData will initially contain all the objects from memories, i.e.
var memories : [Memory] = []
lazy var filteredData = self.memories
The UITableViewDataSource methods will be like,
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.filteredData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "iden") {
cell.textLabel?.text = self.filteredData[indexPath.row].title
return cell
}
return UITableViewCell()
}
Now, while searching update the filteredData with filtered memories using the relevant condition, i.e.
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
self.filteredData = self.memories.filter({ $0.title.hasPrefix(searchText) })
//change the condition as per your requirement......
self.tbl.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.text = nil
self.filteredData = self.memories
self.tbl.reloadData()
}
When cancelled, refill the filteredData with the whole memories data.

How do I put my images from Core Data into a UICollectionView?

I'm relatively new to Xcode and I want to put images I have in CoreData to be shown in an image slider(uicollectionview). The image slider works just fine with some images I reference within an array, but I want to use the images from core data. How do I do that?
var arrAllpost = [post]()
struct post{
var Images:[UIImage]
}
func fetchData(){
let context = (UIApplication.shared.delegate as!
AppDelegate).persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName:
"PhotoData")
do {
let results = try context.fetch(fetchRequest)
for dict in results
{
let imagestr = dict["ImagesName"] as! String
let array = imagestr.components(separatedBy: ", ") // store image
in directory and save image name with comma separated in one string
in core data and then that string split by comma and store in
name array then load that imagename's image from directory
let arrPostImages = NSMutableArray()
for i in array
{
let postimage = loadImageFromDirectory(str: i) //get image from
directory
arrPostImages.add(postimage)
}
arrAllPost.append(post(Images: arrPostImages))
}
}catch let err as NSError {
print(err.debugDescription)
}
}
// tableview delegate method
func tableView(_ tableView: UITableView, numberOfRowsInSection section:
Int) -> Int {
return arrAllPost.count;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell {
let cell = tablePost.dequeueReusableCell(withIdentifier: "Cell",
for: indexPath)
let item = arrAllPost[indexPath.row] as! Post
for img in item.Images
{
cell.postimageView.image = img
}
return cell;
}

Core Data prints saved data but not showing up on table viewcontroller

I would like to show my saved data in core data on a table view controller, the data is saved properly and prints out the details on the console but the data is noot showing up on the tableview cell, kindly please help
var charData = [SavedCharacters]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var name = String()
var house = String()
var ancestry = String()
var getImage = UIImage()
override func viewDidLoad() {
super.viewDidLoad()
getData()
}
func getData(){
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "SavedCharacters")
request.returnsObjectsAsFaults = false
do{
let result = try? context.fetch(request)
for data in result as! [NSManagedObject]
{
name = data.value(forKey: "name") as! String
print(data.value(forKey: "name")as! String)
}
}
tableView.reloadData()
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return charData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "dataCell", for: indexPath) as! SavedDataTableViewCell
cell.nameLabel.text = charData[indexPath.row].name!
cell.house = charData[indexPath.row].house!
cell.ancestry = charData[indexPath.row].ancestry!
// displaying image in table view cell
if let imageURL = URL(string: self.charData[indexPath.row].image!) {
DispatchQueue.global().async {
let data = try? Data(contentsOf: imageURL)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
cell.charImageView.image = image
}
}
}
}
return cell
}
Definitely you've forgotten to init charData in getData() method
var charData: [CharData]
func getData(){
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "SavedCharacters")
request.returnsObjectsAsFaults = false
====> charData = []
do{
let result = try? context.fetch(request)
for data in result as! [CharData]
{
name = data.value(forKey: "name") as! String
print(data.value(forKey: "name")as! String)
===> charData.append(data)
}
}
tableView.reloadData()
}

Can not display image in table view cell using firebase

I can not display image using firebase in table view cell, I don't know why because my code seems to work, but not there, may anyone help me?
Note: The label Works. I created a custom cell using a cocoa touch class, then I have linked that using the notation to cell as you can see.
import UIKit
import Firebase
class PlacesTableViewController: UIViewController,
UITableViewDataSource, UITableViewDelegate{
let ref = Database.database().reference()
var PlacesRef:DatabaseReference! = nil
var SelectedRef:DatabaseReference! = nil
let storage = Storage.storage()
var postdata:[String] = [String]()
#IBOutlet weak var tableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
print("Here Variables")
print("Here translated Names")
PlacesRef = ref.child("Places")
let storageRef = self.storage.reference()
PlacesRef.observe(.value) { (snapshot) in
let postDict = snapshot.value as? [String : AnyObject] ?? [:]
if snapshot.exists() {
for a in ((snapshot.value as AnyObject).allKeys)!{
var now:String = ""
self.postdata.append(a as! String)
DispatchQueue.main.async{
self.tableview.reloadData()
}
}
} else {
print("we don't have that, add it to the DB now")
}
print(self.postdata) //add key to array
}
tableview.delegate = self
tableview.dataSource = self
}
func tableView(_ _tableView: UITableView, numberOfRowsInSection selection: Int) ->Int{
print(postdata)
return postdata.count
}
func tableView( _ tableview: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableview.dequeueReusableCell(withIdentifier: "cell") as! CustomTableViewCell
var image=UIImage()
let StorageRef = storage.reference()
let NationRef = StorageRef.child("Nations/\(postdata[indexPath.row]).jpg")
print("\(postdata[indexPath.row]).jpg")
NationRef.getData(maxSize: 1 * 1024 * 1024) { data, error in
if let error = error {
print(error)
} else {
// Data for "images/island.jpg" is returned
image = UIImage(data: data!)!
print("image downloaded!")
}
}
cell.DetailLabel.text = postdata[indexPath.row]
cell.DetailImage.image = image
return cell
}
}
Let's see what happens in
func tableView( _ tableview: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableview.dequeueReusableCell(withIdentifier: "cell") as! CustomTableViewCell
var image=UIImage()
let StorageRef = storage.reference()
let NationRef = StorageRef.child("Nations/\(postdata[indexPath.row]).jpg")
// HERE we starting async web request for image data (tag 1)
NationRef.getData(maxSize: 1 * 1024 * 1024) { data, error in
if let error = error {
print(error)
} else {
// HERE we getting image data from async request and storing it in image var (tag 3)
image = UIImage(data: data!)!
print("image downloaded!")
}
}
cell.DetailLabel.text = postdata[indexPath.row]
// HERE we setting UIImage to cell's imageView (tag 2)
cell.DetailImage.image = image
return cell
}
if printing tags we'll get tag 1, tag 2 and tag 3. It means that firstly you create empty uiimage, then set this image to cell's imageView and at last you change image to image from request (image, not cell's imageView)
I think the answer can be - replace image = UIImage(data: data!)! with cell.DetailImage.image = UIImage(data: data!)
and there are many ways to improve this method

How do I get the value from the model to the controller

This is my first program using MVC design pattern, I'm stuck how to get the values from the model to my controller and to display it in my view. I'll show you what I have done. Kindly clarify me what I did wrong? Or show me how it can be done in other way around.
Model
class songData: NSObject {
var artistName: String
var albumName: String
init(artistName: String, albumName: String) {
self.artistName = artistName
self.albumName = albumName
}
}
Controller
#IBAction func doTheSearch(sender: AnyObject) {
itunesAPI().itunesSearch({(song : songData) in
})
self.tableView.reloadData()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return song1.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
var artistAndAlbum = itunesAPI().array[indexPath.row]
cell.textLabel?.text =
cell.detailTextLabel?.text =
return cell
}
API
func itunesSearch(completionHandler:(songData)->()) {
Alamofire.request(.GET, "http://itunes.apple.com/search?", parameters: ["term" : "tamil new songs", "media" : "music"])
.responseJSON { (response) in
let json = JSON(response.result.value!)
if let jsonData = json["results"].arrayObject {
self.array = jsonData as! [[String : AnyObject]]
if self.array.count > 0 {
// self.array = jsonData as! [[String : AnyObject]]
// if let resultsDict = resultsArray.first {
let albumName = json["results"]["collectionName"].stringValue
let artistName = json["results"]["artistName"].stringValue
let song = songData(artistName: artistName, albumName: albumName)
completionHandler(song)
}
}
I do have the nothing on my view except the story board which consists of a table view with a single cell. I need to get the response from the API and show it in the view.
First, you're going to want to reload your table after the data is returned. Update your IBAction to this:
itunesAPI().itunesSearch({(song : songData) in
self.tableView.reloadData()
})
Otherwise reloadData will get called before the data is returned. Set a property on the viewController to house the data. Also, it's good practice to start a class name with a capital letter.
var tableData:[SongData] = [SongData]()
Then set this variable when the data successfully returns:
itunesAPI().itunesSearch({(song : songData) in
self.tableData.append(song) // add the result to the list of data
self.tableView.reloadData() // reload the table
})
Then set the cells as so:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
var artistAndAlbum = self.tableData[indexPath.row]
cell.textLabel?.text = artistAndAlbum.artistName
cell.detailTextLabel?.text = artistAndAlbum.albumName
return cell
}