Parsing multiple images in swift from JSON - ios

Json has multiple images,
img1
Json has date with multiple images, I want show Date and first image of that Date in tableview, working fine.
img2
Note :
when click any cell in tableview, display that Date with all images in collection view, But am parsing only first image of that Date,that image only showing in collection view
how to parse all images from Json and pass to collection view from tableview, and display images into collocation view
img3
this is the code ...
json Code
if errorCode == "0" {
if let Media_list = jsonData["events"] as? [Any] {
self.Mediainfo.removeAll()
for i in 0 ..< Media_list.count {
if let MediaEventData = Media_list[i] as? [String: Any] {
var eventImages = MediaEventData["eventImages"] as? [[String: Any]]
if (eventImages?.count)! > 0 {
let bannerImage = eventImages?[0]["bannerImage"] as? String
print(bannerImage as Any)
self.imageUrl = self.url+"/images/events/" + String(describing: bannerImage!)
self.Mediainfo.append(MediaEvent(
eventId: MediaEventData["eventId"]as?String,
date: MediaEventData["date"]as?String,
eventname: MediaEventData["eventName"]as?String,
bannerImages: self.imageUrl
)
)
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Media", for: indexPath)as! MediaCustomTableViewCell
let row = indexPath.row
let media = Mediainfo[row] as MediaEvent
cell.DisplayDate.text = media.date
cell.DisplayName.text = media.eventName
cell.selectionStyle = .none
cell.DisplayImage.downloadImageFrom(link:media.bannerImages, contentMode: UIViewContentMode.scaleAspectFit)
return cell
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return CGFloat.leastNormalMagnitude
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let media = Mediainfo[(indexPath.row)] as MediaEvent
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "IMAGEVID") as! UITabBarController
if let viewControllers = tabBarController.viewControllers,
let imageController = viewControllers.first as? ImagesCollectionViewController {
imageController.RecivedData1 = media.bannerImages
}
navigationController?.pushViewController(tabBarController, animated: true)
}
collection view Code :
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ImageCollectionViewCell
cell.ImageviewCell.downloadImageFrom(link:nameofImages[indexPath.row], contentMode: UIViewContentMode.scaleAspectFit)
return cell
}
pls help me......!

u can do soemthing like this
let eventImages = MediaEventData["eventImages"] as? [[String: Any]]
if (eventImages?.count)! > 0 {
for i in 0...eventImages.count{
let bannerImage = eventImages?[i]["bannerImage"] as? String
self.imageUrl = self.url+"/images/events/" + String(describing: bannerImage!)
self.Mediainfo.append(bannerImage)
// or like u did u can append to array
self.Mediainfo.append(MediaEvent(
eventId: MediaEventData["eventId"]as?String,
date: MediaEventData["date"]as?String,
eventname: MediaEventData["eventName"]as?String,
bannerImages: self.imageUrl
)
} }
In didselect
let media = Mediainfo[(indexPath.row)] as MediaEvent
imageController.RecivedData1 = media.bannerImages
Your doing like this Means Your are slecting a particular cell and
that index your are passing to NextVC.
if you want to show all images You should pass complete array to
nextvc
You should declare a array of same type Mediainfo array in Next VC
and do like
EX: imageController.array = Mediainfo

Related

how to get main tableview index in nested tableview in swift

I am new in swift and I am not able to get main tableview index on nested tableview button click
my code is like this
extension Section2QuestionsViewController: UITableViewDataSource, UITableViewDelegate
{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrFinancialYears.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let strCellID = "Section2QuestionCell"
var cell = tableView.dequeueReusableCell(withIdentifier: strCellID) as? Section2QuestionCell
if cell == nil
{
tableSection2.register(Section2QuestionCell.self, forCellReuseIdentifier: strCellID)
cell = tableSection2.dequeueReusableCell(withIdentifier: strCellID) as? Section2QuestionCell
}
let dictAppStats = arrFinancialYears[indexPath.row] as? [String:Any]
cell?.lblQuestionTitle.text = "\(indexPath.row + 1). \(dictAppStats?["question"] as? String ?? "")"
cell?.arrCourses = [Any]()
cell?.arrCourses = dictAppStats?["options"] as? [Any] ?? []
cell?.tableInsideHeightConstraints.constant = CGFloat(28 * (cell?.arrCourses.count ?? 0))
cell?.tableInside.reloadData()
return cell!
}
}
Inside tableview
extension Section2QuestionCell: UITableViewDataSource, UITableViewDelegate
{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrCourses.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "InsideSection2QuestionCell", for: indexPath) as! InsideSection2QuestionCell
cell.selectionStyle = .none
let dictFeeStats = arrCourses[indexPath.row] as? [String:Any]
cell.lblOption.text = dictFeeStats?["option_value"] as? String
cell.btnOption.tag = indexPath.item
cell.btnOption.addTarget(self, action: #selector(btnOptionClick), for: .touchUpInside)
cell.lblAnswerKey.text = dictFeeStats?["answer_key"] as? String
cell.lblQuestionId.text = dictFeeStats?["question_id"] as? String
cell.lblAnswerId.text = dictFeeStats?["option_id"] as? String
return cell
}
}
Button Click
#objc func btnOptionClick(_ sender: UIButton)
{
let index = IndexPath(row: sender.tag, section: 0)
let cell: InsideSection2QuestionCell = tableInside.cellForRow(at: index) as! InsideSection2QuestionCell
let QuestionId = cell.lblQuestionId.text
let AnswwerId = cell.lblAnswerId.text
print(QuestionId as Any)
print(AnswwerId as Any)
Globalnewdict = ["option":AnswwerId as Any,"question":QuestionId as Any]
Globalindexvalue = sender.tag
NotificationCenter.default.post(name: Notification.Name(rawValue: "disconnectPaxiSockets"), object: nil)
tableInside.reloadData()
}
I am not able to get main tableview index path value on button. Is there is any way to get main tableview index path value on button click.
Please help
Thanks in Advance!
You could add an index path object in your Section2QuestionCell
var parentTableIndexPath : IndexPath!
Then set the value in cellForRowAt tableview delegate method
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let strCellID = "Section2QuestionCell"
var cell = tableView.dequeueReusableCell(withIdentifier: strCellID) as? Section2QuestionCell
if cell == nil {
tableSection2.register(Section2QuestionCell.self, forCellReuseIdentifier: strCellID)
cell = tableSection2.dequeueReusableCell(withIdentifier: strCellID) as? Section2QuestionCell
}
cell.parentTableIndexPath = indexPath
let dictAppStats = arrFinancialYears[indexPath.row] as? [String:Any]
cell?.lblQuestionTitle.text = "\(indexPath.row + 1). \(dictAppStats?["question"] as? String ?? "")"
cell?.arrCourses = [Any]()
cell?.arrCourses = dictAppStats?["options"] as? [Any] ?? []
cell?.tableInsideHeightConstraints.constant = CGFloat(28 * (cell?.arrCourses.count ?? 0))
cell?.tableInside.reloadData()
return cell!
}
Since btnOptionClick() is in same class, you can directly access the parent table Index path in your button action.
In
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let strCellID = "Section2QuestionCell"
var cell = tableView.dequeueReusableCell(withIdentifier: strCellID) as? Section2QuestionCell
if cell == nil
{
tableSection2.register(Section2QuestionCell.self, forCellReuseIdentifier: strCellID)
cell = tableSection2.dequeueReusableCell(withIdentifier: strCellID) as? Section2QuestionCell
}
let dictAppStats = arrFinancialYears[indexPath.row] as? [String:Any]
cell?.lblQuestionTitle.text = "\(indexPath.row + 1). \(dictAppStats?["question"] as? String ?? "")"
cell?.arrCourses = [Any]()
cell?.arrCourses = dictAppStats?["options"] as? [Any] ?? []
cell?.tableInsideHeightConstraints.constant = CGFloat(28 * (cell?.arrCourses.count ?? 0))
cell?.tableInside.tag = indexPath.row
cell?.tableInside.reloadData()
return cell!
}
In ButtonClick
#objc func btnOptionClick(_ sender: UIButton)
{
let index = IndexPath(row: sender.tag, section: 0)
let cell: InsideSection2QuestionCell = tableInside.cellForRow(at: index) as! InsideSection2QuestionCell
let QuestionId = cell.lblQuestionId.text
let AnswwerId = cell.lblAnswerId.text
print(QuestionId as Any)
print(AnswwerId as Any)
Globalnewdict = ["option":AnswwerId as Any,"question":QuestionId as Any]
Globalindexvalue = tableInside.tag
NotificationCenter.default.post(name: Notification.Name(rawValue: "disconnectPaxiSockets"), object: nil)
tableInside.reloadData()
}
In cellForRowAt I set indexpath.row to tableview.tag.
Then on button click I set tableview.tag to global indexpath.

