I have a UICollectionViewCell who's data I want to access when tapped. The data will be used in another view controller... For instance, when I tap on a friend, the next viewcontroller presented will be a page with the tapped friends data.
Here is my didSelectItemAt IndexPath
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let layout = UICollectionViewFlowLayout()
let vc = JoinGroupChatController(collectionViewLayout: layout)
vc.selectedIndex = indexPath
let liveCell = LiveCell()
vc.descriptionLabel = liveCell.descriptionLabel.text
present(vc, animated: true, completion: nil)
}
In essence this is what I want to do however I need the indexPaths specific description label not the default liveCell label text.
I know I need to use the indexPath somewhere just not sure where / how.
Any suggestions?
replace
let liveCell = LiveCell()
with
let liveCell = collectionView.cellForItem(at: indexPath) as! LiveCell
Related
I have a list of user avatars inside of a UICollectionViewCell. When the user taps on one, I'd like to add the selected item to a collection as well as highlight it to indicate it's been tapped.
Unfortunately the UI doesn't seem to update. Any ideas?
Initially I load the images and set them to be rounded. I can even set the border color, if I want, but for now I set it to clear. This all works upon loading the cells:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath) as! UICollectionViewCell
// Configure the cell
let member: UserProfile = groupMembers[indexPath.item]
let imgAvatar = cell.viewWithTag(2) as! UIImageView
imgAvatar.layer.cornerRadius = contactAvatar.frame.size.width / 2
imgAvatar.clipsToBounds = true
imgAvatar.contentMode = UIViewContentMode.scaleAspectFill
imgAvatar.layer.borderWidth = 2.0
imgAvatar.layer.borderColor = UIColor.clear.cgColor
imgAvatar.layer.cornerRadius = 30.0
let downloadURL = NSURL(string: member.avatarUrl)!
imgAvatar.af_setImage(withURL: downloadURL as URL)
return cell
}
And now here is the code that executes when you tap on any given UIImageView in the collection, but it does not seem to update the image:
///Fired when tapped on an image of a person
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath) as! UICollectionViewCell
let tappedUser: UserProfile = groupMembers[indexPath.item]
let imgAvatar = cell.viewWithTag(2) as! UIImageView
..add item to collection, etc..
//Update imageview to indicate it's been tapped.
DispatchQueue.main.async {
contactAvatar.layer.cornerRadius = contactAvatar.frame.size.width / 2
imgAvatar.clipsToBounds = true
imgAvatar.contentMode = UIViewContentMode.scaleAspectFill
imgAvatar.layer.borderWidth = 2.0
imgAvatar.layer.cornerRadius = 30.0
imgAvatar.layer.borderColor = UIcolor.blue.cgColor
}
}
}
Running this code, it hits the breakpoint to indicate I've tapped on the item, but it does not update the UI. I'm convinced there is a thread / ui issue where the collection view isn't "redrawing" the changes I've made to the image. Maybe I can't change around the appearances of a view inside of a collection?
Thanks in advance for any insight.
Your didSelect is not correct. Get the cell from the collection view.
cellForItem
///Fired when tapped on an image of a person
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at:indexPath) as! UICollectionViewCell
let tappedUser: UserProfile = groupMembers[indexPath.item]
let imgAvatar = cell.viewWithTag(2) as! UIImageView
..add item to collection, etc..
//Update imageview to indicate it's been tapped.
DispatchQueue.main.async {
contactAvatar.layer.cornerRadius = contactAvatar.frame.size.width / 2
contactAvatar.clipsToBounds = true
contactAvatar.contentMode = UIViewContentMode.scaleAspectFill
contactAvatar.layer.borderWidth = 2.0
contactAvatar.layer.cornerRadius = 30.0
contactAvatar.layer.borderColor = UIcolor.blue.cgColor
}
}
}
Using mobile so let me know if it does not work.
The code which you have written to to get instance of cell is not correct please use below line of code and rest all seems correct hope by changing this line will work.
let cell = collectionView.cellForItem(at:indexPath) as! UICollectionViewCell
my collectionview contains multiple custom cell class that created programmatically. Fun part is I will have a cell that contains another collectionview inside of it. So how to click into this collectionview to present a new view controller? Below are my sample codes on how to create the cell.
class MainView: UIViewController {
** main view to display UIcollectionview **
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: userCellIdent, for: indexPath) as! UserContainerViewCell
cell.Users = users * to display users array*
return cell
}
class UserContainerViewCell: UICollectionViewCell{
* the uicollectionview that inside a cell , also contains extension to UIcollectioview datasource and delegate to display the cells within this cell*
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ident, for: indexPath) as! userCell
let user = featureUsers![indexPath.row]
cell.config(withUser: user)
return cell
}
}
class userCell: UICollectionViewCell {
func config(withUser: UserProfile) { }
** cell class to display the info from the user array **
}
So with this setup, how to click into the cell and present a new controller with the User info in the array?
You have to pass a delegate or hit notification to viewController on didSelect of internal collectionViewCell and in that method you can present new view controller .
check out the link
Swift: How to use "didSelectItemAtIndexPath" in UITableViewController(contains UICollectionView)?
You can try
class UserContainerViewCell: UICollectionViewCell {
var myInstance: MainView!
}
class MainView: UIViewController {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: userCellIdent, for: indexPath) as! UserContainerViewCell
cell.myInstance = self
}
}
then inside didSelectItemAtRow
let vc = myInstance.storyboard?.instantiateViewController(withIdentifier: "infoView") as! InfoController
vc.providesPresentationContextTransitionStyle = true;
vc.definesPresentationContext = true;
vc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
myInstance.present(vc, animated: false, completion: nil)
Here is what I want to do (UI is showing down below), I want to perform different segue when I taped different cell in it. But I don't know what component I should use to get this done
I think to use the Collection View Controller, but it seems doest support static cells, I want to use Customized UIVIew to do this, but it couldn't be dragged to another VC in StoryBoard, should I adopt some sort of Protocols of something to do this?
Please answer in Swift
After been helped
Turns out I just need to show the ViewController and haven't need segue yet, so here is the code.
let categories: [(name: String, pic: String, identifier: String)] = [
("人物", "Wilson_head", "CharactersVC"),
("动物", "Pig", "MobsVC"),
("植物", "Bamboo_Patch", "PlantsVC"),
("食谱", "Crock_Pot_Build", "RecipesVC")
]
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let currentCategory = categories[indexPath.row]
let destVC: UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: currentCategory.identifier)
navigationController!.pushViewController(destVC, animated: true)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
if(indexPath.row == 0)
{
let objstory = self.storyboard?.instantiateViewController(withIdentifier: “your Story bord identifier”) as! Your View_ViewController
self.navigationController?.pushViewController(objstory, animated: true)
}
}
Collection View Controller doesn't support static cell.
But you can add static cell programmatically.
set your cell data and target(segue id) for each cell.
ex:
cellData[0].segue = "segueToHuman"
cellData[1].segue = "segueToAnimal"
add segues depend on your view controller(not on cell) like below:
create segue
segue setting
perform particular segue in didSelectItemAt indexPath
let segueID = cellData[indexPath.row].segue
performSegue(withIdentifier: segueID, sender: nil)
I'm following a tutorial for making an Instagram-esque app, and the tutorial goes through how to display all data (image, author, likes, etc) all in one collection view. I'm trying to do it a little bit differently so only the images are displayed in the collection view, then if an image is tapped, the user is taken to a different view controller where the image plus all the other data is displayed.
So in my view controller with the collection view (FeedViewController), I have my array of posts declared outside the class (Post is the object with all the aforementioned data):
var posts = [Post]()
Then inside the FeedViewController class, my cellForItemAt indexPath looks like this:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "postCell", for: indexPath) as! PostCell
// creating the cell
cell.postImage.downloadImage(from: posts[indexPath.row].pathToImage)
photoDetailController.authorNameLabel.text = posts[indexPath.row].author
photoDetailController.likeLabel.text = "\(posts[indexPath.row].likes!) Likes"
photoDetailController.photoDetailImageView.downloadImage(from: posts[indexPath.row].pathToImage)
return cell
}
And then I also obviously have a function to fetch the data which I can post if necessary, but I think the problem is because PhotoDetailController doesn't know the indexPath (although I may be wrong).
When I run the app and try to view the FeedViewController I get a crash fatal error: unexpectedly found nil while unwrapping an Optional value, highlighting photoDetailController.authorNameLabel line.
Am I correct in assuming the problem is because the indexPath is available only in the collection view data sources within FeedViewController? If so, how can I pass that indexPath to PhotoDetailController so my code works correctly?
Thanks for any advice!
EDIT: Edited my didSelectItem method:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let photoDetailController = self.storyboard?.instantiateViewController(withIdentifier: "photoDetail") as! PhotoDetailController
photoDetailController.selectedPost = posts[indexPath.row]
self.navigationController?.pushViewController(photoDetailController, animated: true)
}
and cellForItemAt:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "postCell", for: indexPath) as! PostCell
cell.postImage.downloadImage(from: posts[indexPath.row].pathToImage)
return cell
}
And in PhotoDetailController:
var selectedPost: Post! inside the class, then:
override func viewDidLoad() {
super.viewDidLoad()
self.authorNameLabel.text = selectedPost[indexPath.row].author
self.likeLabel.text = "\(selectedPost[indexPath.row].likes!) Likes"
self.photoDetailImageView.downloadImage(from: selectedPost[indexPath.row].pathToImage)
}
But still getting error use of unresolved identifier "indexPath
EDIT 2: Storyboard
You are getting this nil crash because this photoDetailController is not yet loaded so all its outlet are nil also the way currently you are doing is also wrong.
You need to add the controller code in didSelectItemAt method and perform the navigation.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let photoDetailController = self.storyboard?.instantiateViewController(withIdentifier: "YourIdentifier") as! PhotoDetailController
photoDetailController.selectedPost = posts[indexPath.row]
self.navigationController?.pushViewController(photoDetailController, animated: true)
}
Now simply create one instance property of type Post with name selectedPost in PhotoDetailController and set all the detail from this selectedPost object in viewDidLoad of PhotoDetailController.
Edit: Set your viewDidLoad like this in PhotoDetailController
override func viewDidLoad() {
super.viewDidLoad()
self.authorNameLabel.text = selectedPost.author
self.likeLabel.text = "\(selectedPost.likes!) Likes"
self.photoDetailImageView.downloadImage(from: selectedPost.pathToImage)
}
I've a collectionViewCell(dynamic) with images and labels (loading from JSON) inside a tableview. what i want is if i click on any Cell (contains image/folders) it should display detailedViewController with its content(also from JSON).
my mainViewController works fine. displays the DATA.
inside mainViewController i used didSelectItemAtIndexPath like this
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
println("USER TAPPED item# \(indexPath.item)")
let subFolderView:SubFolderViewController = self.storyboard?.instantiateViewControllerWithIdentifier("subFolder") as! SubFolderViewController
self.navigationController?.pushViewController(subFolderView, animated: true)
subFolderView.imageSelected = self.Data[indexPath.row].AbsolutePath
subFolderView.imageSelected = self.Data[indexPath.row].Name
subFolderView.imageSelected = self.Data[indexPath.row].Description
BUT it is returning empty view when clicked.
in my secondViewController i have
var imageSelected:String!
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell:SubFolderCollectionViewCell? = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as? SubFolderCollectionViewCell
cell?.subFolderDescription.text = self.Data[indexPath.row].Description
cell?.subFolderName.text = self.Data[indexPath.row].Name
let picUrl = self.Data[indexPath.row].AbsolutePath
let url = NSURL(string: picUrl)
if(url != nil) {
let data = NSData(contentsOfURL : url!)
if(data != nil) {
cell?.subImage?.image = UIImage(data: data!)
}
}
return cell!
}
Please any one guide me to proceed further......i am new to iOS development and prefer swift!!!!!!!
IN my storyBoadrd both viewControllers contains
View,
Tableview,
TableViewCell,
ContentView,
collectionView,
collectionViewCell.
inside that imageView and labels to display the data
Any help is appreciated,
Please let me know if u need more code............
Check your code..
you use didDeselectItemAtIndexPath instead of didSelectItemAtIndexPath method..
It's different tableview delegate method. change this and let me know if there is any issue.