问题
I have integrated xmpp in my app and able to list all the users in a table view, but I only want to display the online users and then want to implement the feature to send and recieve messages to my online friends...
Please suggest me some helpful code...
Here is my code, executed after facebook login.
- (void)fbDidLogin
{
NSLog(@"logged in.....................");
[appDelegate.facebook requestWithGraphPath:@"me" andDelegate:self];
DDLogVerbose(@"%s accessToken: %@ expirationDate: %@",__PRETTY_FUNCTION__,appDelegate.facebook.accessToken,appDelegate.facebook.expirationDate);
self.accessToken = appDelegate.facebook.accessToken;
if (xmppStreamFB) {
[xmppStreamFB release];
xmppStreamFB = nil;
}
xmppStreamFB = [[XMPPStreamFacebook alloc] init];
xmpReconnect = [[XMPPReconnect alloc] initWithStream:xmppStreamFB];
if (xmppRosterStorage) {
[xmppRosterStorage release];
xmppRosterStorage = nil;
}
xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] init];
if (xmppRoster) {
[xmppRoster release];
xmppRoster = nil;
}
xmppRoster = [[XMPPRoster alloc] initWithStream:xmppStreamFB rosterStorage:xmppRosterStorage];
[xmppStreamFB addDelegate:self];
[xmppRoster addDelegate:self];
[xmppRoster setAutoRoster:YES];
xmppStreamFB.myJID = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@chat.facebook.com", uid]];
// You may need to alter these settings depending on the server you're connecting to
allowSelfSignedCertificates = NO;
allowSSLHostNameMismatch = YES;
// Uncomment me when the proper information has been entered above.
NSError *error = nil;
if (![xmppStreamFB connect:&error])
NSLog(@"Error connecting: %@", error);
if(!tableView)
{
tableView = [[UITableView alloc]initWithFrame:CGRectMake(0,0, 480, 320) style:UITableViewStylePlain];
}
[tableView setFrame:CGRectMake(0,0, 480, 320)];
[tableView setTag:2];
[tableView setDelegate:self];
[tableView setDataSource:self];
[tableView setHidden:NO];
[tableView setBackgroundColor:[UIColor clearColor]];
[tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
[tableView setAlpha:1.0];
[self.view addSubview:tableView];
[self.tableView reloadData];
[self showTopBar];
}
I don't know the actual flow of the xmpp framework for showing users online and to implement chat feature...
i have the following delegate methods as well..
- (void)xmppStreamDidSecure:(XMPPStreamFacebook *)sender
{
NSLog(@"---------- xmppStreamDidSecure: ----------");
}
- (void)xmppStreamDidConnect:(XMPPStreamFacebook *)sender
{
NSLog(@"---------- xmppStreamDidConnect: ----------");
isOpen = YES;
NSError *error = nil;
if (![self.xmppStreamFB authenticateWithAppId:_APP_ID accessToken:self.accessToken error:&error])
{
NSLog(@"Error authenticating: %@", error);
}
else {
NSLog(@"NO Error authenticating:");
/*
ChatViewController *cvc = [[ChatViewController alloc] init];
[self.view addSubview:cvc.view];*/
}
}
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
NSLog(@"---------- xmppStreamDidAuthenticate: ----------");
[self goOnline];
}
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error
{
NSLog(@"---------- xmppStream:didNotAuthenticate: ----------");
}
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
{
NSLog(@"---------- xmppStream:didReceiveIQ: ----------");
/*
ChatViewController *cvc = [[ChatViewController alloc] init];
[self.view addSubview:cvc.view];*/
return NO;
}
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
NSLog(@"---------- xmppStream:didReceiveMessage: ----------");
}
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence
{
NSLog(@"---------- xmppStream:didReceivePresence: ----------");
}
- (void)xmppStream:(XMPPStream *)sender didReceiveError:(id)error
{
NSLog(@"---------- xmppStream:didReceiveError: ----------");
}
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender
{
NSLog(@"---------- xmppStreamDidDisconnect: ----------");
if (!isOpen)
{
NSLog(@"Unable to connect to server. Check xmppStream.hostName");
}
}
And the two methods for online and offline user presence, but don't know how to modify them for my task:
- (void)goOnline
{
NSXMLElement *presence = [NSXMLElement elementWithName:@"presence"];
[[self xmppStream] sendElement:presence];
}
- (void)goOffline
{
NSXMLElement *presence = [NSXMLElement elementWithName:@"presence"];
[presence addAttributeWithName:@"type" stringValue:@"unavailable"];
[[self xmppStream] sendElement:presence];
}
回答1:
finally after lots of efforts i found out how to show online/offline/away users.
i'm going to tell you step by step how i did it, so that i can be useful for the less experienced users too..
Step 1- on click of chat button i'm calling the following method-
-(void) chatFacebook
{
if (appDelegate.facebook == nil)
{
appDelegate.facebook = [[[Facebook alloc] initWithAppId:_APP_ID] autorelease];
}
if (!accessToken)
{
[appDelegate.facebook authorize:[XMPPStreamFacebook permissions] delegate:self appAuth:NO safariAuth:NO];
}
else
{
[self fbDidLogin];
}
}
step 2- Now its time for login dialog delegate methods to come in , if the login is successfull the fbDidLogin is called, here are the delegate methods you should include-
#pragma mark FBLoginDialogDelegate
/** * Called when the user successfully logged in. */
- (void)fbDidLogin
{
NSLog(@"logged in.....................");
[appDelegate.facebook requestWithGraphPath:@"me" andDelegate:self];
DDLogVerbose(@"%s accessToken: %@ expirationDate: %@",__PRETTY_FUNCTION__,appDelegate.facebook.accessToken,appDelegate.facebook.expirationDate);
self.accessToken = appDelegate.facebook.accessToken;
if (xmppStream) {
[xmppStream release];
xmppStream = nil;
}
xmppStream = [[XMPPStreamFacebook alloc] init];
xmpReconnect = [[XMPPReconnect alloc] initWithStream:xmppStream];
if (xmppRosterStorage) {
[xmppRosterStorage release];
xmppRosterStorage = nil;
}
xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] init];
if (xmppRoster) {
[xmppRoster release];
xmppRoster = nil;
}
xmppRoster = [[XMPPRoster alloc] initWithStream:xmppStream rosterStorage:xmppRosterStorage];
[xmppStream addDelegate:self];
[xmppRoster addDelegate:self];
[xmppRoster setAutoRoster:YES];
xmppStream.myJID = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@chat.facebook.com", uid]];
// You may need to alter these settings depending on the server you're connecting to
allowSelfSignedCertificates = NO;
allowSSLHostNameMismatch = YES;
// Uncomment me when the proper information has been entered above.
NSError *error = nil;
if (![xmppStream connect:&error])
NSLog(@"Error connecting: %@", error);
if(!tableView)
{
tableView = [[UITableView alloc]initWithFrame:CGRectMake(0,0, 480, 320) style:UITableViewStylePlain];
}
[tableView setFrame:CGRectMake(0,0, 480, 320)];
[tableView setTag:2];
[tableView setDelegate:self];
[tableView setDataSource:self];
[tableView setHidden:NO];
[tableView setBackgroundColor:[UIColor clearColor]];
[tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
[tableView setAlpha:1.0];
[self.view addSubview:tableView];
[self.tableView reloadData];
[self showTopBar];
}
/** * Called when the user dismissed the dialog without logging in. */
- (void)fbDidNotLogin:(BOOL)cancelled
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Canceled" message:@"Login cancled" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
/** * Called when the user logged out. */
- (void)fbDidLogout
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Logged out" message:@"Logged out" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
Step 3- The second line of the fbDidLogin method calls the FBRequestDelegate methods so you should include this protocol in your .h class, to get the uid of the user(which is logged in , means the current user) you need to implement the following methods-
pragma mark
pragma mark FBRequestDelegate
- (void)request:(FBRequest*)request didFailWithError:(NSError*)error{
DDLogError(@"%s %@",__PRETTY_FUNCTION__,error);
//[appDelegate.facebook logout:self];
}
/** * Called when a request returns and its response has been parsed into an object. * The resulting object may be a dictionary, an array, a string, or a number, depending * on thee format of the API response. */
- (void)request:(FBRequest*)request didLoad:(id)result {
DDLogVerbose(@"%s............DDLOG................... %@",__PRETTY_FUNCTION__,result);
NSLog(@" Result>>>>-------%@", result);
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:(NSMutableDictionary *)result];
uid = [dict objectForKey:@"id"];
NSLog(@"iddddddddddddd---%@", uid);
}
Step 4- Now comes the table view DataSource and Delegate methods, you need to implement these, here are the methods-
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView1
{
return [[[self fetchedResultsController] sections] count];
// need to implement NSFetchedResultsControllerDelegate }
- (NSString *)tableView:(UITableView *)sender titleForHeaderInSection:(NSInteger)sectionIndex
{ NSArray *sections = [[self fetchedResultsController] sections];
if (sectionIndex < [sections count])
{
id <NSFetchedResultsSectionInfo> sectionInfo = [sections objectAtIndex:sectionIndex];
int section = [sectionInfo.name intValue];
switch (section)
{
case 0 : return @"Available";
case 1 : return @"Away";
default : return @"Offline";
}
}
}
return @"";
}
- (NSInteger)tableView:(UITableView *)tableView1 numberOfRowsInSection:(NSInteger)sectionIndex
{
NSArray *sections = [[self fetchedResultsController] sections];
if (sectionIndex < [sections count])
{
id <NSFetchedResultsSectionInfo> sectionInfo = [sections objectAtIndex:sectionIndex];
return sectionInfo.numberOfObjects;
NSLog(@"section ifnfo ===========%@", sectionInfo);
}
}
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
}
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
[cell setSelectionStyle:UITableViewCellSelectionStyleGray];
user = [[self fetchedResultsController] objectAtIndexPath:indexPath];
cell.textLabel.text = user.displayName;
cell.textLabel.textColor = [UIColor whiteColor];
cell1 = cell;
}
Step 5- Finally you also need to implement NSFetchedResultsController delegate methods , so that you can fill table with the chat users, here are the methods-
- (NSFetchedResultsController *)fetchedResultsController
{
if (fetchedResultsController == nil)
{
NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPUserCoreDataStorage"
inManagedObjectContext:[self managedObjectContext]];
NSSortDescriptor *sd1 = [[NSSortDescriptor alloc] initWithKey:@"sectionNum" ascending:YES];
NSSortDescriptor *sd2 = [[NSSortDescriptor alloc] initWithKey:@"displayName" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sd1, sd2, nil];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entity];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchBatchSize:10];
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:[self managedObjectContext]
sectionNameKeyPath:@"sectionNum"
cacheName:nil];
[fetchedResultsController setDelegate:self];
[sd1 release];
[sd2 release];
[fetchRequest release];
NSError *error = nil;
if (![fetchedResultsController performFetch:&error])
{
NSLog(@"Error performing fetch: %@", error);
}
}
return fetchedResultsController;
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[[self tableView] reloadData];
}
Step 6 - Compile and run your code ,user list should appear in table view
if any problems appears, please share , i'm always here to help you .And please dont mind if there are some mistakes while posting this answer, cz i'm posting just for the third time
Thanks.
来源:https://stackoverflow.com/questions/5300912/how-to-list-only-online-users-on-facebook-with-xmpp-framework