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
Brayden Kness
12,492 PointsAdding To The self Destructing Message App
Is there any way to display the sender name with a different icon indicating that the file has been opened in the table view cell after the message has been opened the table view cell would show the sender name and new icon but nothing will happen when clicked on
11 Answers
Ben Jakuben
Treehouse TeacherThat's a cool idea. As of right now, the message is deleted from Parse.com, so there is no way to show it. You could save the message information on Parse.com or locally on the device.
If you save the message on Parse.com, perhaps you could add a new field called something like "recipientIdsRead". Then instead of deleting the message, you could move the recipientID for the user from the recipientIds field to this new field. When loading the inbox, you'd have to perform a separate query to search this field, and if a message is found, show it but disable it. You could break this up into small tasks - first make sure the ID gets copied over correctly instead of deleted, then add the query to the inbox and make sure it shows up, and then disable the item for tapping.
Alternatively, you could store the message within the app and display it as a read-only entry. In this case you wouldn't modify the backend at all, but once it was tapped move it into local storage or memory so that you can retrieve it and display it as read-only.
It's a bit of work, but a cool idea, so hopefully you try it out because I think you would learn a lot. :)
Brayden Kness
12,492 PointsHow would I move the recipientId to recipientIdRead?
Ben Jakuben
Treehouse TeacherWhat makes this easy is that Parse.com is super dynamic. It will handle pretty much whatever you throw at it. Check out this (untested) code:
NSMutableArray *recipientIds = [NSMutableArray arrayWithArray:[self.selectedMessage objectForKey:@"recipientIds"]];
NSMutableArray *recipientIdsRead = [NSMutableArray arrayWithArray:[self.selectedMessage objectForKey:@"recipientIdsRead"]];
[recipientIds removeObject:[[PFUser currentUser] objectId]];
[recipientIdsRead addObject:[[PFUser currentUser] objectId]];
[self.selectedMessage setObject:recipientIds forKey:@"recipientIds"];
[self.selectedMessage setObject:recipientIdsRead forKey:@"recipientIdsRead"];
[self.selectedMessage saveInBackground];
Use something like this instead of the part of didSelectRowAtIndexPath that currently just removes the ID or deletes the message. "recipientIdsRead" won't exist when you first run this, but Parse will just add a new field for you. Then when you do setObject:recipientIdsRead forKey:@"recipientIdsRead" it will store the new array in that field.
The other piece of this is that you need to update retrieveNewMessages to also query for rows where the objectId is in this new field. Check out this (again, untested) code:
PFQuery *query = [PFQuery queryWithClassName:@"Messages"];
[query whereKey:@"recipientIds" equalTo:[[PFUser currentUser] objectId]];
PFQuery *queryRead = [PFQuery queryWithClassName:@"Messages"];
[query whereKey:@"recipientIdsRead" equalTo:[[PFUser currentUser] objectId]];
PFQuery *queryTogether = [PFQuery orQueryWithSubqueries:@[query, queryRead]];
[queryTogether orderByDescending:@"createdAt"];
[queryTogether findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
...
That should get you all the messages, both new and read. The final piece is to disable the "read" messages. So in cellForRowAtIndexPath, you'd need to maybe indicate that the message was read, and then in didSelectRowAtIndexPath you'd need to skip all that code for these "read" messages.
Hope this helps! Again, it'll take a bit of work to get this correct, but it's a great idea!
Brayden Kness
12,492 PointsOk so I used what you showed me and the recipientIds have been successfully moved into recipientsIdsRead on parse the recipientIds field is empty and the recipientsIdsRead has all of the ids I'm not sure what to do from here though
Ben Jakuben
Treehouse TeacherSounds like you're on the right track! At this point you need to update the Inbox to also look for messages based on recipientIdsRead and not just recipientIds. The 2nd half of my previous post (with query, queryRead, and queryTogether) should give you a starting point on how to get the messages, but post back if you have trouble with them.
Brayden Kness
12,492 PointsWhat does the queryTogether do?
Ben Jakuben
Treehouse Teacher'query' is the regular one we are using that checks for new messages.
'queryRead' is a new one that checks for messages that have already been read.
'queryTogether' joins the two together to get one set of results. The results can then be displayed in the list. In cellForRowAtIndexPath you'll need to check each result to see if it's new or already read and then handle the table view cell accordingly.
Brayden Kness
12,492 PointsHow would you determine whether or not the user has opened the message. I tried this but it didn't work...
if ([self.selectedMessage objectForKey:@"recipientsIdsRead"] == [[PFUser currentuser] objectId]) {}
Am I close?
Ben Jakuben
Treehouse TeacherLooks close! First, there might be a typo: you have "recipientsIdsRead", which has an extra "s" compared to what we were using before.
Then, [self.selectedMessage objectForKey:@"recipientIdsRead"] should give you an NSArray of object ID strings. So you would need to check if the array contains [[PFUser currentUser] objectId] instead of the straight equality check that you have (because the array won't equal a single string ID).
Brayden Kness
12,492 PointsI made that typo a long time ago so thats what I've been using the whole project but what do you mean by "check if the array contains [[PFUser currentUser] objectId] instead of the straight equality check that you have"?
Ben Jakuben
Treehouse TeacherThe code you have there is trying to compare a string value with an array variable. objectForKey:@"recipeintsIdsRead" gives you a whole array.
So instead, you'll need to check each of the items in the array. There is a containsObject method that might work, but if not, you could loop through the array like we do for the isFriends method in EditFriendsViewController:
- (BOOL)isFriend:(PFUser *)user {
for(PFUser *friend in self.friends) {
if ([friend.objectId isEqualToString:user.objectId]) {
return YES;
}
}
return NO;
}
Brayden Kness
12,492 PointsSo like this
- (BOOL)isRead:(PFUser *)user {
for(PFUser *idsRead in self.idsRead) {
if ([idsRead.objectId isEqualToString:user.objectId]) {
return YES;
}
}
return NO;
}
Ben Jakuben
Treehouse TeacherThat looks like it would work! I would change the name "idsRead" for your PFUser variable to something more meaningful, though, like "aUser" or "readUser".
Brayden Kness
12,492 PointsI used the containsObject method instead and it kind of works but its pretty glitchy is there any way I can send you the whole project?
Ben Jakuben
Treehouse TeacherSure thing! I can't promise a quick turnaround for help above and beyond the course material, but I'd be happy to take a look. :) Email it to help@teamtreehouse.com and ask that it be forwarded to me.
Brayden Kness
12,492 PointsOk I sent it
Brayden Kness
12,492 PointsBrayden Kness
12,492 PointsHow would I move the recipientId to recipientIdRead?