UICollectionViewCell with image without custom Class - ios

there pretty simple Question actually:
I want a collectionView with an Image with the same size as the Cell. I want to do this all without building a extra class, so from storyboard (maybe, if I get on my subview?!)
And btw, i load data from web, so I Can't just add a new ImageView every time....
just wanna ask if this is possible?!
Cheers

If you have static Collection view then you can do without custom class
but you have dynamic Collection view then you need to create custom class.
which is look like this.
class AddAlbumCell: UICollectionViewCell {
#IBOutlet var imgv: UIImageView!
}
In your Collection view Delegate method
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! AddAlbumCell
cell.imgv.image = images[indexPath.row] //"images" contains image name array
return cell;
}

Related

Nested collectionView in a TableView

I've been successfully nesting collections views into tableview for a while now.
What I still don't know how to do, is to do it while respecting the MVC pattern?
Right now I declare my tableview and its cells and in the cell (where the collectionView sits), I attach my collectionView (I got 1 per cell) and do the data mapping. It works, but it's spaghetti code where my View is acting like a controller.
I tried a few times to respect the MVC patterns. I can get my controller to control both my tableview and my collection. Where I struggle is to tell my collection View delegate which data it should pick as all I have as reference is the indexPath (of the collectionView) but not in which tableView that specific collectionView sits.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
return cell
}
The delegate only gives me the indexPath of the cell not which collectionView it is. To use a concrete example - let's assume that my tableview cells represents messages and that each message has a collectionView that controls reactions (like Discord). How do I tell my collectionView delegate which Message it is linked to?
Thanks a lot for the help!
This is very simple. Every view and its subclass has a property tag. You must have an IBOutlet or a simple reference to the CollectionView that sits in the TableViewCell. When you dequeue the TableViewCell just set the tag of your CollectionView equal to the indexPath.row of your tableViewCell like this:
tableViewCell.collectionView.tag = indexPath.row
Then in the UICollectionViewDataSource or UICollectionViewDelegate methods you may find which collectionView it is in other words which tableViewCell does this collectionView sits in. Here's an example:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
let dataObject = dataSourceArray[indexPath.row] as! YourDataModelObject
// Here you may set any property of the collectionView cell
return cell
}
P.S: It is not necessary to respect MVC to that extent. You may manage your CollectionView from the TableViewCell. Have a look at this example.

iOS Use multiple CollectionView reusing the same cell

I'm new to iOS programming but from my experience with Android i know that you can create one design for a item that can be reused in multiple lists, without needing to create a copy.
In iOS i have been trying the same approach with UICollectionView.
In my view i have created three Horizontal UICollectionViews (with different data sets) which in turn use their own cell (Which is identical to the others). I don't know how to make the other two collections use the first ones cell, so i don't need to recreate the same cell over and over.
You can't achieve this using single storyboard. If you want to use Interface Builder (xml) file for layout, you should create MyCell.xib file, then drag UICollectionViewCell on that file and work with that xib.
Then you should connect .xib file with your collection view like this:
let nib = UINib(nibName: "MyCell", bundle: nil)
collectionView?.register(nil, for: "MyCellReuseID")
And you can work with your cell now.
Also you can create MyCell: UICollectionViewCell class without creating .xib file, create views on it programmatically and then call collectionView?.register(MyCell.self, for: "MyCellReuseID")
In your function collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell you can inform your collectionview which cell to use
if you have define your cell you might have something similar to this
class MyCell: UICollectionViewCell{
var Label: UILabel!
var imageView: UIImageView!
}
so into your function collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) you need to inform your collectionview which cell to use
collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell:MyCell = collectionView.dequeueReusableCellWithReuseIdentifier("myCell", forIndexPath: indexPath) as! MyCell
[...]
}
and dont forget to register your cell first
override func viewDidLoad() {
super.viewDidLoad()
//do your stuff
collectionView.delegate = self
collectionView.dataSource = self
collectionView.backgroundColor = UIColor.whiteColor()
collectionView.registerClass(MyCell.self, forCellWithReuseIdentifier: "myCell")
}
and Voila !
Create new file collection cell with XIB
In your "item at row for index" delegate method in view controller, initialize cell and return it.
Now any collection view within you view controller have the same cell
Create a Swift class(CollectionViewCell) by having UICollectionViewCell as a base class. Select create nib option while doing that.
Then create a view controller and add collection view to it in your storyboard and hook up this custom cell class in Identity Inspector. Basically, your structure needs to look like below

