Retrieving image from Firebase Storage placing in tableView not working, - ios

I was able to display the image properly when i have just an imageView in a ViewController. I used this code:
islandRef.getData(maxSize: 1 * 1024 * 1024) { [weak self] data, error in
if let error = error {
print((error.localizedDescription))
// Uh-oh, an error occurred!
}
if let data = data{
self?.imageItem.image = UIImage(data: data)
}
}
}
I try a similar approach for my tableView, but its a little more complicated. I have two arrays that pull a string and an integer from my firebase document. I append these to the arrays items and prices. I am able to show these values in my tableView. I try the same thing when my pictues array. I am able to append an image to it. I then check if the pictures array has a count. It has a count of 1, but when i try to access it in tableview. It says the error: Thread 1: Fatal error: Index out of range. I don't understand why my other arrays have values that are usable, but this array does. I don't think there is a problem with the imageView because i can replaces pictures[indexPath.row] with my PlaceholderImage and it will properly show my placeholder image.
class ProfileViewController: UITableViewController {
var item = [String]()
var prices = [Int]()
var pricePicture = [Any]()
var db:Firestore!
var pictures = [UIImage]()
let storage = Storage.storage()
var placeholderImage = UIImage(named: "placeholder.jpg")
var imageMenu:UIImage?
override func viewDidLoad() {
getData()
let db = Firestore.firestore()
super.viewDidLoad()
}
func getData(){
let db = Firestore.firestore()
let docRef = db.collection("wine").document("pinot-noir-2017")
let storage = Storage.storage()
docRef.getDocument(source: .server) { (document, error) in
if let document = document {
let keys = document.data()?.keys
for key in keys!{
self.item.append(key)
self.pricePicture = document.data()![key] as! [Any]
self.prices.append(self.pricePicture[0] as! Int)
let stor = storage.reference()
let islandRef = stor.child("carbanet.jpg")
islandRef.getData(maxSize: 1 * 1024 * 1024) { [weak self] data, error in
if let error = error {
print((error.localizedDescription))
}
if let data = data{
self?.pictures.append(UIImage(data: data)!)
//this will print 1
print(self?.pictures.count ?? 0)
}
}
self.tableView.reloadData()
}
} else {
//print("Document does not exist in cache")
}
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return item.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Picture", for: indexPath)
cell.textLabel?.text = item[indexPath.row] + " $" + String(prices[indexPath.row])
cell.imageView?.image = pictures[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let detailViewController = storyboard?.instantiateViewController(identifier: Constants.Storyboard.detailViewController) as? DetailViewController{
show(detailViewController, sender: .none)
}
}
}
If someone could show me the error I am making that would be great. I'm pretty new to swift, so any help you can give me would be appreciated. I have read through the firebase documentation and watched their videos, but I can't figure out why it works in one scenario and not the other.

I think it was because i was trying to do it inside of trying to access a firebase document. I made another function getImage() and this time it worked.
func getImage(){
let stor = storage.reference()
let islandRef = stor.child("carbanet.jpg")
islandRef.getData(maxSize: 1 * 1024 * 1024) { [weak self] data, error in
if let error = error {
print((error.localizedDescription))
// Uh-oh, an error occurred!
}
if let data = data{
self?.pictures.append(UIImage(data: data as Data)!)
//this will print 1
print(self?.pictures.count ?? 0)
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}

Related

Retrieve photos from firebase storage SWIFT

I have a problem since yesterday morning but I can't figure it out how can I resolve this issue.
I'm having a table view which is using prototype cells, 2 labels and 1 photo. For the labels I used Firestore and for the picture firebase storage.
The problems is that the only way I know how to retrieve photos from my firebase storage is this code
let storage = Storage.storage()
let storageRef = storage.reference()
let ref = storageRef.child("Mancare/Mancare3.jpg")
testImage.sd_setImage(with: ref)
I want to retrieve the photos into my table view, but I do not know how can I can accomplish that.
This is what im using for retrieving the labels with Firestore . I'll paste only the necessary parts of the code :
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return labels.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableViewTest.dequeueReusableCell(withIdentifier: "CountryTableViewCell", for: indexPath) as! CountryTableViewCell
let storage = Storage.storage()
let storageRef = storage.reference()
let ref = storageRef.child("Mancare/Mancare3.jpg")
let label = labels[indexPath.row]
cell.labelTest.text = label.firstLabel
cell.labelLaba.text = label.secondLabel
return cell
}
func getDatabaseRecords() {
let db = Firestore.firestore()
labels = [] // Empty the array
db.collection("labels").getDocuments { (snapshot, error) in
if let error = error {
print(error)
return
} else {
for document in snapshot!.documents {
let data = document.data()
let newEntry = Labels(
firstLabel: data["firstLabel"] as! String,
secondLabel: data["secondLabel"] as! String)
self.labels
.append(newEntry)
}
}
DispatchQueue.main.async {
self.tableViewTest.reloadData()
}
}
}
This is how I declared the labels:
struct Labels {
let firstLabel: String
let secondLabel: String
}
var labels: [Labels] = []
If someone can help me , ill be forever grateful . Thanks
First, you need to fix your model so it can help you. Add the bucket name to the model like this:
Struct Labels {
let firstLabel: String
let secondLabel: String
let photoKey: String // This will store the bucket name for this `Labels`
}
Now in your getDatabaseRecords change:
let newEntry = Labels(firstLabel: data["firstLabel"] as! String,
secondLabel: data["secondLabel"] as! String),
photoKey: data["photoKey"] as! String) // Added Line
Then in cellForRow:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableViewTest.dequeueReusableCell(withIdentifier: "CountryTableViewCell", for: indexPath) as! CountryTableViewCell
let label = labels[indexPath.row]
let storageRef = Storage.storage().reference()
let photoRef = storageRef.child(label.photoKey)
cell.labelTest.text = label.firstLabel
cell.labelLaba.text = label.secondLabel
cell.imageView.sd_setImage(with: photoRef) // Assuming the image view in your cell is named this
return cell
}
Last, make sure your document structure matches the new Labels Model in the firebase console, and you have images as well in the root of your storage that match with all the photoKeys. Btw, Labels is not a very good model name, I just went with it for consistency

Why JSON data from decoder to become UITableView datasource does not assigns?

Recently got stuck on a problem of assigning freshly downloaded JSON data to table view datasource variable. I suppose the problem is something obvious but my skill is not enough to gather the big picture. Let me share a bunch of code.
(1) A function retrieves the data from Open Weather Map API (defined in the separate class 'GetWeather').
func getMowForecast(completion: #escaping ((WeatherForecast?, Bool)) -> Void) {
let url = URL(string: "http://api.openweathermap.org/data/2.5/forecast?id=524901&APPID=b3d57a41f87619daf456bfefa990fce4&units=metric")!
let request = URLRequest(url: url)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
do {
let json = try JSONDecoder().decode(WeatherForecast.self, from: data)
completion((json, true))
} catch {
print(error)
completion((nil, false))
}
} else {
print(error)
}
}
task.resume()
}
Everything works fine here. JSON loads correctly and fits the data model.
Here's a link to JSON data to be displayed in tableView: https://pastebin.com/KkXwxYgS
(2) A controller handles the display of retrieved JSON data in tableView format
import UIKit
class ForecastViewController: UITableViewController {
#IBOutlet weak var tableV: UITableView! // tableView outlet in the IB
let weatherGetter = GetWeather() // object to handle the JSON retrieval
var tableData: WeatherForecast? // tableView data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tableData?.list.count ?? 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableVCCell
cell.dateLabel.text = "\(self.tableData?.list[indexPath.row].dt)"
cell.tempLabel.text = "\(self.tableData?.list[indexPath.row].main.temp)"
cell.feelsLikeLabel.text = "\(self.tableData?.list[indexPath.row].main.feels_like)"
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = true
tableV.delegate = self
tableV.dataSource = self
weatherGetter.getMowForecast { (data, status) in
if let data = data, status {
} else if status {
print("-------- Ошибка разбора данных прогноза погоды --------")
} else {
print("-------- Ошибка получения данных прогноза погоды --------")
}
self.tableData = data
print(self.tableData)
}
print(self.tableData?.list.count) // returns nil
self.tableData = weatherGetter.getMowForecast(completion: ((tableData, true))) // error - Cannot convert value of type '(WeatherForecast?, Bool)' to expected argument type '((WeatherForecast?, Bool)) -> Void'
}
}
The problem is - the table view gets nil datasource so it is unable to load the data and shows the blank screen.
I suppose the mistake is in scope - I try to retrieve the JSON data inside a function and it does not go anywhere else. What I am wondering about is - how comes that assigning the data to self.tableData does not makes any effect?
Could you please help.
Thank you!
Regards
First of all delete
print(self.tableData?.list.count) // returns nil
self.tableData = weatherGetter.getMowForecast(completion: ((tableData, true))) // error - Cannot convert value of type '(WeatherForecast?, Bool)' to expected argument type '((WeatherForecast?, Bool)) -> Void'
The error occurs because the method does not return anything and the completion handler syntax is wrong. Both lines are pointless anyway due to the asynchronous behavior of getMowForecast
Secondly I recommend to declare the data source array as a non-optional array of the type which represents List. Then you get rid of all those unnecessary optionals.
var tableData = [List]()
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tableData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableVCCell
let weatherData = self.tableData[indexPath.row]
cell.dateLabel.text = "\(weatherData.dt)"
cell.tempLabel.text = "\(weatherData.main.temp)"
cell.feelsLikeLabel.text = "\(weatherData.main.feels_like)"
return cell
}
To be able to display the data – as already mentioned by others – you have to reload the table view in the completion handler. And assign the data only if status is true.
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = true
tableV.delegate = self
tableV.dataSource = self
weatherGetter.getMowForecast { [weak self] (data, status) in
if let data = data, status {
self?.tableData = data.list
DispatchQueue.main.async {
self?.tableV.reloadData()
}
} else if status {
print("-------- Ошибка разбора данных прогноза погоды --------")
} else {
print("-------- Ошибка получения данных прогноза погоды --------")
}
}
}
And consider that the message Ошибка разбора данных прогноза погоды will be never displayed.
You need to reload the table inside the callback as it's asynchronous
self.tableData = data
print(self.tableData)
DispatchQueue.main.async { self.tableV.reloadData() }

