Getting XMPP client chat history between two users - ios

I have created a XMPP Swift Messenger with the eJabbered, but it doesn't save the history.
I searched a lot and could found just answers written in ObjC, in Stack.
For instance:
- (void)loadChatHistoryWithUserName:(NSString *)userName {
NSString *userJid = [NSString stringWithFormat:#"%##%#",userName,self.hostName];
NSManagedObjectContext *moc = [_xmppMsgStorage mainThreadManagedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"XMPPMessageArchiving_Message_CoreDataObject"
inManagedObjectContext:moc];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
[request setEntity:entityDescription];
NSError *error;
NSString *predicateFrmt = #"bareJidStr == %#";
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateFrmt, userJid];
request.predicate = predicate;
NSArray *messages = [moc executeFetchRequest:request error:&error];
}
But I use XMPP Swift Framework with the XMPP ObjC Framework inside. Look at this Git: GitHub
How can I use those snippet in Swift for getting chat history?

If your'e not saving the history locally (i.e. a cache of some sort), then you should probably look into a server plugin that logs the chats and allows you to retrieve them upon connection and login (and entering the relevant room, etc.), if my memory serves me correctly, ejabbered doesn't have that built in (or maybe the payed version does), from my experience Prosody IM server has that plugin and it's pretty easy to setup.
After that, make sure your client side retrieves the history (using a listener, etc.)
Hope this helps.

Related

How to delete a chat message which was saved using xep-0136(Message Archiving)?