Order multiple TableViewCell types by TimeStamp

What I want to do:
Order all my TableViewCells from most recent to the oldest.
What is my problem:
I can order Cells from the same type by Time, though I fail at ordering them all in the same section by one common value (the time).
Here is my code:
import UIKit
import Firebase
class popularViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet var table: UITableView!
// var models = [PhotoPost]()
var texttt = [TextPost]()
var phots = [PhotoPost]()
var mixed = [MixedPhoto]()
var switchy = [Any]()
override func viewDidLoad() {
super.viewDidLoad()
gettingPosts()
table.register(popularTableViewCell.nib(), forCellReuseIdentifier: popularTableViewCell.identifier)
table.register(featuredTableViewCell.nib(), forCellReuseIdentifier: featuredTableViewCell.identifier)
table.register(textTableViewCell.nib(), forCellReuseIdentifier: textTableViewCell.identifier)
table.register(mixedTableViewCell.nib(), forCellReuseIdentifier: mixedTableViewCell.identifier)
table.delegate = self
table.dataSource = self
self.table.estimatedRowHeight = 225
self.table.rowHeight = UITableView.automaticDimension
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
}
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0{
return mixed.count
}
else if section == 1{
return phots.count
}
else{
return texttt.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0{
let cell = tableView.dequeueReusableCell(withIdentifier: mixedTableViewCell.identifier, for: indexPath) as! mixedTableViewCell
cell.configure(with: self.mixed[indexPath.row])
return cell
}
else if indexPath.section == 1{
let cell = tableView.dequeueReusableCell(withIdentifier: popularTableViewCell.identifier, for: indexPath) as! popularTableViewCell
cell.configure(with: self.phots[indexPath.row])
return cell
}
else{
let cell = tableView.dequeueReusableCell(withIdentifier: textTableViewCell.identifier, for: indexPath) as! textTableViewCell
cell.configure(with: self.texttt[indexPath.row])
return cell
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "commentsVC")
vc.modalPresentationStyle = .fullScreen
self.navigationController?.pushViewController(vc, animated: true)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func gettingPosts(){
let db = Firestore.firestore()
let postsRef = db.collection("posts")
postsRef.addSnapshotListener { (querySnapshot, error) in
guard let snapshot = querySnapshot else {
print("Error fetching snapshots: \(error!)")
return
}
snapshot.documentChanges.forEach { diff in
if (diff.type == .added){
let data = diff.document.data()
let Name = data["username"] as! String
let text = data["description"]
let likes = data["likes"] as! Int
let typ = data["postType"] as! Int
let pfp = data["profileImage"] as! String
let uid = data["uid"] as! String
let pic = data["picture"]
let time = data["time"] as! String
let pid = data["postID"] as! String
if typ == 0{ // Text post
let dasDing = TextPost(numberOfComments: 0, username: Name, timestampName: time, userImageName: pfp, textName: text as! String, postID: pid)
self.texttt.append(dasDing)
self.texttt.sort(by: { $0.timestampName > $1.timestampName })
}
if typ == 1{ // Text + Picture post
let Mixed = MixedPhoto(numberOfComments: 0, username: Name, timestampName: time, userImageName: pfp, textName: text as! String, postImageName: pic as! String, postID: pid)
self.mixed.append(Mixed)
self.mixed.sort(by: { $0.timestampName > $1.timestampName })
}
if typ == 2{ // Picture Post
let Foto = PhotoPost(numberOfComments: 0, username: Name, timestampName: time, userImageName: pfp, postImageName: pic as! String, postID: pid)
self.phots.append(Foto)
self.phots.sort(by: { $0.timestampName > $1.timestampName })
}
if typ == 3{ // Text + Video Post
}
if typ == 4{ // Video Post
}
}
}
self.table.reloadData()
}
}
}
struct PhotoPost {
let numberOfComments: Int
let username: String
let timestampName: String
let userImageName: String
let postImageName: String
let postID: String
}
struct TextPost {
let numberOfComments: Int
let username: String
let timestampName: String
let userImageName: String
let textName: String
let postID: String
}
struct MixedPhoto {
let numberOfComments: Int
let username: String
let timestampName: String
let userImageName: String
let textName: String
let postImageName: String
let postID: String
}
Note
Right now I ordered every Cell type in its own section to be able to display them all, but this isnt a long-term solution for me. I want to have them all in only one section.
Here is another solution:
After reading Paul & Rikh's answer, I thought about this other solution.
You can have one Post model defined as follows:
struct Post {
let numberOfComments: Int
let username: String
let timestampName: String
let userImageName: String
let postImageName: String?
let textName: String?
let postID: String
}
Notice how postImageName and textName are both optionals. That will help you distinguish among post types.
Next, you want to declare a variable allPosts of type [Post]:
var allPosts = [Post]()
And you need to feed it to your tableView:
func numberOfSections(in tableView: UITableView) -> Int {
return 1 // You only need one section. You can't omit this function btw.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return allPosts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let post = allPosts[indexPath.row]
if post.postImageName != nil && post.textName != nil {
let cell = tableView.dequeueReusableCell(withIdentifier: mixedTableViewCell.identifier, for: indexPath) as! mixedTableViewCell
cell.configure(with: post)
return cell
}
else if post.postImageName != nil {
let cell = tableView.dequeueReusableCell(withIdentifier: popularTableViewCell.identifier, for: indexPath) as! popularTableViewCell
cell.configure(with: post)
return cell
}
else if post.textName != nil {
let cell = tableView.dequeueReusableCell(withIdentifier: textTableViewCell.identifier, for: indexPath) as! textTableViewCell
cell.configure(with: post)
return cell
}
return UITableViewCell() // default: return empty cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "commentsVC")
vc.modalPresentationStyle = .fullScreen
self.navigationController?.pushViewController(vc, animated: true)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
Finally, inside your gettingPosts function, you can assign each item to allPosts, and before reloading your tableView, you can sort allPosts by timestamp (and don't forget to call reloadData from the main thread):
self.allPosts.sort(by: { $0.timestampName > $1.timestampName })
DispatchQueue.main.async {
self.tableView.reloadData()
}
EDIT: Inside your gettingPosts function you need to feed the values to your Post struct rather than the previous model you had.
let post = Post(numberOfComments: 0, username: Name, timestampName: time, userImageName: pfp, textName: text as? String, postImageName: pic as? String, postID: pid)
self.allPosts.append(dasDing)
One more remark: there has to be a better way to do this. Why not decode your JSON instead? This can become messy if you got several types of posts. If you post your JSON structure, maybe we can help you figure out a better solution.
You can do that, but you have to declare an array allPosts of type Any:
var allPosts = [Any]()
And you need to feed it to your tableView:
func numberOfSections(in tableView: UITableView) -> Int {
return 1 // You only need one section. You can't omit this function btw.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return allPosts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let mixedPhoto = allPosts[indexPath.row] as? MixedPhoto {
let cell = tableView.dequeueReusableCell(withIdentifier: mixedTableViewCell.identifier, for: indexPath) as! mixedTableViewCell
cell.configure(with: mixedPhoto)
return cell
}
else if let photoPost = allPosts[indexPath.row] as? PhotoPost {
let cell = tableView.dequeueReusableCell(withIdentifier: popularTableViewCell.identifier, for: indexPath) as! popularTableViewCell
cell.configure(with: photoPost)
return cell
}
else if let textPost = allPosts[indexPath.row] as? TextPost {
let cell = tableView.dequeueReusableCell(withIdentifier: textTableViewCell.identifier, for: indexPath) as! textTableViewCell
cell.configure(with: textPost)
return cell
}
return UITableViewCell() // default: return empty cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "commentsVC")
vc.modalPresentationStyle = .fullScreen
self.navigationController?.pushViewController(vc, animated: true)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
Finally, inside your gettingPosts function, you can assign each item to allPosts since it is of type any, and before reloading your tableView, you can sort allPosts by timestamp (and don't forget to call reloadData from the main thread):
self.allPosts.sort(by: { $0.timestampName > $1.timestampName })
DispatchQueue.main.async {
self.tableView.reloadData()
}
You have three different lists maintained. To order all of them, you will have to combine them in one list. Now all of your models have majority of the data common. You can combine them into one protocol and have all your subsequent models conform to that protocol. Something like this:
protocol Post{
var numberOfComments: Int { get set }
var username: String {get set}
var timestampName: String {get set}
var userImageName: String {get set}
}
struct PhotoPost : Post{
var numberOfComments: Int
var username: String
var timestampName: String
var userImageName: String
let postImageName: String
let postID: String
}
struct TextPost : Post { ... }
struct MixedPhoto : Post { ... }
And inside your UIViewController you should have one list.
var oneListToRuleThemAll = [Post]()
func gettingPosts(){
snapshot.documentChanges.forEach{
//blah blah blah
oneListToRuleThemAll.append(PhotoPost(...))
}
//sort by timestamp and reload the table!
}
Or as Paul suggests in his comment, you can go the class (inheritance) route too! To avoid having to write the variables again inside each subclass (But you cannot use structs with that and will have to change everything to classes).

Tapped cell in UITableView returns label text from last cell out of an array not the chosen one

I have fixed my earlier problem and have now worked out where the main problem is, I am pulling in a json array with alamofire but am not sure how to properly move the data from one viewcontroller to another. If I hardcode the array with var name = ["Hello", "Goodbye"] I can get it to work but am not sure how to do it with the json. Thank you to any and all help.
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let URL_GET_DATA = "http://www.localnewsplus.com.au/ios/service.php"
#IBOutlet weak var tableViewHeroes: UITableView!
var heroes = [Hero]()
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return heroes.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ViewControllerTableViewCell
let hero: Hero
hero = heroes[indexPath.row]
cell.labelName.text = hero.name
cell.labelTeam.text = hero.team
Alamofire.request(hero.imageUrl!).responseImage { response in
if let image = response.result.value {
cell.heroImage.image = image
}
}
//cell.labelName.text = name[indexPath.row]
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
Alamofire.request(URL_GET_DATA).responseJSON { response in
if let json = response.result.value {
let heroesArray : NSArray = json as! NSArray
for i in 0..<heroesArray.count{
self.heroes.append(Hero(
name: (heroesArray[i] as AnyObject).value(forKey: "st_heading") as? String,
team: (heroesArray[i] as AnyObject).value(forKey: "st_modified") as? String,
imageUrl: (heroesArray[i] as AnyObject).value(forKey: "imageurl") as? String
))
}
self.tableViewHeroes.reloadData()
}
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = storyboard?.instantiateViewController(withIdentifier: "articleViewController") as? articleViewController
vc?.article_st_heading = name[indexPath.row]
self.navigationController?.pushViewController(vc!, animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
There are 2 ways to do this
Try to get data from the array which you used in cellForRow to populate data
Let text = someArray[indexPath. Row]
Get the cell instead of the create new one in didSelect method
Let cell = table. CellForRowAt[indexPath ]
Let text = cell.text

Issue with passing proper image to tableviewcell

This is my struct...
struct ProductImage {
let id : String
let url : URL
let isDefault : Bool
}
struct Product {
let name : String
let id : String
var images = [ProductImage]()
init(name : String, id: String) {
self.name = name
self.id = id
}
mutating func add(image: ProductImage) {
images.append(image)
}
}
Now I have an image loaded on the collectionview and on the click of a button, I want to pass this image to a tableviewcell. The collectionview does have a couple of labels with name and id which is passed successfully...But how the image can be passed that I'm not able to figure out. Below is what happens so far on the click of the sell button...
func SellBtnTapped(_ sender: UIButton) {
let indexPath = collectionView?.indexPath(for: ((sender.superview?.superview) as! RecipeCollectionViewCell))
let myVC = storyboard?.instantiateViewController(withIdentifier: "productSellIdentifier") as! sellTableViewController
let productObject = productData1[(indexPath?.row)!]
if selectedItems == nil {
//selectedItems is an array which will hold all struct items.
selectedItems = [Product(name:productObject.name, id: productObject.id)]
} else {
selectedItems?.append(productObject)
}
myVC.arrProduct = selectedItems
navigationController?.pushViewController(myVC, animated: true)
}
This is how I'm assigning the images and other data in the tableviewcell. This is the code of cellForRow..(of the tableview from where the cells are loaded..)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: sellTableViewCell = tableView.dequeueReusableCell(withIdentifier: "sellProductIdentifier") as! sellTableViewCell
//cell.prdImgView?.image =.... by doing this, the images are displayed in the tableviewcell in the same order as they are displayed in the collectionview cells irresoective of which cell was clicked. i.e clicking on btn on 1st collection view item shows the image on that collection view item on the tableviewcell.And when I click on the btn on the 4th collectionview item the image shown on the tableview cell will be that of the 2nd collectionview item...
cell.prdImgView?.image = self.appDelegate.commonArrayForURLImages[indexPath.row]
let product = arrProduct?[indexPath.row]
cell.produvtNameLabel.text = product?.name
cell.rateTextField.text = product?.theRate
return cell
}
This is how the array(which is passed to the tableview cell) gets the images...
var theProduct = Product(name: name, id: id, theRate: rate, quantity: qty, sku: skuCode, prdCateg: prodCat, prodDescr: description)
if let images1 = anItem["product_images"] as? [[String:String]] {
for image in images1 {
guard let imageId = image["id"],
let url1 = image["image"],
let isDefault = image["is_default"] else { continue }
let productImage = ProductImage(id: imageId, url: URL(string: url1)!, isDefault: isDefault == "1")
theProduct.add(image: productImage)
self.productData1.append(theProduct)
self.imgData.append(productImage)
let url = URL(string: url1)
if let data = try? Data(contentsOf: url!) {
let img = UIImage(data: data)
print(img!)
self.arrayOfURLImages.append(img!)
}
self.appDelegate.commonArrayForURLImages = self.arrayOfURLImages
}
}
Structs provide you with member wise initialiser, so in most cases you don't need one of your own.In your code your product initialiser is only holding name and id, and not array of productImage, You seem to be having a separate function for holding that data, which i think is not needed here.So what I did is just created a array type for [ProductImages] and sticked with default initialiser.
import Foundation
struct ProductImage {
let id : String?
let url : String? // Keep this string
let isDefault : Bool?
}
struct Product {
let name : String?
let id. : String?
var images : [ProductImage]?
}
ControllerClass(with collection view getting initial data)-:
In your controller class I created 2 arrays -:
1) That holds data for images .
2) That holds data for entire product information.
For saving data I am just passing constant values for now. In viewDidLoad I called initialiser for each object -:
1) Holding images object data.
2) ProductObject data .
3) Append both object to appropriate arrays.
import UIKit
class MyViewController: UIViewController {
#IBOutlet weak var mainCollectionView: UICollectionView!
// ARRAY OBJECT OF TYPE PRODUCT AND PRODUCT IMAGE
var imageData = [ProductImage]()
var productData = [Product]()
//viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
modelDataForCollectionView()
}
func modelDataForCollectionView(){
// GET IMAGE DATA
let imageObject = ProductImage(id: "1", url: "your url", isDefault: true)
imageData.append(imageObject)
// MODEL FOR PRODUCTS
let productObject = Product(name: "", id: "", images: imageData)
productData.append(productObject)
}
//didReceiveMemoryWarning
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
// MyViewController extending collection view
extension MyViewController :UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{
//numberOfItemsInSection
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{
return productData.count
}
//dequeueReusableCell
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionCell
cell.sendButton.addTarget(self, action: #selector(sendDataToTable), for: UIControlEvents.touchUpInside)
return cell
}
//numberOfSections
func numberOfSections(in collectionView: UICollectionView) -> Int{
return 1
}
// sizeForItemAt for each row
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
return CGSize(width: view.frame.width, height: 200)
}
func sendDataToTable(sender:UIButton){
let index = mainCollectionView.indexPath(for: sender.superview?.superview as! CollectionCell)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let Controller = storyboard.instantiateViewController(withIdentifier: "tableData") as! ViewController1
Controller.dataForTableView = productData[(index?.row)!].images
self.navigationController?.pushViewController(Controller, animated: true)
}
}
Now when you tap on a button in UICollectionViewCell , get the tapped index , and read product object present at that index from Product array.After that you can easily pass required data to table view(Second class).
Second controller class-:
import UIKit
class ViewController1: UIViewController {
// ARRAY TO HOLD IMAGE DATA FOR TAPPED COLLECTION CELL
var dataForTableView:[ProductImage]?
var name : String?
var id : String?
#IBOutlet weak var secondTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// CHECK FOR DATA
print(dataForTableView?[0].url as Any) // Optional("your url")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController1 : UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1") as! testingCell2
return cell
}
// Number of sections in table
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}// Default is 1 if not implemented
public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{
return 50
}
}
Once you get image URL and any other required information in second class, you can present that on table easily. To get images make api call to server. I hope that helps you.
Code for parsing-:
var imageUrl:String?
var imageId:String?
var isDefaults:String?
var productId:String?
var productIdTitle:String?
var productIdImageWithPath:String?
//MARK : Call Back Delegate Methods
func apiSuccessResponse(_ response: Dictionary<String, AnyObject>) {
print(response)
if let actualStyleData = response["Productdata"] as? [Dictionary<String, AnyObject>]{
for object in actualStyleData{
if let id = object["product_id"] as? String{
productId = id
}else{
productId = ""
}
if let title = object["product_name"] as? String{
productIdTitle = title
}
if let imageDetails = object["product_images"] as? [Dictionary<String, AnyObject>]{
for details in imageDetails{
if let id = details["id"] as? String{
imageId = id
}
if let url = details["image"] as? String{
imageUrl = url
}
if let isDefault = details["is_default"] as? String{
isDefaults = isDefault
}
let saveImageObject = ProductImage(id: imageId, url: imageUrl, isDefault: isDefaults)
imageData.append(saveImageObject)
}
}
let saveProductObject = Product(name: productIdTitle, id: productId, images: imageData)
productData.append(saveProductObject)
}
}
}