Repeating the same query snapshot, bringing in same data, despite new data being added to firestore

I have been following the documentation to create a query search in my database to obtain the top scores to display in a tableView.
The code below works, however, when a new (higher score) is added, the tableview is still displaying the old query data.
E.g I have three top scores in my database.. [121, 131, 134]. After the first query these are displayed correctly.
I then continue to play and add some more scores, [121, 131, 134, 234, 432] but the same results are shown in my tableView [121, 131, 134].
I am limiting my display to three items. So it should really show ..... [134, 234, 432].
I have tried clearing my tableView with
scoresArray.removeAll()
topScoresTableView.reloadData()
(This is called when I leave the VC) But this had no effect.
class ScoreClass {
let db = Firestore.firestore()
var name = ""
var score = 0
init(withName: String, andScore: Int) {
name = withName
score = andScore
}
}
let ref = Database.database().reference()
func retrieveUserData() {
let postsRef = self.db.collection("users")
let query = postsRef
.whereField("highScore", isGreaterThan: 5000)
.order(by: "highScore", descending: false)
.limit(to: 3)
query.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
print("\(document.documentID) => \(document.data())")
let dict = document.data()
let name = dict["username"] as! String
let score = dict["highScore"] as! Int
let aScore = ScoreClass(withName: name, andScore: score)
self.scoresArray.insert(aScore, at: 0)
}
self.topScoresTableView.reloadData()
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.scoresArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = topScoresTableView.dequeueReusableCell(withIdentifier: textCellIdentifier, for: indexPath) as! TableViewCell
let row = indexPath.row
let scoreClassObject = scoresArray[row]
let name = scoreClassObject.name
let score = scoreClassObject.score
cell.backgroundColor = UIColor.clear
cell.usernameLabel.text = name
cell.resultLabel.text = String(score)
cell.rankNumberLabel.text = "\(indexPath.row + 1)"
print(scoresArray)
return cell
}
Your code isn't arranging to receive realtime updates from Firestore. It is just querying Firestore a single time with getDocuments().
What you will have to do instead is change your code to listen to realtime updates using addSnapshotListener(), then update your TableView every time your listener is invoked, when the results of the query change over time.

