I seem to be running into an issue and don't know where I am going wrong. I am trying to send the user's post to another view controller through a button, and my app keeps crashing. Below is the code for the tableview cell and the the prepare for segue. I am still new to the app development world. So I am sorry if my code is a little messy. Also I am using Parse as my backend. I don't know if that makes a difference.
thank you in advanced!
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! TimelineTableViewCell
let userPost: PFObject = self.userObjects.objectAtIndex(indexPath.row) as! PFObject
cell.backgroundColor = UIColor.darkGrayColor().colorWithAlphaComponent(0.2)
cell.layer.borderColor = UIColor.lightGrayColor().CGColor
cell.layer.borderWidth = 0.5
cell.reportPost.tag = indexPath.row
cell.reportPost.addTarget(self, action: "buttonAction", forControlEvents: .TouchUpInside)
// Display Users Post's
var userText = userPost["text"] as? String
cell.TextLabel!.text = userText
// Display Date and Time
var Date: NSDateFormatter = NSDateFormatter()
Date.dateFormat = "MM-dd HH:mm"
cell.dateLabel.text = Date.stringFromDate(userPost.createdAt!)
// Display username
var findUser:PFQuery = PFUser.query()!
let Id = userPost.objectForKey("username")?.objectId as NSString!
findUser.whereKey("objectId", equalTo: Id)
findUser.findObjectsInBackgroundWithBlock{
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil{
var user:PFUser = (objects as NSArray!).lastObject as! PFUser
cell.userLabel.text = user.username
// Getting User's Profile Image
var initialThumbnail = UIImage(named: "PAHS_Logo")
cell.userImage.image = initialThumbnail
if let PhotoFile = user["ProfileImage"] as? PFFile {
PhotoFile.getDataInBackgroundWithBlock{
(ImageData:NSData?, error:NSError?)->Void in
if error == nil{
let Image:UIImage = UIImage(data: ImageData!)!
cell.userImage.image = Image
}else{
cell.userImage.image = initialThumbnail
}
}
}
}
}
return cell
}
func buttonAction(sender: UIButton!){
let titleString = self.userObjects.objectAtIndex(sender.tag) as? String
let firstActivityItem = "\(titleString)"
let activityViewController: UIActivityViewController = UIActivityViewController(activityItems: [firstActivityItem], applicationActivities: nil)
self.presentViewController(activityViewController, animated: true, completion: nil)
}
var valueToPass: String!
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = tableView.indexPathForSelectedRow();
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;
valueToPass = currentCell.textLabel?.text
performSegueWithIdentifier("reportPost", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "reportPost")
{
var viewController: reportViewController = segue.destinationViewController as! reportViewController
let indexPath = self.tableView!.indexPathsForSelectedRows();
let titleString = userObjects.objectAtIndex(indexPath!.count) as! String
viewController.titleString = titleString
viewController.titleLabel.text = valueToPass //fatal error: unexpectedly found nil while unwrapping an Optional value
self.presentViewController(viewController, animated: true, completion: nil)
}
}
You can change performSegueWithIdentifier("reportPost", sender: self) to performSegueWithIdentifier("reportPost", sender: indexPath) Then, in prepareForSegue(), the sender is going to be the indexPath. You can change your prepareForSegue() to this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "reportPost")
{
var viewController: reportViewController = segue.destinationViewController as! reportViewController
let indexPath = sender as! NSIndexPath
let titleString = userObjects[indexPath.row] as! String // I am assuming userObjects is the object containing the data you want
viewController.titleString = titleString
let cell = tableView.cellForRowAtIndexPath(indexPath) as! UITableViewCell
let valueToPass = cell.textLabel?.text
viewController.titleLabel.text = valueToPass
self.presentViewController(viewController, animated: true, completion: nil)
}
}
If you do it this way, you can get rid of var valueToPass: String! above tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
Related
I have a UITableView with few rows. When I hold on a cell the Camera pop-up and I can take photos and to store them in an album of photos.
Each row can have an album of photos. The problem is that when I click on an album, then every time will open me the album with the last picture made and I don't know how to fix this issue with the indexPath.
Here is my code:
class CustomImg: UIImageView {
var indexPath: IndexPath?
}
class ChecklistVC: UIViewController {
lazy var itemSections: [ChecklistItemSection] = {
return ChecklistItemSection.checklistItemSections()
}()
var lastIndexPath: IndexPath!
var currentIndexPath: IndexPath!
...
...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Constants.checklistCell, for: indexPath) as! ChecklistCell
let itemCategory = itemSections[indexPath.section]
let item = itemCategory.checklistItems[indexPath.row]
if item.imagesPath!.isEmpty{
cell.defectImageHeightConstraint.constant = 0
}
else{
let thumbnailImage = loadImageFromDiskWith(fileName: item.imagesPath?.last ?? String())
cell.defectImageView.indexPath = indexPath
cell.defectImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapOnDefectImageView(_:))))
cell.defectImageHeightConstraint.constant = 100
cell.defectImageView.isUserInteractionEnabled = true
cell.defectImageView.image = thumbnailImage
print("For section \(indexPath.section + 1) - row \(String(describing: indexPath.row + 1)) the album photos are: \(String(describing: item.imagesPath))")
}
return cell
}
#objc func tapOnDefectImageView(_ sender: UITapGestureRecognizer){
guard let img = sender.view as? CustomImg, let indexPath = img.indexPath else { return }
currentIndexPath = indexPath
let listImagesDefectVC = storyboard?.instantiateViewController(withIdentifier: "ListImagesDefectID") as! ListImagesDefectVC
let item = itemSections[indexPath.section].checklistItems[indexPath.row]
listImagesDefectVC.listImagesPath = item.imagesPath
listImagesDefectVC.isPhotoAccessedFromChecklist = true
listImagesDefectVC.delegate = self
navigationController?.pushViewController(listImagesDefectVC, animated: true)
}
// A menu from where the user can choose to take pictures for "Vehicle Damage/Defects" or "Trailer Damage/Defects"
func showOptionsForAddPhoto(_ indexPath: IndexPath){
let addPhotoForVehicle = UIAlertAction(title: "Add photo for Vehicle", style: .default) { action in
self.lastIndexPath = indexPath // Get the position of the cell where to add the vehicle photo
self.showCamera(imagePicker: self.imagePicker)
}
let addPhotoForTrailer = UIAlertAction(title: "Add photo for Trailer", style: .default) { action in
self.lastIndexPath = indexPath
self.showCamera(imagePicker: self.imagePicker)
}
let actionSheet = configureActionSheet()
actionSheet.addAction(addPhotoForVehicle)
actionSheet.addAction(addPhotoForTrailer)
self.present(actionSheet, animated: true, completion: nil)
}
// Get the list of the images from ListImagesDefectVC
extension ChecklistVC: ListImagesDefectDelegate {
func receiveListImagesUpdated(imagesFromList: [String]?) {
print("Received Array: \(imagesFromList ?? [])")
let item = itemSections[currentIndexPath.section].checklistItems[currentIndexPath.row]
item.imagesPath = imagesFromList
}
}
}
Here is a GIF with my actual issue. In this capture I click only on Photo 1 and Photo 3. And every time Photo 2 take the value of what I clicked before:
http://g.recordit.co/VMeGZbf7TF.gif
Thank you if you are reading this.
I guess in tapOnDefectImageView you should use the clicked indexPath for the cell not lastIndexPath which is the reason why clicking a row shows photos of last clicked indexPath
so either add this gesture inside the cell and in the action method do
delegate?.tapOnDefectImageView(self) //// self = cell
and use
#objc func tapOnDefectImageView(_ gest:ChecklistCell){
guard let indexPath = tableView.indexPath(cell) else { return }
let listImagesDefectVC = storyboard?.instantiateViewController(withIdentifier: "ListImagesDefectID") as! ListImagesDefectVC
let item = itemSections[indexPath.section].checklistItems[indexPath.row]
listImagesDefectVC.listImagesPath = item.imagesPath
listImagesDefectVC.isPhotoAccessedFromChecklist = true
listImagesDefectVC.delegate = self
navigationController?.pushViewController(listImagesDefectVC, animated: true)
}
or create
class CustomImg:UIImageView {
var indexPath:IndexPath?
}
with this inside cellForRowAt
cell.defectImageView.indexPath = indexPath
cell.defectImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapOnDefectImageView)))
then assign the class to the imageView of the cell and now you can do
#objc func tapOnDefectImageView(_ sender:UITapGestureRecognizer){
guard let img = sender.view as? CustomImg , let indexPath = img.indexPath else { return }
let listImagesDefectVC = storyboard?.instantiateViewController(withIdentifier: "ListImagesDefectID") as! ListImagesDefectVC
let item = itemSections[indexPath.section].checklistItems[indexPath.row]
listImagesDefectVC.listImagesPath = item.imagesPath
listImagesDefectVC.isPhotoAccessedFromChecklist = true
listImagesDefectVC.delegate = self
navigationController?.pushViewController(listImagesDefectVC, animated: true)
}
I'm new to this and having trouble displaying the comments of a post in a table view with two cells (one cell = post, second cell = comments). Here is my code for the View Controller:
import UIKit
class PostDetailViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var postId = ""
var post = Post()
var user = User()
var comments = [Comment]()
var users = [User]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
print("postId = \(postId)")
loadPost()
loadComments()
}
func loadPost() {
API.Post.observePost(withId: postId) { (post) in
guard let postUid = post.uid else {
return
}
self.fetchUser(uid: postUid, completed: {
self.post = post
self.tableView.reloadData()
})
self.navigationItem.title = post.title
}
}
func fetchUser(uid: String, completed: #escaping () -> Void ) {
API.User.observeUser(withId: uid, completion: {
user in
self.user = user
completed()
})
}
func loadComments() {API.Post_Comment.REF_POST_COMMENTS.child(self.postId).observe(.childAdded, with: {
snapshot in
API.Comment.observeComments(withPostId: snapshot.key, completion: { comment in
self.fetchUser(uid: comment.uid!, completed: {
self.comments.append(comment)
self.tableView.reloadData()
})
})
})
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "Detail_CommentSegue" {
let commentVC = segue.destination as! CommentViewController
let postId = sender as! String
commentVC.postId = postId
}
if segue.identifier == "Detail_ProfileUserSegue" {
let profileVC = segue.destination as! ProfileUserViewController
let userId = sender as! String
profileVC.userId = userId
}
}
}
extension PostDetailViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return comments.count + 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "DetailPostCell", for: indexPath) as! DetailTableViewCell
cell.post = post
cell.user = user
cell.delegate = self
return cell
} else {
let commentCell = tableView.dequeueReusableCell(withIdentifier: "Detail_CommentCell") as! CommentTableViewCell
let comment = comments[indexPath.row]
let user = users[indexPath.row]
commentCell.comment = comment
commentCell.user = user
return commentCell
}
}
}
extension PostDetailViewController: DetailTableViewCellDelegate {
func goToCommentVC(postId: String) {
performSegue(withIdentifier: "Detail_CommentSegue", sender: postId)
}
func goToProfileUserVC(userId: String) {
performSegue(withIdentifier: "Detail_ProfileUserSegue", sender: userId)
}
}
The error I'm getting is at:
let comment = comments[indexPath.row]
"fatal error: Index out of range"
There are comments and they appear on the Comments View Controller without issue. I realize the error has something to do with calling two cells but I am unable to figure out a fix.
You are not accounting for the first row when getting a value from your arrays.
The simple fix is to update cellForRowAt as follows:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "DetailPostCell", for: indexPath) as! DetailTableViewCell
cell.post = post
cell.user = user
cell.delegate = self
return cell
} else {
let commentCell = tableView.dequeueReusableCell(withIdentifier: "Detail_CommentCell") as! CommentTableViewCell
let comment = comments[indexPath.row - 1] // here
let user = users[indexPath.row - 1] // here
commentCell.comment = comment
commentCell.user = user
return commentCell
}
}
Note the two minor changes marked // here. The idea is that comment[0] is at row 1.
Some better suggestions:
Do not have multiple arrays. Have one array for your data. Define a structure that holds all of the data for one row. Then have one array of those structures. This makes your data easier to handle and makes things like sorting and filtering vastly simpler.
Consider putting your different data in different sections instead of all in one section.
I goofed up. I upgraded to Swift 3.0 with out making a back up now my table view is not loading I know it pulling the data from Firebase but the table view is not loading. I was loading before the update but now no luck.
import UIKit
import Firebase
class ActiveCallsTableViewController: UITableViewController {
let cellId = "callCell"
var users = [User]()
var unAcceptedUsers = [User]()
var enRoute = [User]()
var onSite = [User]()
var isFiltered = Bool()
let section = ["Unaccepted", "Enroute", "Onsite"]
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(handleCancel))
tableView.register(UserCell.self, forCellReuseIdentifier: cellId)
fetchUser()
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
print("titleForHeader")
return self.section[section]
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
}
/// Returns the amount of minutes from another date
func fetchUser() {
print("This is fetchUser")
FIRDatabase.database().reference().child("Calls").observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject]{
let user = User()
user.setValuesForKeys(dictionary)
self.users.append(user)
if user.Job_Status == "Unaccepted" {
self.isFiltered = true
self.unAcceptedUsers.append(user)
print("\(user.Name) True")
}else if user.Job_Status == "Enroute"{
self.isFiltered = false
self.enRoute.append(user)
print("\(user.Name) False")
}else{
self.onSite.append(user)
}
//print(self.user)
//DispatchQueue.main.asynchronously(execute: {self.tableView.reloadData()})
DispatchQueue.main.async (execute: { self.tableView.reloadData()
print("Later in fetchUser")
})
}
}, withCancel: nil)
}
func handleCancel() {
dismiss(animated: true, completion: nil)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//var rowCount: Int
print(" This is numbers Of Rows")
if section == 0 {
//rowCount = unAcceptedUsers.count
print(unAcceptedUsers.count)
return unAcceptedUsers.count
}
else if section == 1{
return enRoute.count
//rowCount = enRoute.count
}else {
return onSite.count
}
//return rowCount
}
func userForIndexPath(indexPath: NSIndexPath) -> User {
if indexPath.section == 0 {
// print(unAcceptedUsers)
return unAcceptedUsers[indexPath.row]
}
print(enRoute)
return unAcceptedUsers[indexPath.row]
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//print("Call Cell")
//let cell = UITableViewCell(style: .Subtitle, reuseIdentifier: cellId)
print("CellForRow")
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath as IndexPath)
let user:User
//let user = userForIndexPath(indexPath)
if indexPath.section == 0 {
user = unAcceptedUsers[indexPath.row]
}else if indexPath.section == 1{
user = enRoute[indexPath.row]
}else{
user = onSite[indexPath.row]
}
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = .short
let date3 = dateFormatter.date(from: user.Time_Logged!)
print("THE TIME IS \(date3)")
let elapesedTime = NSDate().timeIntervalSince(date3!)
//let minutesPassed = (elapesedTime / 3600)
//let dateMinutes = NSDate().timeIntervalSinceReferenceDate (date3)
// let calcendar = NSCalendar.currentCalendar()
//let dateComponents = calcendar.components(NSCalendarUnit.Minute, fromDate: date3!, toDate: NSDate(), options: nil)
//let minutesPassed = dateComponents
print ("THE TIME IS \(elapesedTime)")
let duration = Int(elapesedTime)
let minutesLogged = String(duration)
print(duration)
//let user = users[indexPath.row]
cell.textLabel?.text = user.Name
cell.detailTextLabel?.text = minutesLogged
//print(user.Adress)
return cell
}
//var valueToPass:String!
var valueToPass:String!
//var productsValue = [unAcceptedCallDataVie]]
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
let callInfoView:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Callinfo") as UIViewController
let unAcceptedView:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "unAcceptedCall") as UIViewController
let currentCell = tableView.cellForRow(at: indexPath as IndexPath) as UITableViewCell!;
if indexPath.section == 0 {
valueToPass = currentCell?.textLabel!.text
//valueToPass = currentCell2
performSegue(withIdentifier: "passData", sender: self)
self.present(unAcceptedView, animated: true, completion: nil)
//print(valueToPass)
}else if indexPath.section == 1{
self.present(callInfoView, animated: true, completion: nil)
print("Enroute")
}else {
self.present(callInfoView, animated: true, completion: nil)
print("Onsite")
}
// print(user.Adress)
}
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "passData") {
//let user:User
// initialize new view controller and cast it as your view controller
let viewController = segue.destination as! unAcceptedCallDataView
// your new view controller should have property that will store passed value
//var passedValue = viewController.nameLable.text
//print(user.Adress)
viewController.LableText = valueToPass
}
class UserCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder){
fatalError("init(coder:) has not been implemented")
}}}}
`
Try replacing :-
DispatchQueue.main.async (execute:...
To
DispatchQueue.global(qos: .background).async {
self.tableView.reloadData()
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
Im trying to make an app that stores personal details which can be deleted, edited using editActionsForRowAtIndexPath. The delete option seems to work fine but I am having problems with the edit action.
I get an error as I've mentioned below:
Could not cast value of type 'Table_view.UserTableViewController' (0x10a1991b0) to 'NSIndexPath' (0x10a5e8438).
UserRecordViewController is the View Controller where the personal details are to be displayed. And InsertRecordViewController is the other View Controller.
UserTableViewController relevant Code :
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
// 1
let editAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Edit" , handler: { (action:UITableViewRowAction, indexPath:NSIndexPath) -> Void in
self.performSegueWithIdentifier("editSegue", sender: self)
})
editAction.backgroundColor = UIColor.darkGrayColor()
// let editIndex = editAction.indexOfAccessibilityElement(indexPath.row)
let deleteAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Delete" , handler: { (action:UITableViewRowAction, indexPath:NSIndexPath) -> Void in
let userInfo: UserInfo = self.marrUserData.objectAtIndex(indexPath.row) as! UserInfo
let isDeleted = ModelManager.getInstance().deleteUserData(userInfo)
if isDeleted {
Util.invokeAlertMethod("", strBody: "Record deleted successfully.", delegate: nil)
} else {
Util.invokeAlertMethod("", strBody: "Error in deleting record.", delegate: nil)
}
self.getUserData()
})
deleteAction.backgroundColor = UIColor.lightGrayColor()
return [deleteAction, editAction]
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "editSegue"){
let selectedIndexPath = sender as! NSIndexPath
let index = selectedIndexPath.row
//if let indexPath: NSIndexPath = self.tableView.indexPathForCell(sender as! UITableViewCell) {
//let btnEdit : UIButton = sender as! UIButton
//let selectedIndex : Int = btnEdit.tag
let viewController : InsertRecordViewController = segue.destinationViewController as! InsertRecordViewController
viewController.isEdit = true
viewController.userData = self.marrUserData.objectAtIndex(index) as! UserInfo
// }
}
}
I would like to know where I'm going wrong. Any idea guys?
Thanks in advance!!
I had the same exact problem and I was able to solve it by adding a few extra things in the func prepareForSegue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "editSegue"){
let cell = sender as! UITableViewCell
let Path = tableView.indexPathForCell(cell)
let index = Path?.row
let viewController : InsertRecordViewController = segue.destinationViewController as! InsertRecordViewController
viewController.isEdit = true
viewController.userData = self.marrUserData.objectAtIndex(index!) as! UserInfo
// }
}
Now I realize this isn't exactly what you're trying to do. Because with my method you just click on the cell and it directs you immideatly to the path instead of sliding. I wanted to do the slide as well but I couldn't figure it out so I just with with the above method. Hope this helps :)
The line that cause the error is: let selectedIndexPath = sender as! NSIndexPath
Sender is the SelectedCell, not the IndexPath!
Before the line self.performSegueWithIdentifier("editSegue", sender: self) set an property of the class (selectedIndexPath) to indexPath, and then you access this property from prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?).
Another method to do this can be found at: https://developer.apple.com/library/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson9.html#//apple_ref/doc/uid/TP40015214-CH9-SW1
I am using PFQueryTableViewController to retrieve images from Parse.com backend. Later, I want to take a snapshot of swiped row image (using editActionsForRowAtIndexPath).
At this moment, I can retrieve object and create a action on row using editActionsForRowAtIndexPath. The action passes the retrivedObject through a prepareForSegue method to ShareViewController. Once I am on ShareViewController, I can see an image, but it is not the same I clicked to share using editActionsForRowAtIndexPath. It is either the image above or below or sometimes its the same one that i clicked.
Can anyone help me to solve this?
My code is as below:
PFQueryTableViewController
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell") as! DataViewTableViewCell!
if cell == nil {
cell = DataViewTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
}
retrivedObject = object
// Display profile image
let profileThumbnail = UIImage(named: "DProfilePicture")
cell.profilePicture.image = profileThumbnail
if let thumbnail = object?["profilePicture"] as? PFFile {
cell.profilePicture.file = thumbnail
cell.profilePicture.loadInBackground()
}
// Display main image
let initialThumbnail = UIImage(named: "DefaultImage")
cell.picture.image = initialThumbnail
if let thumbnail = object?["picture"] as? PFFile {
cell.picture.file = thumbnail
cell.picture.loadInBackground()
}
//........
}
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
print("EDIT MODE INDEX: \(indexPath.item)")
let Share = UITableViewRowAction(style: .Normal, title: "Share") { action, index in
print("Share button tapped")
self.performSegueWithIdentifier("ShareImage", sender: self)
}
Share.backgroundColor = UIColor.blackColor()
return [Share]
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.destinationViewController is ShareViewController {
let vc = segue.destinationViewController as! ShareViewController
vc.selectedObject = retrivedObject
}
}
ShareViewController
var selectedObject: PFObject!
var sharedImage: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidAppear(animated: Bool) {
if selectedObject == nil {
return
}
if let file = selectedObject["picture"] as? PFFile {
file.getDataInBackgroundWithBlock({ (data, error) -> Void in
if data != nil {
self.sharedPicture.image = UIImage(data: data!)
self.screenShotMethod()
}
})
}
}
#IBAction func cancelBtn(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func shareBtn(sender: AnyObject) {
let vc = SLComposeViewController(forServiceType: SLServiceTypeFacebook)
vc.setInitialText("Look at this great picture!")
vc.addImage(sharedImage)
self.presentViewController(vc, animated: true, completion: nil)
}
func screenShotMethod() -> UIImage {
//Create the UIImage
UIGraphicsBeginImageContextWithOptions(self.shareView.frame.size, true, 2.0 )
self.shareView.drawViewHierarchyInRect(CGRect(x: 0, y: 0, width: self.shareView.bounds.width, height: self.shareView.bounds.height), afterScreenUpdates: false)
view.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
sharedImage = image
return sharedImage
}
The problem is your use of retrivedObject. By setting retrivedObject = object it is always set to the last object (cell) displayed. It is not related to the user selection.
When you create the share action you should set
self.performSegueWithIdentifier("ShareImage", sender: index)
so that in the prepareForSegue function you can use the index (which is the sender) to get the true selected object.