I'm attempting to display an image from my Firebase database in a TableView cell, however, when I run my app, the cell shows up blank. Everything seems to be connected to the storyboard, and Firebase is connected (in the database, the reference to the image is labeled as 'imageURL'), so I'm assuming it's a problem within the code itself. The code is shown below:
Post.swift
import Foundation
import Firebase
import FirebaseStorage
import FirebaseDatabase
class Post {
private var _image: String!
private var _imageKey: String!
private var _imageRef: FIRDatabaseReference!
var postImg: String {
get {
return _image
} set {
_image = newValue
}
}
var imageKey: String {
return _imageKey
}
init(imgUrl: String) {
_image = imgUrl
}
init(imageKey: String, imageData: Dictionary<String, AnyObject>) {
_imageKey = imageKey
if let postImage = imageData["imageUrl"] as? String {
_image = postImage
}
_imageRef =
FIRDatabase.database().reference().child("images").child(_imageKey)
}
}
PostCell.swift
import UIKit
import Firebase
import FirebaseDatabase
class PostCell: UITableViewCell {
#IBOutlet weak var postImg: UIImageView!
var searchedPost: Post!
var searchedPostKey: FIRDatabaseReference!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func configCell(searchedPost: Post, img: UIImage? = nil) {
self.searchedPost = searchedPost
if img != nil {
self.postImg.image = img
} else {
let ref = FIRStorage.storage().reference(forURL: searchedPost.postImg)
ref.data(withMaxSize: 10 * 1000, completion: { (data, error) in
if error != nil {
print(error)
} else {
if let imgData = data {
if let img = UIImage(data: imgData){
self.postImg.image = img
}
}
}
})
}
}
}
ViewController.swift
import UIKit
import Firebase
import FirebaseDatabase
class LeftView: UIViewController, UITableViewDelegate, UITableViewDataSource, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var tableView: UITableView!
var images = [Post]()
var searchedPost: Post!
var imagePicker: UIImagePickerController!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
imagePicker = UIImagePickerController()
imagePicker.allowsEditing = true
imagePicker.delegate = self
FIRDatabase.database().reference().child("images").observe(.value, with:
{(snapshot) in
if let snapshot = snapshot.children.allObjects as? [FIRDataSnapshot] {
self.images.removeAll()
for data in snapshot {
print(data)
if let imageDict = data.value as? Dictionary<String, AnyObject> {
let key = data.key
let searchedPost = Post(imageKey: key, imageData: imageDict)
self.images.append(searchedPost)
}
}
}
self.tableView.reloadData()
})
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return images.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let searchedPost = images[indexPath.row]
if let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell") as? PostCell {
cell.configCell(searchedPost: searchedPost)
return cell
} else {
return PostCell()
}
}
}
You need to reload tableview after you get images from firebase.
Add This line
self.tableView.reloadData()
After
self.images.append(searchedPost)
Also You need to set your image in Main Queue. Use This in Configure Cell method
DispatchQueue.main.async {
self.postImg.image = img
}
Instead of
self.postImg.image = img
Related
I am trying to filter the data from API. The is successful loaded into view controller with table view cell . This is a movie applications . I am trying to filter the data based on the user type into the text box . I mentioned in the code filter my the title of the movie but The code is only able to filter the title and overview of the movie but the Image fields remain unfiltered such as image , overview etc. Here is the struct model .
import Foundation
struct Movie: Decodable {
let originalTitle: String
let overview: String
let posterPath: String
enum CodingKeys: String, CodingKey {
case originalTitle = "original_title"
case overview
case posterPath = "poster_path"
}
}
Here is the protocol class code .
import Foundation
class MoviePresenter: MoviePresenterProtocol {
private let view: MovieViewProtocol
private let networkManager: NetworkManager
var movies = [Movie]()
private var cache = [Int: Data]()
var rows: Int {
return movies.count
}
init(view: MovieViewProtocol, networkManager: NetworkManager = NetworkManager()) {
self.view = view
self.networkManager = networkManager
}
func getMovies() {
let url = "https://api.themoviedb.org/3/movie/popular?language=en-US&page=3&api_key=6622998c4ceac172a976a1136b204df4"
networkManager.getMovies(from: url) { [weak self] result in
switch result {
case .success(let response):
self?.movies = response.results
self?.downloadImages()
DispatchQueue.main.async {
self?.view.resfreshTableView()
}
case .failure(let error):
DispatchQueue.main.async {
self?.view.displayError(error.localizedDescription)
}
}
}
}
func getTitle(by row: Int) -> String? {
return movies[row].originalTitle
}
func getOverview(by row: Int) -> String? {
return movies[row].overview
}
func getImageData(by row: Int) -> Data? {
return cache[row]
}
private func downloadImages() {
let baseImageURL = "https://image.tmdb.org/t/p/w500"
let posterArray = movies.map { "\(baseImageURL)\($0.posterPath)" }
let group = DispatchGroup()
group.enter()
for (index, url) in posterArray.enumerated() {
networkManager.getImageData(from: url) { [weak self] data in
if let data = data {
self?.cache[index] = data
}
}
}
group.leave()
group.notify(queue: .main) { [weak self] in
self?.view.resfreshTableView()
}
}
}
Here is the controller code .
import UIKit
class MovieViewController: UIViewController, UISearchBarDelegate {
#IBOutlet weak var userName: UILabel!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
private var presenter: MoviePresenter!
var finalname = ""
override func viewDidLoad() {
super.viewDidLoad()
userName.text = "Hello: " + finalname
setUpUI()
presenter = MoviePresenter(view: self)
searchBarText()
}
private func setUpUI() {
tableView.dataSource = self
tableView.delegate = self
}
private func searchBarText() {
searchBar.delegate = self
}
#IBAction func selectSegment(_ sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 1{
setUpUI()
presenter = MoviePresenter(view: self)
presenter.getMovies()
}
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText == ""{
presenter.getMovies()
}
else {
presenter.movies = presenter.movies.filter({ movies in
return movies.originalTitle.lowercased().contains(searchText.lowercased())
})
}
tableView.reloadData()
}
}
extension MovieViewController: MovieViewProtocol {
func resfreshTableView() {
tableView.reloadData()
}
func displayError(_ message: String) {
let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
let doneButton = UIAlertAction(title: "Done", style: .default, handler: nil)
alert.addAction(doneButton)
present(alert, animated: true, completion: nil)
}
}
extension MovieViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
presenter.rows
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: MovieViewCell.identifier, for: indexPath) as! MovieViewCell
let row = indexPath.row
let title = presenter.getTitle(by: row)
let overview = presenter.getOverview(by: row)
let data = presenter.getImageData(by: row)
cell.configureCell(title: title, overview: overview, data: data)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let dc = storyboard?.instantiateViewController(withIdentifier: "MovieDeatilsViewController") as! MovieDeatilsViewController
let row = indexPath.row
dc.titlemovie = presenter.getTitle(by: row) ?? ""
dc.overview = presenter.getOverview(by: row) ?? ""
dc.imagemovie = UIImage(data: presenter.getImageData(by: row)!)
self.navigationController?.pushViewController(dc, animated: true)
}
}
extension MovieViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
Here is the screenshot of the result .
Caching image in tableview is a little bit tricky, and you may get problem when the cell changes or reusing itself,
that's cause you see same image when texts are different.
there are 2 famous package you can use it for you're problem and it's easy to use with a lot of options.
1- Kingfisher
2- SDWebImage
I have more restaurants , each have diferent food.Look here
This is how im retrieving data from the Firestore. In the previous controller I have a list of restaurants, each contains a list food.
struct Food {
var photoKeyRestaurant: String
var foodName: String
var foodDescription: String
var restaurantName: String
var priceFood: Int
}
class RestaurantViewController: UIViewController {
var restaurantName: String!
var food: [Food] = []
private let tableView: UITableView = {
let table = UITableView()
return table
}()
func getDatabaseRecords() {
let db = Firestore.firestore()
// Empty the array
food = []
db.collection("RestaurantViewController").whereField("restaurantName", isEqualTo: restaurantName).getDocuments { (snapshot, error) in
if let error = error {
print(error)
return
} else {
for document in snapshot!.documents {
let data = document.data()
let newEntry = Food(photoKeyRestaurant: data["photoKeyRestaurant"] as! String, foodName: data["foodName"] as! String, foodDescription: data["foodDescription"] as! String, restaurantName: data["restaurantName"] as! String , priceFood: data["priceLabel"] as! Int
)
self.food.append(newEntry)
}
}
DispatchQueue.main.async {
// self.datas = self.filteredData
self.tableView.reloadData()
}
}
}
How can I add the data of the selected cell by pressing on + to Firestore in this function ?
I'vrea create a protocol in my FoodTableViewCell , and I've called it in the RestaurantViewController.
func diddTapButtonCell(_ cell: FoodTableViewCell) {
let db = Firestore.firestore()
db.collection("cart").addDocument.(data: foodName) { (err) in
}
Edited: Added Table view
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return food.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FoodTableViewCell", for: indexPath) as! FoodTableViewCell
cell.delegate = self
let mancare = food[indexPath.row]
let storageRef = Storage.storage().reference()
let photoRef = storageRef.child(mancare.photoKeyRestaurant)
cell.foodImage.sd_setImage(with: photoRef)
cell.descriptionLabel.text = mancare.foodDescription
cell.foodNameLabel.text = mancare.foodName
cell.priceLabel.text = "\(mancare.priceFood) lei"
//Fac ca imaginea sa fie cerc - start
cell.foodImage.layer.borderWidth = 1
cell.foodImage.layer.masksToBounds = false
cell.foodImage.layer.borderColor = UIColor.black.cgColor
cell.foodImage.layer.cornerRadius = cell.foodImage.frame.height/2
cell.foodImage.clipsToBounds = true
//Fac ca imaginea sa fie cerc - finish
return cell
}
This is my tableview cell code
protocol CustomCellDelegate {
func diddTapButtonCell (_ cell: FoodTableViewCell)
}
class FoodTableViewCell: UITableViewCell {
var delegate: CustomCellDelegate?
#IBOutlet weak var foodImage: UIImageView!
#IBOutlet weak var foodNameLabel: UILabel!
#IBOutlet weak var descriptionLabel: UILabel!
#IBOutlet weak var priceLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
#IBAction func addToCart(_ sender: Any) {
delegate?.diddTapButtonCell(self)
}
}
https://firebase.google.com/docs/firestore/manage-data/add-data
And here is an example from one of my projects for adding data to firestore.
func updateDocument(rootCollection : String, doc: String, newValueDict: [String : Any], completion:#escaping (Bool) -> Void = {_ in }) {
let db = Firestore.firestore()
db.collection(rootCollection).document(doc).setData(newValueDict, merge: true){ err in
if let err = err {
print("Error writing document: \(err)")
completion(false)
}else{
completion(true)
}
}
}
I am able to query the data and match it to my model but am not able to display it in my table view. I have 3 files I am working with apart from the storyboard.
Here is the main view controller:
class MealplanViewController: UIViewController {
var db: Firestore!
var mealplanArray = [Mealplan]()
#IBOutlet weak var mealplanTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
mealplanTableView?.dataSource = self
mealplanTableView?.delegate = self
db = Firestore.firestore()
loadData()
// Do any additional setup after loading the view.
}
func loadData() {
userEmail = getUserEmail()
db.collection("Meal_Plans").getDocuments() {querySnapshot , error in
if let error = error {
print("\(error.localizedDescription)")
} else {
self.mealplanArray = querySnapshot!.documents.compactMap({Mealplan(dictionary: $0.data())})
print(self.mealplanArray)
DispatchQueue.main.async {
self.mealplanTableView?.reloadData()
}
}
}
}
func getUserEmail() -> String {
let user = Auth.auth().currentUser
if let user = user {
return user.email!
} else {
return "error"
}
}
}
// MARK: - Table view delegate
extension MealplanViewController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return mealplanArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//let cell = tableView.dequeueReusableCell(withIdentifier: "MealplanTableViewCell", for: indexPath)
let mealplanRow = mealplanArray[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "MealplanTableViewCell") as! MealplanTableViewCell
cell.setMealplan(mealplan: mealplanRow)
return cell
}
}
And here is the cell where I am showing one of the queried values:
class MealplanTableViewCell: UITableViewCell {
#IBOutlet weak var mealplanNameLabel: UILabel!
func setMealplan(mealplan: Mealplan) {
// Link the elements with the data in here
mealplanNameLabel.text = mealplan.mpName
print(mealplan.mpName)
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
And finally, here is the data model:
import Foundation
import Firebase
protocol MealplanSerializable {
init?(dictionary:[String:Any])
}
struct Mealplan {
var mealplanId:String
var mpName:String
]
}
}
extension Mealplan : MealplanSerializable {
init?(dictionary: [String : Any]) {
guard let
let mealplanId = dictionary["mealplanId"] as? String,
let mpName = dictionary["mpName"] as? String,
else { return nil }
self.init(mealplanId: mealplanId, mpName: mpName)
}
}
I am getting just an empty table view with no data in it.
I am building an app that uses the Twitter API to post to a user's Twitter and load those tweets in a TableView. The table loads correctly when the app first launches. However, after composing and posting a Tweet (confirmed that the Tweet is posted and in the array) the table view is still displaying the same tweets prior without the newly created one. I thought it might have something to do with the asynchronous code so I implemented the DispatchQueue in the refreshData() function. The table view is still not loading the most recently added tweet. How can I change the refreshData() function so that the table updates when Tweet is posted successfully?
import UIKit
import OAuthSwift
class FeedViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var tweetText: UITextField!
var user: User!
var tweets = [Tweet]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
self.tableView.rowHeight = 200
let consumerSecret = user.consumerSecret
let consumerKey = user.consumerKey
let oAuthToken = user.oAuthToken
let oAuthSecret = user.oAuthSecret
let oauthswift = user.oauthswift
let screen_name = user.screen_name
print("Feed Consumer Secret: \(consumerSecret)")
print("Feed Consumer Key: \(consumerKey)")
print("Feed Auth Token: \(oAuthToken)")
print("Feed Auth Secret: \(oAuthSecret)")
print("Screen Name: \(screen_name)")
loadFeed(oauthswift: oauthswift)
// Do any additional setup after loading the view.
}
#IBAction func postButtonPushed(_ sender: Any) {
let oauthswift = user.oauthswift
let url = "https://api.twitter.com/1.1/statuses/update.json?status="
let tweet_url = tweetText.text
let encoded_tweet = tweet_url?.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlHostAllowed)
let new_url = url + encoded_tweet!
let _ = oauthswift.client.post(
new_url, parameters: [:],
success: { response in
let dataString = response.string!
let jsonDict = try? response.jsonObject()
let jsonDict2 = jsonDict as! Dictionary<String,Any>
let tweetText2 = jsonDict2["text"]!
let jsonDict4 = jsonDict2["user"] as! Dictionary<String,Any>
let username = jsonDict4["screen_name"]!
let newTweet = Tweet(tweetText: tweetText2 as! String, username: username as! String)
self.tweets.append(newTweet)
print(username)
//print(dataString)
self.loadFeed(oauthswift: oauthswift)
self.tweetText.text = ""
},
failure: { error in
print(error)
}
)
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let tweet = tweets[indexPath.row]
if let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell") as? PostCell {
cell.configureCell(tweet: tweet)
return cell
} else {
return PostCell()
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tweets.count
}
func loadFeed(oauthswift: OAuth1Swift){
print("LOAD FEED")
let _ = oauthswift.client.get(
"https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=\(user.screen_name)", parameters: [:],
success: { response in
let jsonDict = try? response.jsonObject()
let jsonDict2 = jsonDict as! Array<Dictionary<String,Any>>
let arrayCount = jsonDict2.count
for index in 0...arrayCount - 1 {
let jsonDict4 = jsonDict2[index]["user"] as! Dictionary<String,Any>
let tweetText = jsonDict2[index]["text"]!
let username = jsonDict4["screen_name"]!
let newTweet = Tweet(tweetText: tweetText as! String, username: username as! String)
self.tweets.append(newTweet)
print(tweetText)
}
self.refreshData()
}, failure: { error in
print(error)
}
)
}
func refreshData() {
DispatchQueue.main.async{
self.tableView.reloadData()
}
}
}
PostCell.swift
import UIKit
class PostCell: UITableViewCell {
#IBOutlet weak var userLabel: UILabel!
#IBOutlet weak var tweetLabel: UILabel!
var tweet: Tweet!
func configureCell(tweet: Tweet) {
self.userLabel.text = "#\(tweet.username)"
self.tweetLabel.text = tweet.tweetText
print(tweet.tweetText)
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Since you are sure that Twitter accepted the post and you appended the new Tweet to the data source there is no need for a full reloadData. You can display just the new row in the table.
In FeedViewController, in method postButtonPushed, inside the oauthswift.client.post's success clousure right after this line self.tweets.append(newTweet) add this:
DispatchQueue.main.async {
self.tableView.beginUpdates()
self.tableView.insertRows(at: [IndexPath(item: self.tweets.count-1, section: 0)],
with: .automatic)
self.tableView.endUpdates()
}
Please see screenshot. There is a repliesTableView, replyTextField and replyButtonin ViewController. repliesTableView cell is called ReplyCell. In ReplyCell there is a commentTableView to list all comments for that reply and a textfField, a commentButton to add new comments.
I have problem when add new replies and new comments. I guess I need to make comments array in ReplyCell empty when I click the Reply button. How can I make this happen? I have no idea how to access comments arrayfrom the root ViewController.
Exact problems: fter clicking commentButton, all comments in every cell doubled. After clicking replyButton, comments went to wrong cell.
Code:
import UIKit
import Firebase
class TopicForumVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {
#IBOutlet weak var topicNameLabel: UILabel!
#IBOutlet weak var replyNumberLabel: UILabel!
#IBOutlet weak var repliesTableView: UITableView!
#IBOutlet weak var replyTextField: UITextField!
var topicName:String?
var firstKey:String?
var secondKey:String?
var replies = [String]()
var replyButtonTapped = false
override func viewDidLoad() {
super.viewDidLoad()
repliesTableView.delegate = self
repliesTableView.dataSource = self
replyTextField.delegate = self
}
override func viewDidAppear(_ animated: Bool) {
topicNameLabel.text = self.topicName
loadReplies()
}
func loadReplies() {
self.replies = []
DataService.ds.Categories_Base.child(self.firstKey!).child("Topics").observe(.value, with:{(snapshot) in
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshots {
if let topicDict = snap.value as? Dictionary<String,AnyObject> {
if let topic = topicDict["text"] as? String {
if topic == self.topicName {
self.secondKey = snap.key
UserDefaults.standard.setValue(snap.key, forKey: Key_SecondKey)
if let replyDict = topicDict["replies"] as? Dictionary<String,AnyObject> {
for eachDict in replyDict {
if let textDict = eachDict.value as? Dictionary<String,AnyObject> {
if let reply = textDict["text"] as? String {
self.replies.append(reply)
self.replyNumberLabel.text = String(self.replies.count)
}
}
}
}
}
}
}
}
self.repliesTableView.reloadData()
}
})
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return replies.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "ReplyCell") as? ReplyCell {
let reply = replies[indexPath.row]
cell.configureReplyCell(reply: reply)
return cell
} else {
return UITableViewCell()
}
}
#IBAction func replyButtonTapped(_ sender: Any) {
replyButtonTapped = true
if let reply = replyTextField.text, reply != "" {
self.replies = []
DataService.ds.Categories_Base.child(self.firstKey!).child("Topics").child(self.secondKey!).child("replies").childByAutoId().child("text").setValue(reply)
self.repliesTableView.reloadData()
let i = replies.count
for n in 0..<i {
let indexPath = IndexPath(row: n, section: 1)
let cell = repliesTableView.cellForRow(at: indexPath) as! ReplyCell
cell.comments = []
cell.repliesToReplyTableView.reloadData()
}
self.replyTextField.text = ""
self.replyButtonTapped = false
}
}
}
import UIKit
import Firebase
class ReplyCell: UITableViewCell,UITableViewDataSource,UITableViewDelegate, UITextFieldDelegate {
#IBOutlet weak var replyTextView: UITextView!
#IBOutlet weak var repliesToReplyTableView: UITableView!
#IBOutlet weak var commentTextField: UITextField!
var reply:String?
var comments = [String]()
var replyKey:String?
override func awakeFromNib() {
super.awakeFromNib()
self.comments = []
repliesToReplyTableView.delegate = self
repliesToReplyTableView.dataSource = self
commentTextField.delegate = self
loadComments()
}
func configureReplyCell(reply:String) {
self.reply = reply
self.replyTextView.text = self.reply
}
func loadComments() {
self.comments = []
if let firstKey = UserDefaults.standard.value(forKey: Key_FirstKey) as? String, let secondKey = UserDefaults.standard.value(forKey: Key_SecondKey) as? String {
DataService.ds.Categories_Base.child(firstKey).child("Topics").child(secondKey).child("replies").observe(.value, with:{(snapshot) in
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshots {
if let replyDict = snap.value as? Dictionary<String,AnyObject> {
if let reply = replyDict["text"] as? String {
if reply == self.reply {
self.replyKey = snap.key
DataService.ds.Categories_Base.child(firstKey).child("Topics").child(secondKey).child("replies").child(snap.key).child("comments").observe(.value, with: { (commentSnapshot) in
if let commentSnapshots = commentSnapshot.children.allObjects as? [FIRDataSnapshot] {
for commentSnap in commentSnapshots {
if let commentDict = commentSnap.value as? Dictionary<String,AnyObject> {
if let comment = commentDict["text"] as? String {
self.comments.append(comment)
}
}
}
}
self.repliesToReplyTableView.reloadData()
})
}
}
}
}
}
})
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return comments.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let commentCell = tableView.dequeueReusableCell(withIdentifier:"CommentCell")
commentCell?.textLabel?.text = comments[indexPath.row]
return commentCell!
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
#IBAction func commentBtnPressed(_ sender: Any) {
if let comment = commentTextField.text, comment != "" {
self.comments = []
if let firstKey = UserDefaults.standard.value(forKey: Key_FirstKey) as? String, let secondKey = UserDefaults.standard.value(forKey: Key_SecondKey) as? String {
DataService.ds.Categories_Base.child(firstKey).child("Topics").child(secondKey).child("replies").child(self.replyKey!).child("comments").childByAutoId().child("text").setValue(comment)
if let myViewController = parentViewController as? TopicForumVC {
// myViewController.repliesTableView.reloadData()
myViewController.replies = []
}
self.repliesToReplyTableView.reloadData()
self.commentTextField.text = ""
self.replyKey = ""
}
}
}
I don't really know the exact circumstances of what you're building but there are two ideas that may offer some guidance.
1) If your table is displaying content from a data source then you will likely have some kind of reference. E.g. when loading the cells (in this case CustomCell) you'll do something like get the index of the cell and get the same index from the data, and put that data in the cells content. If that's the case, all you have to do on the button click is use tableview.cellForRowAtIndexPath with your sender object, and then remove the array from the data source, e.g. tableDataSource[index] = nil and reload the tableView.
2) If you have a stored property on the CustomCell that you've add specifically for storing this array, then you'd cast the sender object to CustomCell and remove the property, as in Kim's answer.
Hope this helps, but without more information it's kind of hard to tell.
let cell = tableview.cellForRowAtIndexPath(...) as? CustomCell
if cell != nil {
let arr = cell.array
}
BTW: I would re-think storing your array in the cell..