Json Data not properly reflecting in tableView

Loading local json file to table view and in Debugger Log all goes fine but data is repeating itself in tableView. I've taken screenshot of simulator and Log both here - May be i think i've a problem in appending data. I have TableViewCell - viewCell and my data class - attendance.swift and a tableViewController of course. I am trying to display two data fields. Code for tableViewController -
var checkins = [attendance]()
override func viewDidLoad() {
super.viewDidLoad()
jsonParsingFromFile()
}
func jsonParsingFromFile()
{
let path: NSString = NSBundle.mainBundle().pathForResource("jsonFile", ofType: "json")!
let data : NSData = try! NSData(contentsOfFile: path as String, options: NSDataReadingOptions.DataReadingMapped)
self.parseJsonData(data)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
}
func parseJsonData(data:NSData) -> [attendance]{
do{
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
//parse json data
let jsonCheckins = jsonResult?["university1"] as! [AnyObject]
for jsonAttendance in jsonCheckins {
let checkin = attendance()
checkin.id = jsonAttendance["id"] as! Int
checkin.name = jsonAttendance["name"] as! String
if (creden != checkin.id)
{
}
else
{
print(checkin.id)
print(checkin.name)
let check = jsonAttendance["attendance"] as! [AnyObject]
for ch in check {
checkin.subject = ch["subject"] as! String
print(checkin.subject)
checkin.attended = ch["attended"] as! Int
checkin.done = ch["held"] as! Int
checkin.atd = (Float(checkin.attended)/Float(checkin.done))*100
print(checkin.atd , " %")
checkins.append(checkin)
}
}
}
}
catch{
print(error)
}
return checkins
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return checkins.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! viewCell
cell.subjectLabel.text = checkins[indexPath.row].subject
cell.attendanceLabel.text = String(checkins[indexPath.row].atd)+" %"
return cell
}
Error seems to be because you are updating a single object only and adding it to array. Therefore in the end you are left up with only one type of object in array with same values
let checkin = attendance()
move that to inside the loop
for ch in check {

ReloadData not working Swift with Alamofire

I tried to reload my UITableView after adding new items. When I try with a reloadData() it's not working. Nothing is shown.
If I try to reload my getallrecords function, that reload items but they are repeated.
My source code is :
class FriendsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate {
#IBOutlet var tabeview: UITableView!
var textArray: NSMutableArray! = NSMutableArray()
var subArray: NSMutableArray! = NSMutableArray()
let defaults = NSUserDefaults.standardUserDefaults()
var valueToPass:String!
var reports_d:String!
var reports:String!
#IBOutlet var menuButton: UIBarButtonItem!
#IBOutlet var friends_icon: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
tabeview.dataSource = self
tabeview.delegate = self
tabeview.emptyDataSetSource = self
tabeview.emptyDataSetDelegate = self
tabeview.tableFooterView = UIView()
getallrecords()
self.tabeview.addPullToRefresh({ [weak self] in
// refresh code
self!.getallrecords()
self?.tabeview.stopPullToRefresh()
})
// Do any additional setup after loading the view.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.textArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
cell.textLabel?.text = self.textArray.objectAtIndex(indexPath.row) as? String
cell.detailTextLabel?.text = self.subArray.objectAtIndex(indexPath.row) as? String
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("You selected cell #\(indexPath.row)!")
// Get Cell Label
let indexPath = tableView.indexPathForSelectedRow!
let currentCell = tableView.cellForRowAtIndexPath(indexPath)! as UITableViewCell
valueToPass = currentCell.textLabel!.text
reports = reports_d
performSegueWithIdentifier("friends_details", sender: self)
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete) {
// handle delete (by removing the data from your array and updating the tableview)
let currentCell = tableView.cellForRowAtIndexPath(indexPath)! as UITableViewCell
let friend2 = currentCell.textLabel!.text
let defaults = NSUserDefaults.standardUserDefaults()
let username = defaults.objectForKey("name") as! String
Alamofire.request(.GET, "http://www.example.com/app/remove_friends.php", parameters: ["key_id": "xxxxx","user_id": username,"friend_receive_id": friend2!, "action": "delete"])
.response { request, response, data, error in
print(request)
print(response)
print(error)
if(error == nil)
{
self.tabeview.beginUpdates()
self.textArray.removeObjectAtIndex(indexPath.row)
self.subArray.removeObjectAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
self.tabeview.endUpdates()
}
}
NSNotificationCenter.defaultCenter().postNotificationName("reloadData",object: self)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){
if (segue.identifier == "friends_details") {
// initialize new view controller and cast it as your view controller
let viewController = segue.destinationViewController as! DetailsFriendsViewController
// your new view controller should have property that will store passed value
viewController.passedValue = valueToPass
viewController.reports = reports
}
}
func getallrecords(){
if(defaults.stringForKey("name") != nil ){
let username = defaults.objectForKey("name") as! String
let full = "http://www.example.com/app/danger_friend_view.php?search=true&username=" + username
let url = NSURL(string: full)
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
do {
let d = NSString(data: data!, encoding: NSUTF8StringEncoding)
var arr = d!.componentsSeparatedByString("<") // spliting the incoming string from "<" operator because before that operator is our required data and storing in array
let dataweneed:NSString = arr[0] as NSString // arr[0] is the data before "<" operator and arr[1] is actually no use for us
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
SwiftSpinner.hide()
do {
if let data = try NSJSONSerialization.JSONObjectWithData(dataweneed.dataUsingEncoding(NSUTF8StringEncoding)!, options: [NSJSONReadingOptions.MutableContainers]) as? NSArray {
for dd in data{
var name : String = dd["danger"]! as! String
self.reports_d = name
let info : String = dd["username"]! as! String
name = NSLocalizedString("SEND_ALERT_BEGIN",comment:"SEND_ALERT") + name + NSLocalizedString("ALERTS",comment:"ALERTS")
print("ID is : \(name)")
print("Username is : \(info)")
self.textArray.addObject(info)
self.subArray.addObject(name)
}
self.tabeview.reloadData()
}
} catch let error as NSError {
print(error.localizedDescription)
}
})
}
}
task.resume()
}
else
{
//Do something
}
}
#IBAction func reload_data(sender: UIButton) {
let banner = Banner(title: NSLocalizedString("RELOAD_DATA_TITLE",comment:"I'm in danger, I'm currently at "), subtitle: NSLocalizedString("RELOAD_DATA",comment:"I'm in danger, I'm currently at "), image: UIImage(named: "Icon"), backgroundColor: UIColor(red:52.00/255.0, green:152.00/255.0, blue:219.00/255.0, alpha:0.89))
banner.dismissesOnTap = true
banner.show(duration: 10.0)
dispatch_async(dispatch_get_main_queue()) {
//Not working ....
self.tabeview.reloadData()
}
}
func titleForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
let str = "Oups"
let attrs = [NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)]
return NSAttributedString(string: str, attributes: attrs)
}
func descriptionForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
let str = NSLocalizedString("NO_FRIENDS_TO_SHOW",comment:"No friends to show ")
let attrs = [NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleBody)]
return NSAttributedString(string: str, attributes: attrs)
}
func imageForEmptyDataSet(scrollView: UIScrollView!) -> UIImage! {
return UIImage(named: "no-friends")
}
func buttonTitleForEmptyDataSet(scrollView: UIScrollView!, forState state: UIControlState) -> NSAttributedString! {
let str = NSLocalizedString("ADD_FRIENDS",comment:"Add a friend ")
let attrs = [NSFontAttributeName: UIFont(name: "HelveticaNeue-Light", size: 19)!]
return NSAttributedString(string: str, attributes: attrs)
}
func emptyDataSetDidTapButton(scrollView: UIScrollView!) {
let alert = SCLAlertView()
let txt = alert.addTextField("Friend's username")
alert.addButton("Add") {
if(txt.text=="")
{
let banner = Banner(title: NSLocalizedString("ERROR_NO",comment:"An error occured"), subtitle: NSLocalizedString("ERROR_NO_TEXT",comment:"I'm in danger, I'm currently at "), image: UIImage(named: "Icon"), backgroundColor: UIColor(red:152.00/255.0, green:52.00/255.0, blue:52.00/255.0, alpha:0.89))
banner.dismissesOnTap = true
banner.show(duration: 10.0)
}
else
{
let defaults = NSUserDefaults.standardUserDefaults()
let username = defaults.objectForKey("name") as! String
let remove_friend_username = txt.text! as String
Alamofire.request(.GET, "http://www.example.com/add_friends.php", parameters: ["key_id": "xxx","user_id": username,"friend_receive_id": remove_friend_username, "action": "add"])
.response { request, response, data, error in
dispatch_async(dispatch_get_main_queue()) {
self.tabeview.reloadData()
//Not working
}
}
}
}
alert.showEdit("Add friend", subTitle: "You can add a friend by enter his username")
}
}
I believe you are missing a little point in here buddy :)
Question 1
Why reloading tableView wont show new data ??
Your function reload_data is doing nothing more than reloading data buddy :) When you call reload data all the tableView delegates like number of rows in section,number of sections and cellForRowAtIndexPath gets called but all these methods return the value depending on the data source you provide isn't it buddy :)
So if you change the data source and then call reload data they will show you the new data :) but in your reload_data function you are not altering the data source at all :) simply calling reload data on the unalterred data source will re render the tableView again thats all :)
What you can do :)
You already have a method that fetches the new data using almofire :) just call it and in the success block anyway you are reloading the tableView :) So everything will be fine buddy :)
#IBAction func reload_data(sender: UIButton) {
let banner = Banner(title: NSLocalizedString("RELOAD_DATA_TITLE",comment:"I'm in danger, I'm currently at "), subtitle: NSLocalizedString("RELOAD_DATA",comment:"I'm in danger, I'm currently at "), image: UIImage(named: "Icon"), backgroundColor: UIColor(red:52.00/255.0, green:152.00/255.0, blue:219.00/255.0, alpha:0.89))
banner.dismissesOnTap = true
banner.show(duration: 10.0)
self.getallrecords() //simply call this method this will anyhow will reload data on success :)
}
Question 2
Why my tableView shows duplicate data???
Your tableView always show the data which is there in its datasource :) SO if your tableView is showing duplicate cells that means you have duplicate entry in your data source :)
You are dealing with array, in future you might migrate to coredata :)
Understand one thing, when you enter or add a entry to your data source if you dont want to show duplicates you will have to handle it explicitly.
How can I do that ???
From your code I beilieve info(username) value is unique per object. So before blindly adding response to textArray check if text array already consists that object if yes then dont add it again :)
Based on the above stated assumption and believing you are making use of swift 2.0
if let data = try NSJSONSerialization.JSONObjectWithData(dataweneed.dataUsingEncoding(NSUTF8StringEncoding)!, options: [NSJSONReadingOptions.MutableContainers]) as? NSArray {
for dd in data{
var name : String = dd["danger"]! as! String
self.reports_d = name
let info : String = dd["username"]! as! String
name = NSLocalizedString("SEND_ALERT_BEGIN",comment:"SEND_ALERT") + name + NSLocalizedString("ALERTS",comment:"ALERTS")
print("ID is : \(name)")
print("Username is : \(info)")
if !self.textArray.contains(info){
self.textArray.addObject(info)
self.subArray.addObject(name)
}
}
self.tabeview.reloadData()
}
Now that's a lot of code, I want a easier solution :)
Clear the array before adding the new response :) Thats all :)
if let data = try NSJSONSerialization.JSONObjectWithData(dataweneed.dataUsingEncoding(NSUTF8StringEncoding)!, options: [NSJSONReadingOptions.MutableContainers]) as? NSArray {
self.textArray.removeAll()
self.subArray.removeAll() //clear the arrays and then re populate them thats all no duplicate data anymore :P
for dd in data{
var name : String = dd["danger"]! as! String
self.reports_d = name
let info : String = dd["username"]! as! String
name = NSLocalizedString("SEND_ALERT_BEGIN",comment:"SEND_ALERT") + name + NSLocalizedString("ALERTS",comment:"ALERTS")
print("ID is : \(name)")
print("Username is : \(info)")
self.textArray.addObject(info)
self.subArray.addObject(name)
}
self.tabeview.reloadData()
}

Resources