uicollectionview not showing cells swift - ios

I got my data from a url as json string. in my codes, titles variable is an array of my url images.
private let reuseIdentifier = "cell_supporters"
class SupportersCollectionViewController: UICollectionViewController {
var ids = [String]()
var titles = [String]()
#IBOutlet var collection_supporters: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collection_supporters.delegate = self
// Register cell classes
self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
getSupporters()
}
// MARK: UICollectionViewDataSource
// override func numberOfSections(in collectionView: UICollectionView) -> Int {
// // #warning Incomplete implementation, return the number of sections
// return 1
// }
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return self.titles.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! SupportersCollectionViewCell
print("Hello collectionView")
let url_img = URL(string: self.titles[indexPath.row])!
print(url_img)
cell.img_logo.af_setImage(
withURL: url_img
)
return cell
}
func getSupporters() {
RestApiManager.sharedInstance.getSupporters { (json: JSON) in
if let results = json.array {
for entry in results {
// print(entry["title"])
//self.ids.append(entry["id"].string!)
self.titles.append(entry["title"].string!)
}
print(self.titles.count)
DispatchQueue.main.async{
self.collection_supporters.reloadData()
}
}
}
}
}
in my code :
print(self.titles.count) // it shows 5
but:
print("Hello collectionView") // not show anything !

If you're using the default UICollectionViewFlowLayout class for the layout you can try implementing the delegate method that returns the size of each item in the collectionView. The UICollectionView doesn't call the cellForItemAt dataSource method at all if it doesn't have the size information or if they're zero.
Try adding this:
extension SupportersCollectionViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 40, height: 40) // Return any non-zero size here
}
}

Dont register cell classes. Delete following line from viewDidLoad function :
self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)

Add this line in your ViewDidLoad() method:
self.collectionView!.delegate = self

Change it to this:
private let reuseIdentifier = "cell_supporters"
class SupportersCollectionViewController: UICollectionViewController {
var ids = [String]()
var titles = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Register cell classes
self.collectionView!.register(SupportersCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
getSupporters()
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return self.titles.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! SupportersCollectionViewCell
print("Hello collectionView")
let url_img = URL(string: self.titles[indexPath.row])!
print(url_img)
cell.img_logo.af_setImage(
withURL: url_img
)
return cell
}
func getSupporters() {
RestApiManager.sharedInstance.getSupporters { (json: JSON) in
if let results = json.array {
for entry in results {
// print(entry["title"])
//self.ids.append(entry["id"].string!)
self.titles.append(entry["title"].string!)
}
print(self.titles.count)
DispatchQueue.main.async{
self.collectionView!.reloadData()
}
}
}
}
}
First, you don't required this:
#IBOutlet var collection_supporters: UICollectionView!
Because your view controller is inherited from UICollectionViewController
Also I changed the register of the UICollectionViewCell class to this so it won't crash when you the cells are created:
self.collectionView!.register(SupportersCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)

Related

want to add a collectionView inside tableView by downloading data from firebase to show . ios App Swift

