Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
jean-marie castellucci
4,954 PointsSwift : how to display an image from a collectionView controller to a detail viewController
Hello
I have a collectionView wich is populated by images from a NSMutableArray of Parse.com PFObject. Each object have an image.
What i want to achieve is to click on a particular picture in the collectionView and display it bigger in a detailViewController. The probleme is i don't know how to pass the good picture.
I used this method :
override func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
let userPost: AnyObject = self.timeLineData.objectAtIndex(indexPath.row)
let viewController:ImageDetailTableViewController = ImageDetailTableViewController()
viewController.modalPresentationStyle = UIModalPresentationStyle.Custom
viewController.transitioningDelegate = self
viewController.timeLineData = userPost as NSMutableArray
self.presentViewController(viewController, animated: true, completion: {})
}
But i have an error :
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
Any idea ?
5 Answers
Stone Preston
42,016 Pointsok since your detail view controller is just going to display data from a single post, you dont need a Mutable Array property in your detail VC, just a PFObejct property
class ImageDetailTableViewController: UITableViewController {
var photoPassed : UIImageView = UIImageView()
var post: PFObject!
then in your selection method you can pass the selected post to the detail view controller. you could try getting the cell using cellForItemAtIndexPath
override func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
//get the post
let userPost: PFObject = self.timeLineData.objectAtIndex(indexPath.row)
let viewController:ImageDetailTableViewController = ImageDetailTableViewController()
viewController.modalPresentationStyle = UIModalPresentationStyle.Custom
viewController.transitioningDelegate = self
//set the detail post
viewController.post = userPost
self.presentViewController(viewController, animated: true, completion: {})
Stone Preston
42,016 Pointswhat kind of objects are stored in timelineData?
you have this here:
let userPost: AnyObject = self.timeLineData.objectAtIndex(indexPath.row)
which sets the post, however the type of that object is generic. it would be helpful if we knew what was in there.
then in this line you set a property of the next view controller using the userPost, however if userPost is not an array thats not going to work:
viewController.timeLineData = userPost as NSMutableArray
if timeLineDate does indeed contain mutable array objects then you most likely need to use:
let userPost: NSMutableArray = self.timeLineData.objectAtIndex(indexPath.row)
jean-marie castellucci
4,954 PointsThis how my collectionView is set up :
import UIKit
class UserPostsCollectionViewController: UICollectionViewController, UIViewControllerTransitioningDelegate {
var userPassed : PFUser = PFUser()
var timeLineData:NSMutableArray = NSMutableArray ()
var followedFriends:NSMutableArray = NSMutableArray ()
func loadPost () {
timeLineData.removeAllObjects()
var findPosts:PFQuery = PFQuery(className: "UserPost")
findPosts.whereKey("from", equalTo: userPassed)
findPosts.cachePolicy = kPFCachePolicyNetworkOnly
findPosts.orderByDescending("createdAt")
//run the query
findPosts.findObjectsInBackgroundWithBlock { (objects:[AnyObject]!, error:NSError!) -> Void in
if !(error != nil) {
//found posts
for object in objects {
self.timeLineData.addObject(object)
self.collectionView?.reloadData()
println("Image post loaded")
}
} else {
// Log details of the failure
println("error loadind posts ")
}
}
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell : UserPostsCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as UserPostsCell
cell.backgroundColor = UIColor.lightGrayColor()
let userPost = self.timeLineData.objectAtIndex(indexPath.row) as PFObject
//define the imagepost
if let imagesPost:PFFile = userPost["imageFile"] as? PFFile {
imagesPost.getDataInBackgroundWithBlock{(imageData:NSData!, error:NSError!)-> Void in
if (error == nil) {
var image:UIImage = UIImage(data: imageData)!
println("image from posts finded")
cell.imagePost.image = image as UIImage
}
else {
println("error")
}
} }
return cell
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
loadPost()
}
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 self.timeLineData.count
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
let userPost: AnyObject = self.timeLineData.objectAtIndex(indexPath.row)
let viewController:ImageDetailTableViewController = ImageDetailTableViewController()
viewController.modalPresentationStyle = UIModalPresentationStyle.Custom
viewController.transitioningDelegate = self
viewController.timeLineData = userPost as NSMutableArray
self.presentViewController(viewController, animated: true, completion: {})
}
}
I set up the detail VC like this :
import UIKit
class ImageDetailTableViewController: UITableViewController {
var photoPassed : UIImageView = UIImageView()
var timeLineData:NSMutableArray = NSMutableArray ()
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : ImageDetailTableViewCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as ImageDetailTableViewCell
let userPost = self.timeLineData.objectAtIndex(indexPath.row) as PFObject
if let imagesPost:PFFile = userPost["imageFile"] as? PFFile {
imagesPost.getDataInBackgroundWithBlock{(imageData:NSData!, error:NSError!)-> Void in
if (error == nil) {
var image:UIImage = UIImage(data: imageData)!
println("image from posts finded")
cell.imageDetail.image = image as UIImage
cell.imageDetail.backgroundColor = UIColor.lightGrayColor()
}
else {
println("error")
}
} }
println(cell)
return cell
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
}
}
jean-marie castellucci
4,954 PointsIn fact timeLineData is a NSMutableArray containing PFobject with PFiles (the picture that populate the Table)
The best way would be to pass the picture without having to call Parse another time in the detailViewController.
But i don't know how to do it so i decided to pass the PFobject and then make another call to Parse.com to get the PFfile. I'm sure we can do it easier...
jean-marie castellucci
4,954 PointsOk it work but now it s my xcode beta version who make the service kit bug every 5 min... Gona install the previous version. Thank Stone