Accessing <status> properties

136 views
Skip to first unread message

Niems

unread,
Feb 21, 2012, 11:45:57 AM2/21/12
to XMPPFramework
Hi all,

I hope this is a no brainer for you guys, but I'm having a little
issue with accessing the status field of a roster item's presence.

I basically have the framework up and working a la Xcode project
included with the repository. As it stands, presence information is
correctly received, and roster items are updated under the 'available'
group whenever a change occurs. (Note: the protocol we are using only
uses available|offline presences at the moment).

Now I want to take it one step further and be able to display the
status of an item in the detailTextField of the table cells.

I noticed that the status property is available via a relationship
access (XMPPUserCoreDataStorageObject --> primaryResource). I can get
this field just fine, but if I read the field in my view controller,
the available|offline grouping breaks completely, i.e. online items
will stay online even if their presence changes. The status field
shown in the detailTextField will continue to update as per normal
though.

It seems no matter how I access the field and what I do with it, the
cells lose their ability to change table group after a roster item
comes online / is already online.

I have tried accessing the field by using:
- user.primaryResource.status
- user.primaryResource.presence.status
- copies of the above

To to reiterate: I'm getting and outputting the status information
just fine, but accessing it via cellForRowAtIndexPath causes the
roster items to be stuck in the 'online' group if they a) come online
from being offline, b) were online to begin with.

I hope this is all clear. Any help is greatly appreciated!

Regards,
Niems

Eric Chamberlain

unread,
Feb 21, 2012, 8:21:22 PM2/21/12
to xmppfr...@googlegroups.com
Can you post your view controller, what you are trying to do is unclear?

Eric Chamberlain

> --
> You received this message because you are subscribed to the Google Groups "XMPPFramework" group.
> To post to this group, send email to xmppfr...@googlegroups.com.
> To unsubscribe from this group, send email to xmppframewor...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/xmppframework?hl=en.
>

Matthew Niemann

unread,
Feb 22, 2012, 2:07:05 AM2/22/12
to xmppfr...@googlegroups.com
Basically, I have a tabbed application accessed from a login screen. One of these tabs holds the tableviewconstroller for my 'XMPP friends'.

I'm simply trying to extended the information presented to the user to include status information about his/her friends, and display that in the detailTextLabel of my table cells (I'm using 'subtitle' style cells). Think of it being exactly the same as the reference project (which I have followed as my own reference) extended with status fields for each cell.

The ONLY method I have changed code-wise is in the following:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"friendCell"; //just a subtitle style cell


UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                      reuseIdentifier:CellIdentifier];
}


XMPPUserCoreDataStorageObject *user = [[self fetchedResultsController] objectAtIndexPath:indexPath];


    

    cell.textLabel.text = user.displayName;

    cell.detailTextLabel.text = user.primaryResource.status//this is added, and breaks available/offline presence

    [self configurePhotoForCell:cell user:user];


return cell;
}

If I comment that added line out, online/offline presence works as normal.

I hope this clears things up. Let me know if you need anything more from the viewcontroller.

Thank you!

Regards,
Niems

Eric Chamberlain

unread,
Feb 22, 2012, 10:51:31 PM2/22/12
to xmppfr...@googlegroups.com
Have you tried using user.sectionNum, that's updated when the user state changes and what the NSFetchedResultsController users to sort the users.
--
Eric Chamberlain, Founder
RingFree Mobility Inc.

Matthew Niemann

unread,
Mar 12, 2012, 5:29:01 PM3/12/12
to xmppfr...@googlegroups.com
OK, so after coming back to this issue, I have discovered some new things:

- When we receive a presence update of 'unavailable', we remove the resource object associated with it.

- Obviously this resource object contains some information which I use in my table (the status field)

- Testing to see if the status resource is nil after the presence update, I get nil, which I understand as the resource having been correctly deleted.

- After the presence update to unavailable, the roster item DOES have the correct sectionNum (2), but continues to reside in its old section (0 or 1).

- In 'titleForHeaderInSection', the number of sections returned by the fetchedResultsController is incorrect. I tested this with a roster of 2 items:
 1. both items start off as offline. --> numberOfSections is 1
 2. roster item 1 comes online. --> numberOfSections is 2
 3. roster item 1 goes offline. --> numberOfSections is 2 (obviously incorrect)

Just to refresh your memory, the above occurs when ANY attempt at reading the resource is made.
This even happens if testing "if (user.primaryResource != nil)" before any further reading is done!
I am performing these reads in cellForRowAtIndexPath.

I am completely at a loss as to why this is occurring. The only thing I can think of is that by reading the value from the resource object somehow keeps a strong pointer to the viewcontroller, so when it is "deleted", it isn't really deleted because the persistentcoordinator thinks there is something still 'using' it. I even set the cell label's text to nil to ensure that its not pointing to anything if it detects a user with a nil primaryResource.

    if (user.primaryResource != nil) cell.detailTextLabel.text = user.primaryResource.status;
    else cell.detailTextLabel.text = nil;


I hope I'm providing enough information here. Unfortunately, I am still an amateur when it comes to CoreData, so trying to trace the steps is quite a challenge.

As far as I can see, it is simple enough to reproduce. All you need to to simply read a roster item's resource. Then, on the other device, go 'unavailable', and hopefully you'll see the item stuck in the wrong section. (funny how you say hopefully in the case of producing a reproducible bug).