want to add a UICollectionView inside UITableView by downloading data from firebase to show
Now I'm done with the interface part, but I'm stuck in the problem, can't bring data from firebase to show in the UICollectionView.
I can't run collectionView.reloadData() because the UICollectionView is different in class, how should I fix it?
func showImageRewardData(rewardID:String) {
let databaseRef = Database.database().reference().child("reward").child(rewardID).child("rewardImage")
databaseRef.observe(DataEventType.value, with: { (Snapshot) in
if Snapshot.childrenCount>0{
self.rewardDataArr.removeAll()
for rewardImage in Snapshot.children.allObjects as! [DataSnapshot]{
let rewardObject = rewardImage.value as? [String: AnyObject]
if(rewardObject?["imageURL"] != nil){
let imageUrl = rewardObject?["imageURL"]
let Data = rewardDetailClass(rewardImage: imageUrl as? String)
self.rewardDataArr.insert(Data, at: 0)
}
YOURVIEWCONTROLLER.SWIFT
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let CellIdentifier: String = "Cell_NotesList"
var cell: Cell_NotesList? = (tableView.dequeueReusableCell(withIdentifier: CellIdentifier) as? Cell_NotesList)
if cell == nil {
let topLevelObjects: [Any] = Bundle.main.loadNibNamed("Cell_NotesList", owner: nil, options: nil)!
cell = (topLevelObjects[0] as? Cell_NotesList)
cell?.selectionStyle = .none
}
cell?.reloadCollectionView(arr: arrofofthumbImages)
return cell!
}
YourCell.SWIFT
class Cell_NotesList: UITableViewCell {
var imagesArr = NSMutableArray()
override func awakeFromNib() {
collectionView.register(UINib.init(nibName: "cell_ImageCollection", bundle: nil), forCellWithReuseIdentifier: "cell_ImageCollection")
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
extension Cell_NotesList : UICollectionViewDataSource {
func reloadCollectionView(arr:NSMutableArray) {
imagesArr = arr
collectionView.reloadData()
self.layoutIfNeeded()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imagesArr.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell : cell_ImageCollection? = collectionView.dequeueReusableCell(withReuseIdentifier: "cell_ImageCollection", for: indexPath) as? cell_ImageCollection
//YOUR CODE HERE
return cell!
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
}
extension Cell_NotesList : UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 120.0, height: 120.0)
}
}
extension UICollectionViewCell {
var indexPath: IndexPath? {
return (superview as? UICollectionView)?.indexPath(for: self)
}
}
In class that extends UICollectionView, put one setter method like
func setData(data: String){
// Update your cell view here like
Label.text = data
}

MoPub Collection View Cell set background color

For my app, I have a collection view that sets the background color of the cells based on a variable in the ViewController.
When MoPub places ads into the CollectionView how can I set the ad's background to match the other cells?
class RestController: UIViewController {
#IBOutlet weak var collectionView: UICollectionView!
var category: Category!
// Ads
var placer = MPCollectionViewAdPlacer()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
collectionView.mp_reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
// AD Cell
collectionView.register(AdCell.self, forCellWithReuseIdentifier: "cell")
let settings = MPStaticNativeAdRendererSettings()
settings.renderingViewClass = AdCell.self
settings.viewSizeHandler = { (maxWidth: CGFloat) -> CGSize in
return CGSize(width: 160, height: 100)
}
let config = MPStaticNativeAdRenderer.rendererConfiguration(with: settings)
placer = MPCollectionViewAdPlacer(collectionView: collectionView, viewController: self, rendererConfigurations: [config as Any])
let targeting = MPNativeAdRequestTargeting()
targeting.desiredAssets = [ kAdStarRatingKey, kAdIconImageKey, kAdTitleKey, kAdPrivacyIconUIImageKey ]
placer.loadAds(forAdUnitID: unitId, targeting: targeting)
collectionView.mp_setDelegate(self)
collectionView.mp_setDataSource(self)
}
}
// MARK: UICollectionViewDataSource
extension RestController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return results.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.mp_dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! RestCell
cell.backgroundColor = category.colors[1]
return cell
}
}
Is there any way to pass this information to the Ad Cell or any method that MoPub offers to set the design of the cell?

UICollectionView Disappear

I'm quite new to Swift. My problem is that my UICollectionView is disappearing.
In Xcode, it shows that everything is in place, but when I launch on a simulator or a device it disappears only left with the Navigation Bar and the Tab Bar.
Does anyone know what caused this or how to solve this?
Cheers!
Here is my code:
class User: UICollectionViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return 0
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "Header", for: indexPath) as! UserHeaderView
header.userEmail.text = PFUser.current()!.email
header.userChosenName.text = PFUser.current()!.object(forKey: "nickname") as? String
header.profilePicture.layer.cornerRadius = header.profilePicture.frame.size.width/2
header.profilePicture.clipsToBounds = true
let query = PFUser.current()?.object(forKey: "profilePicture") as! PFFile
query.getDataInBackground { (image, error) in
if error == nil {
header.profilePicture.image = UIImage(data: image!)
}
else {
SVProgressHUD.showError(withStatus: "Something's Wrong...")
}
}
return header
}
You are using the generated class and you have the number of sections 0 and number of rows 0 you have to change those based the count you want them to show
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
// The number of sections you have to provide
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// Number of Items in this section at least it should be 1
return 1
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "Header", for: indexPath) as! UserHeaderView
header.userEmail.text = PFUser.current()!.email
header.userChosenName.text = PFUser.current()!.object(forKey: "nickname") as? String
header.profilePicture.layer.cornerRadius = header.profilePicture.frame.size.width/2
header.profilePicture.clipsToBounds = true
let query = PFUser.current()?.object(forKey: "profilePicture") as! PFFile
query.getDataInBackground { (image, error) in
if error == nil {
header.profilePicture.image = UIImage(data: image!)
}
else {
SVProgressHUD.showError(withStatus: "Something's Wrong...")
}
}
return header
}
Edit:
You should have a cellForItemAt indexPath func else app will crash. here is an example of the function
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// this will return an empty cell where you're app will not crash
// but you have to create a cell and populate some data to the cell
return UICollectionViewCell()
}

