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)
}
}
}