I want to add eCommerce Homepage functionality to my app
Like Horizontal CollectionView(Slider) for each featured, special and selected category. I have implemented a special and featured category with slider but don't know how to add/handle dynamic data for other category collectionview ??
What i have..
var FeaturedProduct = [SubcatItemModel]()
var SpecialProduct = [SubcatItemModel]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.selectedProductForCart = self.products[indexPath.row].productId
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryTableViewCell") as! CategoryTableViewCell
if(indexPath.row == 0){
//getFeaturedProduct()
cell.MyheaderName.text = "FEATURED PRODUCTS"
}
cell.cCollectionView.layer.backgroundColor = UIColor.paleGrey.cgColor
cell.cCollectionView.tag = indexPath.row
cell.cCollectionView.reloadData()
print(String(cell.cCollectionView.tag))
if(indexPath.row == 1){
self.special = 1
}else{
self.special = 0
}
return cell
}
//For CollectionView
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if(collectionView.tag == 0){
return self.subcatModel.count
}else if(collectionView.tag == 1){
return self.SpecialProduct.count
}else{
return 2 //here is i want dynamic collectionview item for category products
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell : RelatedCell = collectionView.dequeueReusableCell(withReuseIdentifier: "RelatedProducts", for: indexPath) as! RelatedCell
let item = self.RelatedProduct[indexPath.row]
cell.ProductName.text = item.name
let modifiedUrl = item.image.replace(target: " ", withString:"%20")
let urlll = URL(string:modifiedUrl)
cell.productImage.kf.setImage(with: urlll, placeholder: UIImage(named: "noImagePlaceholder"))
cell.ProductPrice.text = item.price
return cell
}
Note: Other tutorial returning static collectionview size that i want dynamic.
Please Help....this problem makes me cry
Related
I'm asking for your help because I blocked with something in my Swift App.
I would like to parse an array with some meals.
My array is the next one:
let meals_list: [[String]] = [
["breakfast", "snack_1", "pre_intra_post", "lunch", "snack_2", "diner"],
["breakfast", "snack_1", "lunch", "snack_2", "diner"]
]
As you can see, there are 6 items in the first part, and 5 items in the second one.
These meals are going to be displayed in a horizontal CollectionView.
Each CollectionView needs to be in a table view.
So, I would like to create 6 cards in my first collection view
And 5 cards in my second collection view.
Here is how I manage everything
//Manage meals content
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if section == 0{
return 6
} else {
return 5
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collection_cell", for: indexPath) as! Meal_vc_cell
return cell
}
//Manage day type content (train/rest)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "food_plan_cell", for: indexPath) as! FoodPlanCell
if (indexPath.row == 0){
cell.meals_day_type.text = "Vos repas les\r\njours d'entraƮnement".uppercased()
} else {
cell.meals_day_type.text = "Vos repas les\r\njours de Repos".uppercased()
}
return cell
}
private func tableView(tableView: UITableView,
willDisplayCell cell: UITableViewCell,
forRowAtIndexPath indexPath: NSIndexPath) {
guard let tableViewCell = cell as? FoodPlanCell else { return }
tableViewCell.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, forRow: indexPath.row)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collection_cell", for: indexPath) as! Meal_vc_cell
cell.meal.text = meals_list.[indexPath.section][indexPath.item]
return cell
}
I want to show image using sdWebImage to an image inside collectionView Cell which is inside tableView cell. How to do it ?
I have array of images and I want to show it in collection view cell
this is what I tried
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let imgUrl = (myArray[indexPath.row] as? String)
{
//myArray = image array
if let url = URL(string: imgUrl as! String) {
cell.imgView.sd_setImage(with: url, placeholderImage: UIImage(named: "product.png"), options: .lowPriority)
}
}
}
I already set
func setCollectionViewDataSourceDelegate(dataSourceDelegate: UICollectionViewDataSource & UICollectionViewDelegate, forRow row: Int) {
collectionVIew.delegate = dataSourceDelegate
collectionVIew.dataSource = dataSourceDelegate
collectionVIew.tag = row
collectionVIew.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DashboardTableViewCell") as! DashboardTableViewCell
cell.delegate = self
cell.selectedIP = indexPath
cell.collectionVIew.tag = indexPath.row
cell.collectionVIew.reloadData()
return cell
}
But I don't know how to show images inside collection view in particular tableview section.
Please Help.
Set Collection view Deleagte and dataSource inside the table view cellforRow method
collectionview.delegae = self
collectionview.datasource = self
As mention by #AjinkyaSharma You have to rearrange your data structure, where it would be an array of arrays.
let myImages: [[String]] = [
["image_url_0_0", "image_url_0_1", "image_url_0_2", "image_url_0_3"],
["image_url_1_0", "image_url_1_1", "image_url_1_2"],
["image_url_2_0", "image_url_2_1", "image_url_2_2", "image_url_2_3", "image_url_2_4"],
["image_url_3_0", "image_url_3_1"]
]
Now you tableview cellForRowAt will set the required array of images for collectionView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myImages.size
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DashboardTableViewCell") as! DashboardTableViewCell
cell.delegate = self
cell.selectedIP = indexPath
cell.collectionVIew.tag = indexPath.row
cell.myArray = myImages[indexPath.row]
cell.collectionVIew.reloadData()
return cell
}
Now you need to use your myArray array to display your collectionView cells
One of your url is not able to satisfy if let condition. Set default image to nil to make sure not to show any previous data.
Try This:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
cell.imgView.image = nil // set default image nil
if let imgUrl = (myArray[indexPath.row] as? String)
{
//myArray = image array
if let url = URL(string: imgUrl as! String) {
cell.imgView.sd_setImage(with: url, placeholderImage: UIImage(named: "product.png"), options: .lowPriority)
}
}
}
Try With Below Code
class YourCustomizeTableViewCell: UITableViewCell {
let collectionView: CollectionView
...
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HorizontalSlideCell", for: indexPath) as! YourCustomizeTableViewCell
cell.collectionView.tag = indexPath.row
return cell
}
...
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "InnerCollectionViewCell",
for: indexPath as IndexPath)
//indexPath.section is the collectionview section index but needs to be its parent tableview section's index. How do I get it?
cellCharLabel?.text =
Languages.sharedInstance.alphabets[collectionView.tag].set[indexPath.row].char
...
return cell
}
func setCollectionViewDataSourceDelegate<D:UICollectionViewDataSource & UICollectionViewDelegate>(datasourcedelegate : D, forRow row:Int){
collectionVIew.delegate = datasourcedelegate
collectionVIew.dataSource = datasourcedelegate
collectionVIew.tag = row
collectionVIew.isPagingEnabled = row == 0 ? false : true
collectionVIew.accessibilityHint = row == 0 ? "category" : "offers"
collectionVIew.reloadData()
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
guard let cell = cell as? DashboardTableViewCell else {
return
}
cell.setCollectionViewDataSourceDelegate(datasourcedelegate: self, forRow: indexPath.section)
}
extension HomeViewController : UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return array.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PopularCollectionViewCell.identifier, for: indexPath) as? PopularCollectionViewCell else {
return UICollectionViewCell()
}
cell.backgroundColor = .clear
cell.setValue(data: popularItemList[indexPath.row])
return cell
}
}
extension HomeViewController : UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width:120, height: itemWidth + 82)
}
}
I'm trying to embed a UITableView into a UICollectionViewCell. I'm managing to get everything to load. However, when it does load it up it seems to randomly use the last loaded value for the UITableView List Items. My DebugPrint Output seems to load all of the CollectionViewCells before even referencing the TableView. Once the CollectionViewCells are set, then it populates the TableView with whatever value it is left with. How can I resolve this so that I'm using the correct values? I suspect it is something to how I'm using IndexPath however I'm fairly new to Swift.
Populating UICollectionView
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: releaseIdentifier, for: indexPath) as! ReleaseCollectionViewCell
let vid: VideoItem
vid = Video[indexPath.item]
let rating = vid.Rating
let denominator = 2.0
let roundedRating = round(rating*denominator )/denominator
if vid.SiteVideoID != 0 {
cell.ReleaseImage.setImageFromURl(stringImageUrl: "\(file.BaseURL)/sitePictures/\(GetFilePath(ID: String(vid.SiteVideoID)))/\(String(vid.SiteVideoID)).jpg")
} else {
cell.ReleaseImage.setImageFromURl(stringImageUrl: "\(file.BaseURL)/pictures/\(GetFilePath(ID: String(vid.VideoID)))/\(String(vid.VideoID))_001.png")
}
cell.ReleaseDate.text = vid.ReleaseDate
cell.ReleaseTitle.text = vid.Title
cell.SiteLogo.setImageFromURl(stringImageUrl: "\(file.BaseURL)/siteLogos/" + String(vid.SiteID) + ".png")
if vid.VideoID == 0 {
cell.ReleaseImage.alpha = 0.5
} else {
cell.ReleaseImage.alpha = 1.0
}
indexPathItem = -1
indexPathItem = indexPath.item
debugPrint(indexPathItem)
cell.TagsView.delegate = self
cell.TagsView.dataSource = self
return cell
}
and for populating the TableView
extension MiscCollectionViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if indexPathItem != -1 {
return Video[indexPathItem].Tags.count
} else {
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let tags = tableView.dequeueReusableCell(withIdentifier: "Tag", for: indexPath) as! TagTableViewCell
debugPrint(String(indexPathItem) + " " + Video[indexPathItem].Tags[indexPath.row])
tags.TagLabel.text = String(indexPathItem) //Video[indexPathItem].Tags[indexPath.row]
return tags
}
}
I am currently using two prototype cells to have my collectionView in top cell moving horizontally while all other cells moves vertical. It's still short one cell count at the bottom and I can't seem to figure out why.
This is the code. Can you point out where the issue is please?
//Mark:- Data arrays
var dataArray: [String] = ["c1","c2","c3","c4","c5"]
var cellArray: [String] = ["10","11","12","13","14","15"]
//Mark:- UITableView Delegate
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "MainTableViewCell") as! MainTableViewCell
return cell
} else {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell") as! CustomTableViewCell
cell2.cellImage.image = UIImage(named: cellArray[indexPath.row])
return cell2
}
}
//Mark:- UICollectionView Delegate
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return dataArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "InsideCollectionViewCell", for: indexPath) as! InsideCollectionViewCell
cell.myImage.image = UIImage(named: dataArray[indexPath.row])
return cell
}
It seems you want your table view to contain the values in your cellArray array plus one extra special row at index 0.
In order to do this you need to indicate that there is an extra row and your indexing needs to account for the extra row.
But a simpler approach is to use multiple sections in your table view. Use section 0 for the extra special row and use section 1 for the values in your cellArray.
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return section == 0 ? 1 : cellArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "MainTableViewCell") as! MainTableViewCell
return cell
} else {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell") as! CustomTableViewCell
cell2.cellImage.image = UIImage(named: cellArray[indexPath.row])
return cell2
}
}
Make sure you adjust for the use of multiple sections in any other table view method you may implement (such as didSelectRowAt, etc.).
For the sake of comparison, here is how you would need to change your code if you want all of the rows in one section:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellArray.count + 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "MainTableViewCell") as! MainTableViewCell
return cell
} else {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell") as! CustomTableViewCell
cell2.cellImage.image = UIImage(named: cellArray[indexPath.row - 1])
return cell2
}
}
Image 1:
I have a collection view and a table view in the same view controller. I want to update the data of my table view, based on the selected item in the collection view. So every time I click on any item of the collectionView, my tableView data should update.
My code:
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
for superSkill in skills!{
if superSkill.name == (skills?[indexPath.row].name)! {
childSkills = superSkill.skills!
}
}
DispatchQueue.main.async{
self.childSkillTableView.reloadData()
}
}
Is there any way i can achieve it
First thing is to make sure your childSkillTableView.dataSource = self and your superSkillsCollectionView.delegate = self
The second thing, there's no reason to use DispatchQueue.main.async({})
The third thing, though less important, instead of a for loop, you might use something like:
childSkills = skills?.first(where { superSkill in superSkill.name == (skills?[indexPath.row].name)! }
Though you should use some if let or guard let statements to check for optionals instead of force unwrapping.
extension PerformanceVC: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return skills.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "superSkillCell", for: indexPath) as! SuperSkillCell
cell.superSkillName.text = skills[indexPath.row].name
//loading image async
ImageAsyncLoader.loadImageAsync(url: (skills[indexPath.row].imageURL)!, imgView: cell.superSkillImage)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
return CGSize(width: skillCollections.frame.height * 0.9, height: skillCollections.frame.height) //use height whatever you wants.
}
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print((skills[indexPath.row].name)!)
for skill in skills{
if skill.name == (skills[indexPath.row].name)! {
childSkills = skill.skills!
}
}
self.subSkillTableView.reloadData()
}
}
extension PerformanceVC: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let openViewHeight: Int = 55
if (indexPath.row == selectedRowIndex.row && isExpanded == false){
isExpanded = true
return CGFloat(openViewHeight + 36 * (childSkills[indexPath.row].skills?.count)!)
} else if (indexPath.row == selectedRowIndex.row && isExpanded == true){
isExpanded = false
return CGFloat(openViewHeight)
} else {
isExpanded = false
return CGFloat(openViewHeight)
}
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return childSkills.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(childSkills[indexPath.row].name)
selectedRowIndex = indexPath
tableView.beginUpdates()
//let cell = tableView.dequeueReusableCell(withIdentifier: "SubSkillTableCell", for: indexPath) as! SubSkillTableCell
let cell = tableView.cellForRow(at: indexPath) as! SubSkillTableCell
for subview in cell.grandSkillStack.subviews {
subview.removeFromSuperview()
}
var grandSkillView: GrandChildSkillItem
grandChildSkills = (childSkills[indexPath.row].skills)!
for grandchildskill in grandChildSkills {
grandSkillView = GrandChildSkillItem(frame: CGRect(x: 0, y: 0, width: 300, height: 30))
grandSkillView.grandChildSkillNameLabel.text = grandchildskill.name
grandSkillView.grandChildSkillProgress.progress = Float(grandchildskill.percentage!)
cell.grandSkillStack.addArrangedSubview(grandSkillView)
}
tableView.endUpdates()
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//tableView.separatorStyle = .none
tableView.showsVerticalScrollIndicator = false
let cell = tableView.dequeueReusableCell(withIdentifier: "SubSkillTableCell", for: indexPath) as! SubSkillTableCell
cell.subSkillName.text = childSkills[indexPath.row].name
cell.subSkillProgress.progress = Float(childSkills[indexPath.row].percentage!)
if let uPoints = childSkills[indexPath.row].userPoints {
if let tPoints = childSkills[indexPath.row].totalPoints {
if let count = childSkills[indexPath.row].skills?.count {
cell.subSkillDetail.text = "\(uPoints)" + "/" + "\(tPoints)" + "XP \u{2022} " + "\(count)" + " subskills"
}
}
}
return cell
}
}