Collection View inside Table View Cell

I want to create collection view inside the table view cell for horizontal scrolling of elements. But I have the problem how to fill right my collection views. I need a way to connect collection views with my data.
How can I get and loop through Table View Cells to find needed collection view and return the cells with data?
below is a general example of how you can pass data to collection views inside your table view cell. Also this link is a youtube tutorial on this subject.
Models:
class ListOfParents: NSObject {
var parents:[Parent]?
}
class Parent: NSObject {
var children: [Child]?
static func fetchParents(_ completionHandler: #escaping (ListOfParents) -> ()) {
//fetch parents data
}
}
class Child: NSObject {
}
TableView cell:
class CustomTableViewController: UITableViewController {
var listOfParents: ListOfParents?
override func viewDidLoad() {
super.viewDidLoad()
Parent.fetchparents { (listOfParents) in
self.listOfParents = listOfParents
}
tableView.register(CustomParentCell.self, forCellReuseIdentifier: "tableCell")
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let parentsCount = listOfParents?.parents?.count else {return 0}
return parentsCount
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomParentCell
cell.parent = listOfParents?.parents?[indexPath.item]
return cell
}
}
Parent cell:
class CustomParentCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource {
var parent: Parent? {
didSet {
// set child value here
}
}
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
return collectionView
}()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(CustomChildCell.self, forCellWithReuseIdentifier: "childCellID")
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
guard let childrenCount = parent?.children?.count else {return 0}
return childrenCount
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "childCellID", for: indexPath) as! CustomChildCell
cell.child = parent?.children?[indexPath.item]
return cell
}
}
Child cell:
class CustomChildCell: UICollectionViewCell {
var child: Child?
}

Populating UICollectionView with images is returning nil : Swift 2

I have a UICollectionView with a custom cell with an UIImageView in it as well as a custom class with the outlet
class theCell: UICollectionViewCell {
#IBOutlet var theImage:UIImageView!
}
I have an array of UIImage (Which only has one constant image). The image is in the main bundle.
var tempImages = [UIImage(named: "placeholder.png" )]
delegate methods
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return tempImages.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = self.collectionView?.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! theCell
//Unexpectadly found nil
cell.theImage.image = tempImages[indexPath.row]
return cell
}
If you have added this line:
self.collectionView!.registerClass(CollectionViewCell.self, forCellWithReuseIdentifier: "cell")
then remove this first and here is complete working code:
CollectionViewController.swift
import UIKit
class CollectionViewController: UICollectionViewController {
var tempImages = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
tempImages.append(UIImage(named: "bg.jpg")!)
}
// MARK: UICollectionViewDataSource
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
//#warning Incomplete method implementation -- Return the number of sections
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//#warning Incomplete method implementation -- Return the number of items in the section
return tempImages.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CollectionViewCell
// Configure the cell
cell.theImage.image = tempImages[indexPath.row]
println(cell.theImage.image)
return cell
}
}
CollectionViewCell.swift
import UIKit
class CollectionViewCell: UICollectionViewCell {
#IBOutlet var theImage:UIImageView!
}
And don't forget to assign Identifier to your cell:
Sample for more Info.
Try registering first in cellForItemAtIndexPath:
collectionView.registerNib(UINib(nibName: "FeedCell", bundle: nil), forCellWithReuseIdentifier: "cell")
EDIT
In your situation:
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
collectionView.registerNib(UINib(nibName: "FeedCell", bundle: nil), forCellWithReuseIdentifier: "cell")
let cell = self.collectionView?.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! theCell
cell.theImage.image = tempImages[indexPath.row]
return cell
}
The problem is reinitialize tempImages array so it return nil.
var tempImages = [UIImage(named: "placeholder.png" )]

Resources