0

I'm trying to add a feature to my group chat app where if an avatar is tapped on, you will be brought to a profile page which has information about that user. The framework I'm using (JSQMesssagesViewController) has a built in method for tapping the avatar, didTapAvatarImageView.

override func collectionView(_ collectionView: JSQMessagesCollectionView!, didTapAvatarImageView avatarImageView: UIImageView!, at indexPath: IndexPath!) {

    let message = messages[indexPath.item]

    DispatchQueue.main.async {
        let profileVC = ProfileViewController()
        let name = message.senderDisplayName ?? ""
        let gender = self.genderDictionary.value(forKey: message.senderId) as? String ?? ""
        let status = self.statusDictionary.value(forKey: message.senderId) as? String ?? ""
        let avatarString = self.avatarDictionary.value(forKey: message.senderId) as? String ?? ""

        print("\n\nsegueTest: name: \(name), gender: \(gender), avatar: \(avatarString), status: \(status)\n\n")

        profileVC.profileImageView.loadImageUsingCacheWithUrlString(avatarString)
        profileVC.nameLabel.text = name

        switch gender {
        case "male":
            profileVC.nameLabel.textColor = UIColor(hexString: "8097E1")
        case "female":
            profileVC.nameLabel.textColor = UIColor(hexString: "E98BD5")
        default:
            profileVC.nameLabel.textColor = UIColor(hexString: "4F4F4F")
        }

        switch status {
        case "2FCB78":
            profileVC.profileGoingOutLabel.text = "\(name) wants to go out tonight!"
        case "E13F34":
            profileVC.profileGoingOutLabel.text = "\(name) is staying in tonight."
        default:
            profileVC.profileGoingOutLabel.text = "\(name) might want to go out tonight - let them know what the plans are!"
        }

        self.performSegue(withIdentifier: "chatToProfile", sender: self)
    }
}

When I tap on an avatar, I get the unexpectedly found nil crash - but my print statement prints the values with no problem, so they do exist. I'm not sure where I'm going wrong here, as Xcode does not show me which value in nil, and as I said the values I'm trying to pass do indeed exist.

What can I do to solve this error?

KingTim
  • 1,281
  • 4
  • 21
  • 29
  • in which line your code broken ? – KKRocks Jun 06 '17 at 18:26
  • That's the problem, Xcode doesn't highlight a problematic line. It just crashed with the unexpectedly found nil error and shows me a page which, as a beginner, looks like Matrix code. – KingTim Jun 06 '17 at 18:28
  • can you add exception break point to your project. so you can find specific line where your code actually broken ? – KKRocks Jun 06 '17 at 18:29
  • If I comment out all the code in that method except for `self.performSegue(withIdentifier: "chatToProfile", sender: self)`, the profile view is presented just fine, albeit without the avatar/name etc. and since my print statement shows that all the values (name, avatar, gender, status) have values, it leads me to believe that the problem lies in `let profileVC = ProfileViewController()`. But as far as I know that's the proper way of doing it - insatiate an instance of the view controller then access its values. – KingTim Jun 06 '17 at 18:31
  • 1
    1. You're creating your view controller wrong since it's created in your storyboard so you have to instantiate it with the `UIStoryboard` method. 2. You're accessing your IBOutlets before the profile vc's view has loaded so they are nil. 3. The whole thing is pointless because you are creating a view controller and then throwing it away at the end of the method since performing your segue creates a new view controller and you have to pass your data in `prepareForSegue` – dan Jun 06 '17 at 18:32
  • See: https://stackoverflow.com/questions/5210535/passing-data-between-view-controllers – dan Jun 06 '17 at 18:34
  • If you're creating your view controller from storyboard, you will need to call: THE_STORYBOARD.instantiateViewController(withIdentifier: "ProfileViewController") instead of ProfileViewController(). – hoang Cap Jun 06 '17 at 18:34
  • @dan So I should pass everything in `prepareForSegue`? Thats fine, but how do I pass those specific values (name, avatar, etc) into `prepareForSegue`? I need to get the values in the collection view method because I need the indexPath to figure out which avatar was tapped on. – KingTim Jun 06 '17 at 18:34
  • You can store the message in a property and access it in `prepareForSegue` or just pass the message or index path as the `sender` – dan Jun 06 '17 at 18:36
  • you need to pass string to profileVC instead of set label text here . – KKRocks Jun 06 '17 at 18:38

1 Answers1

1

you need to declare string property for all label which is displayed to through previous view controller in profileVC.

var strName : String

In viewDidLoad

nameLabel.text = strName

In previous viewcontroller

profileVC.strName = yourstring

If use prepareForSegue then you need to pass data in this method instead of didSelect.

If you want to pass data on didSelect without prepareForSegue then you need to create instance of viewcontroller as below.

Correct following code it is only for explanation

let profileVC = self.storyboard.initiatedwithidentifier: "yourViewcontrollerIdentifier"
profileVC.strName = yourString
self.navigationviewcontroller(profileVc, animated : true) 
KKRocks
  • 8,222
  • 1
  • 18
  • 84
  • Thanks, I ended up doing something similar. Made some class variables for the values (name, avatar etc) in both the chat controller and profile controller, then set the values in the `didTapImage` method and set them equal to the chat controller class variables. Then in `prepareForSegue`, set the profile controller variables equal to the chat controller variables. – KingTim Jun 06 '17 at 19:03
  • is you need prepareForSegue method ? – KKRocks Jun 06 '17 at 19:05