How to display dynamically data from Server in CollectionViewCell in TableViewCell with swift3?

I got my json link data from TableViewCell , and then retrieve that data from server and display in collectionView with related TableViewCell data.
How to display this data in swift3? Please, help me.
I got url link (mainThemeList.main_associated_url,main_name) from TableViewCell.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let mainThemeList = mainHomeThemeTable[(indexPath as NSIndexPath).row]
let cell = tableView.dequeueReusableCell(withIdentifier: "homecell") as! HomeCategoryRowCell
DispatchQueue.main.async {
cell.categoryTitle.text = mainThemeList.main_name
cell.mainAssociatedURL.text = mainThemeList.main_associated_url
self.prefs.set(mainThemeList.main_name, forKey: "main_name")
cell.categoryTitle.font = UIFont.boldSystemFont(ofSize: 17.0)
cell.collectionView.reloadData()
}
DispatchQueue.main.async {
self.retrieveDataFromServer(associated_url: mainThemeList.main_associated_url,main_name: mainThemeList.main_name)
}
return cell
}
And then data related url link data from Server.
private func retrieveDataFromServe(associated_url : String , main_name: String) {
SwiftLoading().showLoading()
if Reachability().isInternetAvailable() == true {
self.rest.auth(auth: prefs.value(forKey: "access_token") as! String!)
rest.get(url: StringResource().mainURL + associated_url , parma: [ "show_min": "true" ], finished: {(result : NSDictionary, status : Int) -> Void in
self.assetsTable.removeAll()
if(status == 200){
let data = result["data"] as! NSArray
if (data.count>0){
for item in 0...(data.count) - 1 {
let themes : AnyObject = data[item] as AnyObject
let created = themes["created"] as! String
let assets_id = themes["id"] as! Int
let name = themes["name"] as! String
var poster_img_url = themes["poster_image_url"] as! String
let provider_id = themes["provider_id"] as! Int
poster_img_url = StringResource().posterURL + poster_img_url
self.assetsTable.append(AssetsTableItem(main_name: main_name,created: created,assets_id: assets_id, name: name, poster_image_url: poster_img_url,provider_id: provider_id))
}
}
SwiftLoading().hideLoading()
}else{
SwiftLoading().hideLoading()
}
})
}
}
Retrieve data from Server data store in assetsTable.
And then assetsTable data display in CollectionViewCell.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "videoCell", for: indexPath) as! HomeVideoCell
cell.movieTitle.text = list.name
cell.imageView.image = list.image
return cell
}
My problem is collectionViewCell data are duplicate with previous assetsTable data and didn't show correct data in CollectionView.
My tableViewCell show (Action, Drama) label and My CollectionViewCell show movies Name and Movie Image. I retrieve data for CollectionViewCell from server but CollectionViewCell didn't display related data.
in HomeVideoCell Subclass clean up data in prepareforreuse
override func prepareForReuse() {
super.prepareForReuse()
self.movieTitle.text = ""
self.imageView.image = nil
}

Resources