I want to provide user a functionality to delete single or multiple messages at a time using long-tap/select action.
I know you want to know what I have tried so far. But the thing is I haven't found anything regarding deleting messages to implement.
Any kind of help is appreciated!
You have to delete message from xmpp core database.
So xmpp had created "XMPPMessageArchiving_Message_CoreDataObject" named core database table and using this you can delete message.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"XMPPMessageArchiving_Message_CoreDataObject" inManagedObjectContext:myAppdelObject.Obj_xmppManager.moc];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *items = [mocObject executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *managedObject in items) {
[mocObject deleteObject:managedObject];
}
#Parthpatel1105's answer is right, though as #Bista says, it will not delete the messages permanently.
After performing the deletion, any deletion, either full deletion as #Parthpatel1105 does, or a single message, which would be the same but without the for loop and you'd have to find the single message to delete. You HAVE to save the storage context.
Which means, after doing:
for (NSManagedObject *managedObject in items) {
[mocObject deleteObject:managedObject];
}
You have to add a call to save,
In Swift (where I've used it):
mocObject.save()
In Objective-C, I think it would be something like:
[mocObject save:&error];

Core Data is deleting records when app crashes

I have an app that saves a lot of data in the phone. I am using the following code:
- (void)datostickets:(NSString*)cod local:(NSString*)nombre{
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *ticket =[NSEntityDescription entityForName:#"History" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:ticket];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(codigo = %#)", cod];
[request setPredicate:pred];
//NSManagedObject *matches = nil;
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if ([objects count] == 0) {
NSManagedObject *nuevoticket = [NSEntityDescription insertNewObjectForEntityForName:#"History" inManagedObjectContext:context];
[nuevoticket setValue:[NSString stringWithFormat:#"%#",cod] forKey:#"codigo"];
[nuevoticket setValue:self.idloc forKey:#"actividad"];
[nuevoticket setValue:nombre forKey:#"localidad"];
NSLog(#"GRABA: %#",cod);
} else {
NSLog(#"VERIFICA");
check++;
}}
It saves fine, but the problem happens if the app crashes (I think it only happen this way, also the app only crashes when I am manipulating the data).
When the app crashes Core Data starts acting really weird, and it deletes the recent data that I saved, but somehow some of the old data is not deleted (apparently when I change of viewController Core Data makes a commit, so this old data is not deleted).
This problem is solved when I navigate trough the app windows and it starts again if the app crashes. I know the problem is pretty weird.
So, is there a way to solve this? maybe there is a commit statement or something like that.
Thanks for the help
Use [context save:&error] to commit changes.
Use context save& error .or if you using magicall records use MR_Save to persistent store and wait method other wise it is Unable to delete data from storage.

Fetch Data from multiple Entities with no relationship between them

I have to fetch data from multiple entities which are associated to different screens of an iPhone App, now the scenario is as follows, when user press a Sync button i will have to fetch data from all these entities (i have about 12 entities) and send all this data to a server via a web service, and all these entities have no relationship among them, now my question is what is the best approach to do this task, should i write 12 different fetch requests in a single method, or is there some other better approach, if any one can guide with some tutorial link, that will me most appreciated, thanx in advance.
You can use a for loop to accomplish your task like this. I've used this code to delete all entries of the Database.
NSArray *allEntities = [[[[UIApplication sharedApplication] delegate] managedObjectModel] entities];
NSError *error;
for (NSEntityDescription *entityDescription in allEntities)
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entityDescription];
fetchRequest.includesPropertyValues = NO;
fetchRequest.includesSubentities = NO;
NSArray *items = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(#"Error requesting items from Core Data: %#", [error localizedDescription]);
}
//Do whatever you need to do here
}

Manage XMPP users with Core Data

I am making chat-app and I looking the way to save and load from core data.
I save and load to it all user's history and it works good.
I am looking the way how can I load and save roster list
I am not sure here. I load user's info from web at startup by getting user's ids from roster list and request web service for that user's info. I want to save it to core data with roster list.
How can I set for every jUser (loaded from core data) his web server info? There are 2 problems here:
I can not get JUser from core data for its id
If I do 1. I can set to that user his web image and data to his core data's storied account. - I think it is not a good idea. How can I manage users here?
Some code:
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController == nil)
{
NSManagedObjectContext *moc = [[self appDelegate] managedObjectContext_roster];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"XMPPUserCoreDataStorageObject"
inManagedObjectContext: moc];
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:moc
sectionNameKeyPath:#"sectionNum"
cacheName:nil];
[_fetchedResultsController setDelegate:self];
NSError *error = nil;
if (![_fetchedResultsController performFetch:&error])
{
//DDLogError(#"Error performing fetch: %#", error);
}
}
return _fetchedResultsController;
}
What you are showing above is for keeping track/getting the info that is populated with a request to the XMPP server for it's roster (be it an autoFetch or a manual fetch using the XMPPRoster 'fetchRoster' method (assuming you have set the CoreData way of storing your roster data, not memory).
Once the response to the roster fetch is returned (iq result), the delegates within the XMPPRoster instance will capture and put in place with the given storage option. If the server you are using conforms to the XMPP rfc, then this should happen pretty automatically on the return.
For example - in XMPPRoster.didReceiveIQ() - you can see the call to '[xmppStorage handleRosterItem:item xmppStream:xmppStream]'. This is where the processed
You can extend the storage here (XMPPRosterCoreDataStorage and XMPPUserCoreDataStorage for example) and set in place to add additional information to the entity. For example here - XMPPUserCoreDataStorage has an over-ride '(void)didUpdateWithItem:(NSXMLElement *)item' that you can define attributes in to point to another entity. Here you would copy the existing data model and add your own attributes to it - using the over-ride above to enter them.
As for the messages, depends on if a MUC or a 1:1 - but they use different managed objects as well. XEP-0045 is what is storing the MUC messages that you can try to attach to for the users last message in there - as well as XMPPMessageArchiving for the 1:1 storage, but you would still need support from the server on this if you need to persist the capturing of another users last message - unless you are only talking about per session (which you could then store locally for display).

Can not delete an entity from Core Data, using RestKit 0.20

The code below does not delete the entity. The "delete was successful" message appears on the console so the entity is found. All other operations I use succeed.
I am using RestKit 0.20.
NSManagedObjectContext *context = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;
NSError *error = nil;
NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity: [NSEntityDescription entityForName:#"Auction" inManagedObjectContext:context]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"AuctionID = %d", auctionID];
[fetchRequest setPredicate:predicate];
NSArray *result = [context executeFetchRequest:fetchRequest error:&error];
if(result.count) {
Auction *block = result[0];
[context deleteObject:block];
BOOL status = [context save:&error];
if (status == NO) {
NSLog(#"delete falied for AuctionID:%d, error: %#", auctionID, error);
}
else {
[context processPendingChanges];
NSLog(#"delete was successful for AuctionID:%d", auctionID);
}
}
Why might this delete operation not succeed and what is the solution to making it work.
I found this solution :
In fact, you have to fetch datas from the persistentstore and not the current created managed context :
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"MyModel"];
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"id" ascending:NO];
fetchRequest.sortDescriptors = #[descriptor];
// Setup fetched results
NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
// AND TO DELETE A MODEL :
[[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext deleteObject:myobject];
i am doing the same thing and have nearly same code.
In my code also, i get delete done and saved....
But, its not deleted when i am checking DB.
the problem is not with simulator... SURE bcz i am getting same problem on device also.
there is something called child context, it might be the cause...Check these links http://restkit.org/api/0.20.0-dev/Classes/RKManagedObjectRequestOperation.html#//api/name/managedObjectContext
RestKit 0.20 — What is the preferred way to create a new NSManagedObject?
. If you found solution pls share here
#Sumitiscreative I ran into the same issue today. What if found was that normally using Core Data you have to use
[NSManagedObject save:]
for it to store the changes. I dug through Restkit a bit and found this
[[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext deleteObject:(NSManagedObject *)];
[[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext saveToPersistantStore:(NSError *)];
Calling this after the above delete method is working to remove the object out of the DB.
**Edit - Also I would have just made this a comment but i don't have the option
#Lance
Hey, pls update your restkit with the latest version.
As now, this works in the latest version , if your server related configuration is correct. and if you get success codes for your delete request from server. Then, restkit automatically deletes the data.
If you need to delete any data externally then, you can use persistentStoreManagedObjectContext and after deleting, save it.
Also, if you want to check at your end that whether its correctly deleting via restkit or not. what you can do is ...
make delete request, after success
check with same id, if item exists. (just for help)

Resources