Custom UICollectionView in Swift 3 not working

So I am new to swift and am trying to create a custom UiCollectionView that you can horizontally scroll through, and when tapping on a button, you can add an image from your camera roll to the array of images in the collection view. This is what I have so far and I have run into some problems. I have tried watching videos online but I still get errors so i don't know what I am doing wrong. I have some images of apple products that I loaded into my assets folder and I will be using those images in an array for the collectionView. Each image will be in one colletionViewCell.
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var collectionView: UICollectionView!
let imageArray = [UIImage(named: "appleWatch" ), UIImage(named: "iPhone"), UIImage(named: "iPad" ), UIImage(named: "iPod" ), UIImage(named: "macBook")]
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.imageArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! UICollectionViewCell
cell.ourImage?.image = self.imageArray[indexPath.row]
return cell
}
}
It gives me an error here cell.ourImage?.image = self.imageArray[indexPath.row] and says that "value type UICollectionViewCell has no member 'ourImage'" Even though I named the outlet ourImage on another UICollectionViewCell swift file. I have checked the Main.storyboard and I think I have named all of my classes correctly and have assigned them to the collectionViewCell and the identifier. I delete this line and it compiles fine, but whenever the app is run nothing shows up on the screen so there may be something wrong with my images too. Does anybody have any ideas? How would you go about creating a custom UiCollection View? Do I have the right idea?
Instead of casting the dequeued cell to UICollectionViewCell, you need to treat it as your custom UICollectionViewCell subclass.
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourReuseIdentifier", for: indexPath) as? YourCustomCollectionViewCell {
// set the cell's custom properties
}
You can also force cast using as! YourCustomCollectionViewCell, but I personally prefer not to do this.

Is it possible to reuse cellForItemAtIndexPath:?

I have two collection views. They both use identical cell layouts but for other reasons they must be separate controllers. Currently when I make updates to cellForItemAtIndexPath: in one, I have to copy and paste the change to the other.
Is there a way for me to separate out this one method so I can make changes in one place and have them reflected in both controllers? One of the controllers is a UIViewController subclass. The other is a subclass of a custom UIViewController subclass.
You can make a Separate Data Source class then you can just link the collectionview data source to it.
Your data source will be like this
class CollectionViewDataSource: NSObject, UICollectionViewDataSource {
var dataArray:[YourObjects]?
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return dataArray!.count ?? 0
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("YourCellIdentifier", forIndexPath: indexPath) as! UICollectionViewCell
return cell
}
}
And you can cell it in your controller like this
lazy var collectionViewDataSource: CollectionViewDataSource = {
return CollectionViewDataSource()
}()
#IBOutlet weak var collectionView: UICollectionView! {
didSet{
collectionViewDataSource.dataArray = //Your array
collectionView.dataSource = collectionViewDataSource
}
You can achieve this
Suppose there are 2 viewcontroller vc1 and vc2 and 2 collectionview cv1 and cv2
Make a separate class
CollectionDelegate cD
now set datasource of both collectionview to this newly made CollectionDelegate
like
cv1.dataSource = cD
cv2.datasource = cD
Implement you cellForItemAtIndexPatha and other data source method in CollectionDelegate class

Runtime error when trying to access the members of a cell that has been registered

I have a CollectionView cell that has an image view and a label within it. When I try to set either the image or the text within the label my program crashes within this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
The cell is a custom class that has inherited from UICollectionViewCell, and the outlets have been created and linked in the storyboard:
class CustomCell: UICollectionViewCell {
#IBOutlet var thumbnailImageView: UIImageView!
#IBOutlet var textLabel: UILabel!
}
I am setting the imageView with:
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as CustomCell
cell.thumbnailImageView.image = UIImage(named: "ss")
return cell
}
I originally thought there was something wrong with the image file location so I commented it out and tried to change the text of the label with:
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as CustomCell
cell.textLabel.text = "Hello"
return cell
}
But that also caused a crash. What could cause a custom cell to load correctly but not have access to any of its' members?
EDIT: In the viewdidload function I registered my class like this:
self.collectionView?.registerClass(CustomCell.self, forCellWithReuseIdentifier: reuseIdentifier)
EDIT:
You shouldn't register the class if the cell was made in a storyboard. Delete that line. Make sure you set the identifier for the cell in the storyboard. You only register the class if you're making the cell entirely in code.

Resources