ios - docs - Usando JSQMessagesViewController con Parse.com
docs parse platform (1)
Me encontré con lo que parece ser una biblioteca muy compleja y personalizada que sería muy útil para cualquier aplicación que quiera tener un sistema de mensajería integrado. JSQMessagesViewController en Github . Mientras intentaba implementar la biblioteca por mi cuenta, tuve algunos problemas. Uno. No entiendo muy bien la terminología de "protocolos" y "clases" (entiendo un poco sobre clases). El primer problema fue que no pude usar PFObjects en CollectionView porque una instancia de JSQMessage debe pasarse a través de la mayoría de los métodos personalizados. Ahora, sé cómo tomar un PFObject y obtener las propiedades de ese tipo
self.eachMessage = [self.messages objectAtIndex:indexPath.row]; //each message
self.eachMessage[@"message"] //message from the PFObject
self.eachMessage[@"sender"] //sender from the PFObject
La clase JSQMessage tiene propiedades personalizadas que representarían las propiedades del PFObject como
JSQMessage *message = [[JSQMessage alloc] init]; //initialize it
message.senderId //could be the objectId of the user
message.senderDisplayName //the user''s username
message.text //text of the message
message.date //time sent of the message
El caso es que, en la clase personalizada JSQMessage ... todas estas propiedades son de solo lectura. Estoy seguro de que puedo entrar y cambiar eso para poder asignarles exactamente lo que quiero, pero debe haber algo que me falta aquí. Adjuntaré todo en mis archivos .h y .m. Cuando envío un mensaje, lo único que aparece es el texto, y creo que es así porque se inicia cuando proviene de textView en la barra de herramientas de entrada.
.h Archivo
#import <UIKit/UIKit.h>
#import <JSQMessagesViewController/JSQMessages.h>
#import <Parse/Parse.h>
#import <JSQMessagesViewController/JSQMessagesBubbleImageFactory.h>
@interface ConvoViewController : JSQMessagesViewController
@property (strong, nonatomic) NSMutableArray *messages;
@property (strong, nonatomic) PFUser *sender;
@property (strong, nonatomic) PFUser *receiver;
@property (strong, nonatomic) JSQMessage *eachMessage;
@property (strong, nonatomic) PFObject *aMessage;
@property (strong, nonatomic) JSQMessagesBubbleImageFactory *bubbleImage;
@end
.m Archivo
- (void)viewDidLoad {
[super viewDidLoad];
//Color of the keyboard (Dark to match everything else)
self.inputToolbar.contentView.textView.keyboardAppearance = UIKeyboardAppearanceDark;
//Color the inputview background
self.inputToolbar.backgroundColor = [UIColor colorWithWhite:0 alpha:0.9];
//Delete the avatars appearing next to the messages
self.collectionView.collectionViewLayout.incomingAvatarViewSize = CGSizeZero;
self.collectionView.collectionViewLayout.outgoingAvatarViewSize = CGSizeZero;
//Set the senderID
self.senderId = self.sender.objectId;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
//Query for part of the messages
PFQuery *messages1 = [PFQuery queryWithClassName:@"Messages"];
[messages1 whereKey:@"sender" equalTo:self.sender];
[messages1 whereKey:@"receiver" equalTo:self.receiver];
//Query for other part of messages
PFQuery *messages2 = [PFQuery queryWithClassName:@"Messages"];
[messages2 whereKey:@"sender" equalTo:self.receiver];
[messages2 whereKey:@"receiver" equalTo:self.sender];
//Combine those queries
PFQuery *allMessages = [PFQuery orQueryWithSubqueries:@[messages1, messages2]];
[allMessages findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
self.messages = [objects mutableCopy];
[self.collectionView reloadData];
}];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Send Button
- (void)didPressSendButton:(UIButton *)button withMessageText:(NSString *)text senderId:(NSString *)senderId senderDisplayName:(NSString *)senderDisplayName date:(NSDate *)date {
[JSQSystemSoundPlayer jsq_playMessageSentSound];
JSQMessage *message = [[JSQMessage alloc] initWithSenderId:self.sender.objectId
senderDisplayName:self.sender.username
date:[NSDate date]
text:text];
[self.messages addObject:message];
NSLog(@"%@", text);
[self finishSendingMessageAnimated:YES];
}
#pragma mark - JSQMessages Data Source methods
- (id<JSQMessageData>)collectionView:(JSQMessagesCollectionView *)collectionView messageDataForItemAtIndexPath:(NSIndexPath *)indexPath
{
//Return the actual message at each indexpath.row
return [self.messages objectAtIndex:indexPath.row];
}
- (id<JSQMessageBubbleImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView messageBubbleImageDataForItemAtIndexPath:(NSIndexPath *)indexPath
{
/**
* You may return nil here if you do not want bubbles.
* In this case, you should set the background color of your collection view cell''s textView.
*
* Otherwise, return your previously created bubble image data objects.
*/
JSQMessage *message = [self.messages objectAtIndex:indexPath.item];
if ([message.senderId isEqualToString:self.senderId]) {
return [self.bubbleImage incomingMessagesBubbleImageWithColor:[UIColor orangeColor]];
}
return [self.bubbleImage outgoingMessagesBubbleImageWithColor:[UIColor grayColor]];
}
#pragma mark - Collection View
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
//Number of messages
return self.messages.count;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
//Number of sections
return 1;
}
- (UICollectionViewCell *)collectionView:(JSQMessagesCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
//Creating or initial cell for the number of index paths (number of messages)
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
//Put our messages dictionaries into PFObject so we can put them into individual cells
self.eachMessage = [self.messages objectAtIndex:indexPath.row];
//Put the message object into the textView''s text property
cell.textView.text = self.eachMessage.text;
//Setting the text color of the message bubble based upon the sender
if ([self.eachMessage.senderId isEqualToString:self.senderId]) {
cell.textView.textColor = [UIColor blackColor];
} else {
cell.textView.textColor = [UIColor whiteColor];
}
//Set the top label to the person who sent the message
cell.cellTopLabel.text = [NSString stringWithFormat:@"@%@", self.eachMessage.senderId];
//Format the bottom label to a readable date
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"MM/dd/yy h:mm a"];
cell.cellBottomLabel.text = [dateFormatter stringFromDate:self.eachMessage.date];
//If there is a link of some sorts in the message
cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor,
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) };
//What we return into the collectionview
return cell;
}
Aquí hay parte de mi código. Los archivos completos son grandes y mi jefe no estará contento si los comparto. :-)
Así es como cargué mi DemoData en mi DemoMessagesViewController
:
self.demoData = [[DemoModelData alloc] init];
self.demoData.users = @{self.senderId:self.senderDisplayName,
self.targetUserId:self.targetUserName};
UIImage *tempImg = [HTTPServerKaDost fetchImageFromUrlString:userProfile.profilePicUrl]; //replace with your code to load image
JSQMessagesAvatarImage *srcImage = [JSQMessagesAvatarImageFactory
avatarImageWithImage:tempImg
diameter:kJSQMessagesCollectionViewAvatarSizeDefault];
tempImg = [HTTPServerKaDost fetchImageFromUrlString:self.targetUserImageFullUrl];
JSQMessagesAvatarImage *destImage = [JSQMessagesAvatarImageFactory
avatarImageWithImage:tempImg
diameter:kJSQMessagesCollectionViewAvatarSizeDefault];
self.demoData.avatars = @{self.senderId:srcImage,
self.targetUserId:destImage};
[self.demoData loadMessages];
dentro del método loadMessages
(agregado por mí dentro de DemoModelData
Class), crea objetos JSQMessage
:
JSQMessage *msg = [[JSQMessage alloc] initWithSenderId:[msgDict valueForKey:@"sender"]
senderDisplayName:[msgDict valueForKey:@"fname"]
date:dateT
text:[msgDict valueForKey:@"data"]];
[self.messages addObject:msg];
y cada vez que desee actualizar la vista de chat, llame a esto dentro de DemoMessagesViewController
:
[self finishReceivingMessageAnimated:YES];
[self scrollToBottomAnimated:YES];