0

I have like a social app with a sort of newsfeed. if u click on the users name from a post in the newsfeed, you will go to his profile. Now i can't retrieve the data from that specific cell/post to the other viewController. so i have to display the user's profile, with he's username, etc. but that doesn't work?

i have a Post model:

class Post {
    private var _postDescription: String!
    private var _profileImageURL: String?
    private var _likes: Int!
    private var _username: String!
    private var _postKey: String!
    private var _timeStamp: String!
    private var _postRef: Firebase!

    var postDescription: String? {
        return _postDescription
    }

    var likes: Int {
        return _likes
    }

    var username: String {
        return _username
    }

    var postKey: String {
        return _postKey
    }

    var profileImageURL: String? {
        return _profileImageURL
    }

    init(description: String, username: String, profileImageURL: String?) {
        self._postDescription = description
        self._username = username
        self._profileImageURL = profileImageURL
    }

    init(postKey: String, dictionary: Dictionary<String, AnyObject>) {
        self._postKey = postKey

        if let likes = dictionary["likes"] as? Int {
            self._likes = likes
        }

        if let desc = dictionary ["description"] as? String {
            self._postDescription = desc
        }

        if let imgUrl = dictionary["profileImg"] as? String {
            self._profileImageURL = imgUrl
        }

        if let user = dictionary ["username"] as? String {
            self._username = user
        } else {
            self._username = ""
        }

        self._postRef = DataService.ds.REF_POST.childByAppendingPath(self._postKey)
    }

} 

this is my profileVC:

class ProfileVC: UIViewController {

    @IBOutlet weak var username: UILabel!

    var post: Post?

    override func viewDidLoad() {
        super.viewDidLoad()

            username.text = post.username // gives me a nil error.  
    }
}

and i use a TapGestureRecognizer in my tableViewCell to perform the segue. in my cellForRowAtIndexPath:

let profileLblTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(NewsVC.goToProfileScreen(_:)))
        profileLblTapRecognizer.numberOfTapsRequired = 1
        profileLblTapRecognizer.delegate = self

    cell.usernameLabel.tag = indexPath.row
    cell.usernameLabel.userInteractionEnabled = true
    cell.usernameLabel.addGestureRecognizer(profileLblTapRecognizer)

and the goToProfileScreen function:

func goToProfileScreen(gesture: UITapGestureRecognizer) {
        self.performSegueWithIdentifier("ProfileScreen", sender: self)

    }

this is my datamodel on firebase: enter image description here

UPDATE:

i tried this instead:

let profileLblTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(NewsVC.prepareForSegue(_:sender:)))

with this function:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "ProfileScreen" {
            if let cell = sender as? NewsCell, row = tableView.indexPathForCell(cell)?.row, vc = segue.destinationViewController as? ProfileVC {
                vc.post = posts[row]

            }

        }


    }

but that gave me an error on appDelegate: Thread 1: EXC_BAD_ACCESS(code=1, address = 0x1)

adams.s
  • 185
  • 1
  • 14

1 Answers1

1

I've added this as an answer rather than a comment so that I can add and format some code examples.

When you call performSegueWithIdentifier, a NEW instance of the view controller identified by that segue is created, so all of its properties will be their defaults.

You have two ways of instantiating this view controller and setting properties before it loads. The first is the prepareForSegue option, in your case it may look something like this:

override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
    if (segue.identifier == "ProfileScreen") {
        let vc = segue.destinationViewController as! ProfileVC
        vc.post = post
    }
}

Another option is to create and present the view controller yourself, this example uses a storyboardID

let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = mainStoryboard.instantiateViewControllerWithIdentifier("profileVC") as! ProfileVC
vc.post = post

presentViewController(vc, animated: false, completion: nil)

Update:

I'm not sure why you are adding a tap gesture recogniser to this, you could just use didSelectRowAtIndexPath, have a look at this other question and answer

you could have a property on your table view controller called selectedItem or something similar. and then in didSelectRowAtIndexPath set selectedItem to the item at the current index. Then in prepare for segue you would just do vc.post = selectedItem

Update Two:

After the op sharing their code privately, I noticed that the issue is that the user is using tapGestureRecogniser in the tableView. I added some code into the called function to get the row in which contained the tapped view, once I had the indexPath it was then easy to store it in a temporary property and retreive later in the prepareForSegue method, details below

// temp property
var selectedPost:Post?

// function called on tap
func viewProfile(sender:UITapGestureRecognizer) {

    if (sender.state == UIGestureRecognizerState.Ended) {
        let point = sender.locationInView(self.tableView)
        if let indexPath = self.tableView.indexPathForRowAtPoint(point) {
            selectedPost = self.posts[indexPath.row]
            performSegueWithIdentifier("ProfileScreen", sender: self)
        }
    }
}

// Prepare for segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if (segue.identifier == "ProfileScreen") {
        let vc = segue.destinationViewController as! ProfileVC
        if let post = selectedPost {
            vc.post = post
        }
    }
}
Community
  • 1
  • 1
Scriptable
  • 19,402
  • 5
  • 56
  • 72
  • the vc.post = post // which is the second post for you? is it like post: Post! or var post = [Post]() i'm trying now with creating and presenting the view controller – adams.s May 10 '16 at 10:19
  • yeah i use it because i have 3 clickable things in one cell. a button, and a profileImage and a profile username label. so i use tapGestureRecognizer for the click on the profileImg and usernameLbl.. i tried your second option but then my navigation bar and tabbar disappears. also the username label is just empty. while i do say in mij profileVC username.text =post.username – adams.s May 10 '16 at 10:28
  • it still gives me a nil if i print this. – adams.s May 10 '16 at 10:30
  • the prepare for segue method should work for you, i have used it in a similar way alot of times. if you could share the code on github or privately I will have a look and find the issue for you. – Scriptable May 10 '16 at 10:33
  • how can i send it privately? :) – adams.s May 10 '16 at 10:36
  • share with user scriptable on github or bitbucket (same username on both) – Scriptable May 10 '16 at 10:49
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/111519/discussion-between-adams-s-and-scriptable). – adams.s May 10 '16 at 10:49