Is it possible to retrieve data from collectionViewCell? - swift

I'm looking to retrieve data, such as a label.text from within a visible cell, and I don't know how that would be possible.
Plain context: I have a collectionView displaying questions (each cell display a question)
the collectionView is within a UIView.
Within this same uiview I have a button which, when pressed, should validate the question answer.
At this point the only thing Im doing is linking a #IBAction to the button in order for it to println the question from the visible cell (only one cell is visible).
here is how I construct the cell
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// return arr.count
return questionData.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell:CollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as CollectionViewCell
let thereq:PFObject = self.questionData.objectAtIndex(indexPath.row) as PFObject
// cell.contentView.frame = cell.bounds
var action = thereq.objectForKey("action") as String
var what = thereq.objectForKey("what") as String
cell.askingQuestionLabel.text = "where \(action) \(what)"
return cell
}
on button touch (button is out of the cell).
I know visibleCells() exists but it doesn't look like I can retrieve info out of it.
for cell in self.collectionView!.visibleCells() as [UICollectionViewCell] {
}
Is there any way?

You already have a custom collection view cell class. The obvious solution is to pass the PFObject to the CollectionViewCell in your cellForItemAtIndexRow method, and then retrieve it from the cell when the button is clicked.
Just cast the return value from visibleCells to your collection view cell class and then pull the PFObject out of it.

To access data (such as a label.text) within a visible cell, you can use the visibleCells() method as follow:
for item in self.collectionView!.visibleCells() as [UICollectionViewCell] {
var indexpath : NSIndexPath = self.collectionView!.indexPathForCell(item as CollectionViewCell)!
var cell : CollectionViewCell = self.collectionView!.cellForItemAtIndexPath(indexpath) as CollectionViewCell
//access cell data
println(cell.labelName.text)
}

Related

Make the first cell automatically selected when VC opens is not working

I have a ViewController that have a collectionView and I managed to make it selectable and all but the problem is that I have a checkmark image that stays in the first cell when the VC opens but in fact the cell is not selected at all and still the checkmark is there!
Code of the VC:
var selected = IndexPath(item: 0, section: 0)
var properties = connectedProperties(StatusCode: 0)
var propertiesNew = connectedProperties(StatusCode: 0)
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return properties.Result?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "dashboardCollectionViewCell", for: indexPath) as? dashboardCollectionViewCell else { return UICollectionViewCell() }
let currentPropertie = properties.Result?[indexPath.row]
cell.checkMarkButton.isHidden = !(indexPath == selected)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedCell = properties.Result?[indexPath.row]
changeCustomerKey.DefaultsKeys.keyTwo = indexPath.row
changeCustomerKey.DefaultsKeys.keyThree = selectedCell!.id!
let previous = selected.dropLast()
selected = indexPath
collectionView.reloadItems(at: [previous, selected])
}
If you want to tell your collection view to select a specific cell, you need to call the UICollectionView method selectItem(at:animated:scrollPosition:).
The "tricky bit" is that you can't call that until the collection view has finished populating itself (by calling your data source methods) and the first cell has been added to the collection view.
You might need to resort to something a bit hacky like adding an "initialDisplay" bool property who's value starts as true.
In your data source method that returns cells, check if initialDisplay==true and the requested indexPath is (0,0). If so, set initialDisplay=false, and fire a one-shot timer with a short delay. In the timer's closure, call selectItem(at:animated:scrollPosition:). The timer delay will return control to the event loop and give the system time to add the cell to the collection view.
There might be a better way to do this, but I can't think of it offhand, since you can't be sure when you will be asked to return your cell at IndexPath (0,0)

Adding placeholder images to UICollectionView cells while actual images are being downloaded

I have a collection view that is being populated with images created from parsed data. It is being populated and updated by using an NSFetchedResultsController as the data source. The code is in Swift 4, so to do so I am using the data source methods for the collection view along with the delegate methods for the NSFetchedResultsControllerDelegate as shown here:
func collectionView (_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if let count = fetchedResultsController.sections?[0].numberOfObjects {
return count
}else {
return 0
}
}
func collectionView (_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
print("Setting cell with photo")
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", for: indexPath) as! CollectionViewCell
let photoForCell = fetchedResultsController.object(at: indexPath)
cell.cellImage.image = UIImage(data: photoForCell.imageData!)
print(photoForCell.imageData!)
return cell
}
I am trying to calculate how many images were pulled in the parsed data and use this information to temporarily populate that many cells in the collection view with the same placeholder image in all of them. Then, once the images have all been downloaded and saved the NSFetchedResultsController will trigger the data source methods to refresh and populate the collection view with the new photos instead of the placeholder photos.
I have not been able to find any videos or posts that show how to do so. I tried creating a variable that holds the count of objects in the parsed data. That variable is then used in an if statement in the (:numberOfItemsInSection:) and (:cellForItemAt:) to determine whether it should populate the collection from saved photos or using the temporary photos like this:
func collectionView (_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if self.placeHolderCount != nil {
return placeHolderCount
}
if let count = fetchedResultsController.sections?[0].numberOfObjects {
return count
}else {
return 0
}
}
func collectionView (_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
print("Setting cell with photo")
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", for: indexPath) as! CollectionViewCell
let photoForCell = fetchedResultsController.object(at: indexPath)
if self.placeHolderCount != nil {
cell.cellImage.image = #imageLiteral(resourceName: "VirtualTourist_5112")
return cell
}
cell.cellImage.image = UIImage(data: photoForCell.imageData!)
print(photoForCell.imageData!)
return cell
}
Unfortunately, that causes the app to crash with an error saying "NSInvalidArgumentException reason: 'no object at index 0 in section at index 0"
During my troubleshooting, I found that this crash happens at the point when the view context is saved after downloading all the images. Everything in the application works perfectly including loading the downloaded images until I add the changes to the delegate methods. Does anyone know if I am on the right track? Should I be going about it in a completely different way? I have seen external libraries around that will accomplish this, but I cannot use any external libraries or frameworks for this particular application.

