如何从用户的 blob id 将照片提供给对话框?
Posted
技术标签:
【中文标题】如何从用户的 blob id 将照片提供给对话框?【英文标题】:How to give photo to dialog from user's blob id? 【发布时间】:2016-05-06 06:52:08 【问题描述】:我正在使用 Quickblox,我上传了用户个人资料图片,如堆栈溢出 (How to upload the Users profile pic and how to fetch that profile pic from another users device?) 中所述,这对我来说很好用。
然后我可以在 user2 的联系人中看到 user1 的个人资料图片。(通过下载 user1 的 blob 文件并将其转换为图像)
但现在我的问题是,如果我们想创建一个与 user1 和 user2 登录的新聊天对话框。我应该将这个 user1 的个人资料图片(如上面的堆栈溢出示例中所述上传)与我要创建的新对话框用于与 user1 聊天。
问题:1 - 那么我如何才能将此用户的个人资料图片与新创建的聊天对话框链接,尤其是在一对一聊天的情况下。(私人聊天)。
问题:2 - 聊天对话框中的图像应该能够在用户 1 更改他的个人资料图片时更新(使用更新 blob api 调用)。正如我们在 WhatsApp 中看到的那样。
【问题讨论】:
【参考方案1】:在,
问题:1
如果我理解您的问题,当您为两个用户创建对话框时,您希望在您的对话框列表中显示对话框图像,并且对话框图像应该是其他用户正确的图像我的意思是 user1 应该将对话框图像视为 User2 和用户 2 应该看到用户 1 正确的对话框图像???
如果是,哥们对不起!但是您遵循的方法是错误的:) Dialog 的属性对于两个用户都是相同的。因此,如果您将对话框的图像设置为 User1,则 user2 将看到 User1 的图片,但 User1 也会看到他自己的图像,这是错误的 :)
我要解决的是,除非是组对话框,否则不要为对话框本身使用任何图像或名称:)
每次您收到QBChat
时,您都会在其中包含居住者 ID。在QBChatPrivate
messages 的情况下,占用者 ID 的计数将为 2,其中一个将是您自己的 ID。所以删除它会给你其他用户的ID。
每当我收到一条消息时,我都会找出除了我自己之外的参与者,并且在将消息插入 coredata 并在应用程序中显示之前,我会检查我的 coredata 以查找用户是否存在于我的本地数据库中。如果用户存在,我将获取有关该用户的所有信息,例如他的个人资料照片、姓名和所有显示他的个人资料照片和列表中的姓名的信息。 否则,我将使用他的 id 下载有关用户的所有信息,然后将其插入 db,最后将消息插入 db。现在,当我展示它时,我将按照相同的程序,在对话框列表中显示用户名、他的个人资料图片和最后一条消息。
这给人的感觉就像对话框正在显示另一个用户名和他的个人资料图片。但实际上对话从来没有任何私人对话的图像或名称:)
结论
在私人对话的情况下,不要将任何图像或名称保存到 ABChatDialog 本身:)
问题:2
WhatsApp中的图像更新不仅涉及客户端逻辑,还包括来自服务器的支持。不幸的是,服务器没有这样的支持,服务器向所有客户端发送通知,通知配置文件图片更改。让我们希望 Quickblox 尽快实现它。
解决方案
我们用一种简单的方法来处理它,每次用户进入对话框列表屏幕时,我们都会获取所有参与当前可见对话框的用户,并为每个用户创建一个单独的 NSOperations 并获取所有信息,包括他的姓名,图像所有内容,以使用户始终保持更新:)
在我们的应用程序中,我们提供了用户也可以更改其姓名的规定,因此对我们而言,完全更新用户而不仅仅是他的个人资料照片很重要:)
所有操作都在后台线程中运行,保持主线程空闲并在后台更新核心数据。
将 NSFetchedResultsController 与 coredata 一起使用,我们可以在更新用户名和他的个人资料图片后立即更新。
当您打开特定用户消息时也会发生相同的过程。一旦您打开他的消息,我们就会获取并更新该特定用户的信息。
这涉及到冗余的服务器调用,我们非常清楚这一点,但这种方法始终保持用户信息的更新。
编辑 根据您的要求,为您提供一些代码:) 这是一个非常抽象但不完全工作的代码,但我相信它应该会给您一个良好的开端:)
问题 1:此代码让您了解如何在添加聊天本身之前先添加用户 :)
- (void)processMessage:(QBChatMessage *)message
// processMessage method is called in background thread so creating a background managed object context for the queue. You can make use of performBlock as well
//once you recieve message check if dialog exists in your db or not
NSManagedObjectContext *privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[privateManagedObjectContext setParentContext:appdelegate.managedObjectContext];
NSFetchRequest *request=[[NSFetchRequest alloc] initWithEntityName:@"Dialog"];
NSPredicate *predicate=[NSPredicate predicateWithFormat:@"id == %@",message.dialogID];
[request setPredicate:predicate];
NSArray *results=[privateManagedObjectContext executeFetchRequest:request error:nil];
if([results count]>0)
//once dialog found for the chat
Dialog *updatedDialog=(Dialog *)[results objectAtIndex:0];
// involves is a one to many relation ship between user and dialog
NSPredicate *userExistsPredicate=[NSPredicate predicateWithFormat:@"recipient_Id = %@",[NSNumber numberWithInteger:message.senderID]];
NSArray *foundUserArray=[[updatedDialog.involves allObjects] filteredArrayUsingPredicate:userExistsPredicate];
if([foundUserArray count] > 0)
//user exists in db
//check if its a duplicate chat sometime same chat comes back specially in group chat
NSFetchRequest *request=[[NSFetchRequest alloc] initWithEntityName:@"Chats"];
NSPredicate *predicate=[NSPredicate predicateWithFormat:@"chat_Id == %@",message.ID];
[request setPredicate:predicate];
NSArray *results=[privateManagedObjectContext executeFetchRequest:request error:nil];
if([results count] ==0)
//message not in db
Chats *recievedChat=[NSEntityDescription insertNewObjectForEntityForName:@"Chats" inManagedObjectContext:privateManagedObjectContext];
recievedChat.sender_Id=[NSNumber numberWithInteger:message.senderID];
recievedChat.date_sent=message.dateSent;
recievedChat.chat_Id=message.ID;
recievedChat.belongs=updatedDialog;
recievedChat.message_Body=message.text;
//populate the way you want it
//commit background context use perform block for better performance
NSError *updateDialogError = nil;
[privateManagedObjectContext save:&updateDialogError];
dispatch_async(dispatch_get_main_queue(), ^
//commit main context
[appdelegate.managedObjectContext save:nil];
);
else
//fetch user not in db
[QBRequest usersWithIDs:@[[NSNumber numberWithInteger:message.senderID]] page:nil
successBlock:^(QBResponse *response, QBGeneralResponsePage *page, NSArray *users)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
NSManagedObjectContext *privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[privateManagedObjectContext setParentContext:appdelegate.managedObjectContext];
NSFetchRequest *request=[[NSFetchRequest alloc] initWithEntityName:@"Dialog"];
NSPredicate *predicate=[NSPredicate predicateWithFormat:@"id == %@",message.dialogID];
[request setPredicate:predicate];
NSArray *results=[privateManagedObjectContext executeFetchRequest:request error:nil];
Dialog *updatedDialog=[results objectAtIndex:0];
NSMutableArray *occupants=[[NSMutableArray alloc] init];
//create user
for(QBUUser *user in users)
if(user.ID != appdelegate.currentUser.ID)
Recipient *recipient=[NSEntityDescription insertNewObjectForEntityForName:@"Recipient" inManagedObjectContext:privateManagedObjectContext];
recipient.recipient_Name=user.fullName;
recipient.recipient_Id=[NSNumber numberWithInteger:user.ID];
[occupants addObject:recipient];
NSMutableArray *newUsersArray=[NSMutableArray arrayWithArray:[updatedDialog.involves allObjects]];
[newUsersArray addObjectsFromArray:occupants];
updatedDialog.involves=[NSSet setWithArray:newUsersArray];
NSFetchRequest *chatRequest=[[NSFetchRequest alloc] initWithEntityName:@"Chats"];
NSPredicate *chatPredicate=[NSPredicate predicateWithFormat:@"chat_Id == %@",message.ID];
[chatRequest setPredicate:chatPredicate];
NSArray *chatResults=[privateManagedObjectContext executeFetchRequest:chatRequest error:nil];
//add chat
if([chatResults count] ==0)
//add chats or messages
Chats *recievedChat=[NSEntityDescription insertNewObjectForEntityForName:@"Chats" inManagedObjectContext:privateManagedObjectContext];
recievedChat.sender_Id=[NSNumber numberWithInteger:message.senderID];
recievedChat.date_sent=message.dateSent;
recievedChat.chat_Id=message.ID;
recievedChat.belongs=updatedDialog;
recievedChat.message_Body=message.text;
//save context
NSError *updateDialogError = nil;
[privateManagedObjectContext save:&updateDialogError];
dispatch_async(dispatch_get_main_queue(), ^
//commit main context
[appdelegate.managedObjectContext save:nil];
);
);
];
问题 2 你不需要代码 :) 一旦你完成了我所说的教程,你就会明白 NSOperation 是如何工作的:) 然后只需在 NSOperation 中编写 quickblox api 来为你下载图像:)
我希望我的观点很清楚。快乐编码
【讨论】:
首先感谢您冗长而详细的回答。感谢您的时间。方法非常好。但是当涉及到每个用户的核心数据管理和 NSOperationQueues 时,我并不感到困惑。我从不处理核心数据。但我做了一些示例应用程序,这些应用程序在 ios& 烹饪书中。所以问题出在我的最后。但我还有其他一些疑问,比如 疑问 :1 - 那么我是否应该暂停基于此链接上传文件的程序 -- (***.com/questions/37043763/… ) 或者还有其他更好的方法来上传用户个人资料图片。 如果可能的话,您能否提供一些与此操作相关的代码(问题 1 和 2),以便我可以理解和比较我的代码并找出我的错误。那对我会有很大的帮助。我正在使用 Quickblox 示例聊天应用程序,它使用 QMViewController 和 QMServices。我认为这个内存管理是由这个 QMServices 处理的。那么如何从这个示例应用程序中获取这些内容。 您好,我们不会将用户个人资料图像直接上传到 Quickblox,而是将图像上传到我们自己的服务器并从我们自己的服务器流式传输。我们向 QBUUser 添加一个自定义对象,并使用 user_profile_image_path 之类的参数对其进行更新,并为其设置相对路径。因此,当我收到 QBUser 信息时,我将提取自定义对象获取相对路径并查询我们的服务器并下载图像:) 原因是 Quickblox 是第三方框架,我们可能会在未来找到更好的框架,我们想要尽可能减少对QB的依赖:) 但是是的,我们确实使用 TUploadFile 来上传和下载聊天图像和视频 :) 是的,如果您没有自己的服务器,您绝对可以使用它 :) 没问题,伙计 :) 根据代码担心提供整个代码是不可能的,因为它涉及多个文件并且遵守公司的规章制度:(但是如果你开始工作并且有任何问题我会帮助你:)根据你对 coredata 的关注参考@987654322 @以上是关于如何从用户的 blob id 将照片提供给对话框?的主要内容,如果未能解决你的问题,请参考以下文章