Regards,
Niems

Eric Chamberlain

unread,
Mar 16, 2012, 1:31:26 PM3/16/12
to xmppfr...@googlegroups.com
It is unclear what you are trying to do and what problem you are having, post your code.

Robbie Hanson

unread,
Mar 18, 2012, 11:37:35 PM3/18/12
to xmppfr...@googlegroups.com
Posting the code would certainly help. There are a couple possibilities. First, it's possible something in the code is marking the user or resource as 'dirty', and depending on the configuration of the managedObjectContext of the main thread, may cause it to persist. We'd need to step through various parts of the code to check.

Second, there could be a bug in fetchedResultsController. I've discussed some of these "hideous" bugs in past blog posts. Not sure if they still exist as they did in prior OS releases, but the point is there could still be bugs.

-Robbie Hanson
Sent from my iPhone

Matthew Niemann

unread,
Mar 19, 2012, 7:39:33 AM3/19/12
to xmppfr...@googlegroups.com
I'm sorry guys, but I'm unsure about what code to paste? I have provided the code I used in previous mails. The only issue I have is still with that one liner:

if (user.primaryResource != nil) cell.detailTextLabel.text = user.primaryResource.status;
    else cell.detailTextLabel.text = nil;

Other than the code above, you can consider my application to be exactly the same as the demo project. I am only using the XMPPFramework as a single module in my app, and I have left it largely untouched from the demo code aside some some statements to add and remove roster items. My requirements aren't to extend the functionality largely, so I have hardly added anything in that regard.

In actual fact, I added that same one liner to the demo app and the same thing happens.

To try make this as clear as possible:

- IF I perform a read on XMPPUserCoreDataStorageObject --> primaryResource --> status ,
THEN the UITableView SECTION for that XMPPUserCoreDataStorageObject becomes STATIC, i.e it will NOT change section regardless of presence (available, away, offline).
- More precisely, an XMPPUserCoreDataStorageObject can go from OFFLINE to ONLINE / AWAY, but never back to OFFLINE

I'm pretty convinced now that this may be a bug with the FRC. I have actually switch over to the memory storage system and checking out what it can do. I know it's rather silly to change over a 'status' field, but my clients require it nonetheless.

Thank you!

Regards,
Niems

Matthew Niemann

unread,
Mar 19, 2012, 8:33:31 AM3/19/12
to xmppfr...@googlegroups.com
Hi again,

Just to give an update:

I can safely say that there is a method you can try to reproduce this bug:

  1. Open up the demo project
  2. In RootViewController --> cellForRowAtIndexPath, add: cell.detailTextLabel.text = user.primaryResource.status;
  3. (You may have to change the cell style to UITableViewCellStyleSubtitle)
  4. Run the project
  5. On a different client which has the open project as a buddy, go online, then offline.

That should hopefully show you it getting stuck.

I have hunted the culprit statement to this problem, located in

- (void)updateWithPresence:(XMPPPresence *)presence streamBareJidStr:(NSString *)streamBareJidStr

in the XMPPUserCoreDataStorageObject.m file.
The statements:

if (resource)
{
        [self removeResourcesObject:resource];
[[self managedObjectContext] deleteObject:resource]; //problem?
}

remove the resource when a user goes offline. If you comment out the second call, [[self managedObjectContextdeleteObject:resource], then the roster will behave as expected! But obviously this isn't desirable  as we now have a coredata leak. I know it's not much enlightenment, but maybe you guys will understand why this delete call is causing the issue.
Just out of interest, I believe the call to 'removeResourcesObject' is unnecessary, as the delete rule is Nullify as it stands. Nonetheless, removing it while keeping the call to deleteObject continues to cause issues :(

Regards,
Niems

Robbie Hanson

unread,
Mar 24, 2012, 12:30:06 PM3/24/12
to xmppfr...@googlegroups.com
Very perplexing. Looking forward to investigating this. Quick question: what version of iOS are you testing this on?


-Robbie Hanson
Sent from my iPhone

Matthew Niemann

unread,
Mar 25, 2012, 12:07:18 PM3/25/12
to xmppfr...@googlegroups.com
I am currently using iOS 5.0.1

I am currently undecided whether to upgrade to 5.1 yet...

Robbie Hanson

unread,
Mar 28, 2012, 4:21:04 AM3/28/12
to xmppfr...@googlegroups.com
I'm able to reproduce the issue on 5.1.
Very bizarre… I'll try to spend some more time tomorrow researching this and see what I can find.

-Robbie Hanson

Matthew Niemann

unread,
Apr 11, 2012, 5:29:13 AM4/11/12
to xmppfr...@googlegroups.com
Hi Robbie,

I'm not sure if you've managed to track down the culprit in this issue yet, but I did notice an issue posted about 3 months ago by someone who appears to have the same issue.


He posts a new section of code which he claims sorts out his issue, although his code doesn't include a 'deleteObject' call which makes me wonder whether there is a persistent storage leak there.

Just thought I'd share in case we missed this!

Regards,
Niems

Robbie Hanson

unread,
Apr 11, 2012, 11:50:30 AM4/11/12
to xmppfr...@googlegroups.com
I did start looking at it, but hadn't figured it out. Thanks for the info!


-Robbie Hanson
Sent from my iPhone
Reply all
Reply to author
Forward
0 new messages