Passing Data to Custom CollectionView Cell (Static Data for all cells) SWIFT 2

So I have a collectionView in a viewcontroller. I have a variable var user = User! which stores the current selected user (FYI I'm using Parse). I want to pass variable to the custom cell.
extension SentViewController : UICollectionViewDataSource
{
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
{
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return cards.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(Storyboard.CellIdentifier, forIndexPath: indexPath) as! SentCardCollectionViewCell
cell.card = self.cards[indexPath.item]
cell.delegate = self
cell.user = user
return cell
}
}
Now, my problem is that when I pass the variable user to the variable user in custom collection view cell, I get an object that repeats 3 times. i.e.: the same variable gets passed over, but it is multiplied 3 times.
Any idea how to solve this? I have a feeling that it has something to do with the indexPath. Anyone have solutions?

UICollectionView setting first cell to always be specific content

Hi so I'm using a side scrolling UICollectionView to display groups of people that the user makes. The groups are stored on my server and when the view loads, they load from the server. However I want the first cell to always be the same which is a cell which lets you create groups. This is the layout i need.
I know how to use multiple different custom cells, but how do I make it so the first cell is static and the cells after load content from my servers? Thanks :)
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return familyName.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
if indexPath.row == 0 {
let cell : AddGroupCollectionViewCell = collectionViewOutlet.dequeueReusableCellWithReuseIdentifier("Add", forIndexPath: indexPath) as! AddGroupCollectionViewCell
return cell
} else {
let cell : FriendGroupsCell = collectionViewOutlet.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! FriendGroupsCell
cell.groupImage.image = UIImage(named: "pp")
cell.groupNameLabel.text = familyName[indexPath.row]
return cell
}
}
This is my code and it misses out the first person in the array because the index path skips over it. How can i modify this so it works
UICollectionViewCell is leveraging reusing techniques to improve performance. Remember this. Nothing can be static in a cell, because this cell later will be on another index.
You can use collectionView:cellForItemAtIndexPath: to make the first cell always load the same images/labels via indexPath.row == 0
You can use prepareReuse method to clean up the resources in the cell. So if cell No.2 is going to be the new No.1 cell, it get a chance to clean up old resources.
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell : AddGroupCollectionViewCell = collectionViewOutlet.dequeueReusableCellWithReuseIdentifier("Add", forIndexPath: indexPath) as! AddGroupCollectionViewCell
if indexPath.row == 0 {
cell.groupImage.image = UIImage(named: "new")
cell.groupNameLabel.text = "new"
} else {
cell.groupImage.image = UIImage(named: "pp")
cell.groupNameLabel.text = familyName[indexPath.row]
}
return cell
}

SWIFT... how to loop through UIcollectionView, and getting values from the textfield into an array

so i have given the textfields a tag of 10 i want to loop through the cells of the collection view and get the values of the textfield and store them into an array... here is some code.......
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let cell1 = collectionView.cellForItemAtIndexPath(indexPath)
let textbox1 = cell1?.viewWithTag(10) as? UITextField
print(indexPath.row)
print(textbox1?.text)
}
if I select the cell the right text is shown, I will eventually have a button, when clicked id want it to loop though all of the cells and store it into an array(which i can do). i need a way to loop through the cells using the index path and storing the textfield data, any help would be much appreciated
Method 1:
But it only give visible Cells textField values
for item in self.collectionView!.visibleCells() as! [CollectionViewCell] {
var indexpath : NSIndexPath = self.collectionView!.indexPathForCell(item as CollectionViewCell)!
var cell : CollectionViewCell = self.collectionView!.cellForItemAtIndexPath(indexpath) as! CollectionViewCell
println(cell.textField1.text)
}
Method 2:
globally declare a mutableArray
var arrayCellsTextFields : NSMutableArray = []
in cellForItemAtIndexPath
cell.textField1.tag = indexPath.row;
if(arrayCellsTextFields .containsObject(cell.textField1)==false)
{
arrayCellsTextFields .addObject(cell.textField1)
}
Array contain ur textFields object, you can identify the textfield with its tag, i.e., cell.textField1.tag & indexPath.row are same
Method 3:
in cellForItemAtIndexPath
cell.textField1.tag = indexPath.row;
cell.textField1.delegate = self;
using the textField delegate textFieldDidEndEditing u will get values in textField