这几天遇到一个bug,相册选择图片然后上传,最后回来的顺序并不是你选择图片时的顺序,于是想到了 在本地区处理这个东西。 当然在这个问题解决后,发现还有很多可供参考的解决办法,比如:PromiseKit、NSOperationQueue、以及AFNetworking 2中的batch request 也都可以解决这个问题。
-(void)pickMediaFromAlbum{
//TODO
__block PRImagePickerVc *vc = [PRImagePickerVc new];
vc.pickMode = kPickType_ImageOrVideo;
PDNavigationController *pvc = [[PDNavigationController alloc] initWithRootViewController:vc];
[self presentViewController:pvc animated:YES completion:nil];
__weak PRImagePickerVc *weakVc = vc;
__weak PRGroupChatVc *ws = self;
[vc setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) {
[weakVc dismissViewControllerAnimated:YES completion:nil];
[photos enumerateObjectsUsingBlock:^(UIImage * _Nonnull image, NSUInteger idx, BOOL * _Nonnull stop) {
@autoreleasepool{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSString *path = [PDCommonUtil getPathByCompressImage:image ext:nil];
[dict setObject:[PDCommonUtil dictFromDimensions:image.size] forKey:path];
//单张上传
[ws sendSingleFile:path dimensions:dict];
}
}];
}];
}
// ********************* 发送单张图片 begin *********************
-(void)sendSingleFile:(NSString *)imageUrl dimensions:(NSDictionary *)dimensionDict{
if (imageUrl.length == 0) {
return;
}
//本地增加一个localID
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithDictionary:@{@"localID" : @([UMSCloud getMessageID])}];
UMSMessageObject *msgo = [[UMSMessageObject alloc] initMessageWith:@"" peerID:_folderID.targetID.peerID attributes:attributes attachments:nil];
//发送单张图片
[self sendSinglePicMsg:msgo path:imageUrl dimes:dimensionDict];
}
-(void)sendSinglePicMsg:(UMSMessageObject *)msgo path:(NSString *)filepath dimes:(NSDictionary *)dimesdict{
_bForceScrollToBottom = YES;
NSMutableArray *attachinfo = [NSMutableArray array];
BOOL ret = [[PDCvsMan shareInstance] saveMsgDraft:msgo at:self.folderID];
if (!ret) {
[[PDCvsMan shareInstance] notifySyncDataAdd:msgo folderID:self.folderID];
return;
}
__weak PRGroupChatVc *ws = self;
[[PDCvsMan shareInstance] saveAttachsDraft:@[filepath] desc:nil dimens:dimesdict at:msgo.attributes[@"localID"]];
[msgo ums_setAttachments:@[]];
NSURL *url;
if ([[filepath lowercaseString] hasPrefix:@"file:"]) {
url = [NSURL URLWithString:filepath];
}else{
url = [NSURL fileURLWithPath:filepath];
}
NSString *filePath = url.path;//[obj substringFromIndex:@"file://".length];
NSString *contentType = [PDCommonUtil mimeTypeForExtension:filePath.pathExtension];
NSFileManager *fm = [NSFileManager defaultManager];
NSDictionary *fileAttr = [fm attributesOfItemAtPath:filePath error:nil];
UInt64 fsize = [fileAttr fileSize];
SInt64 msgId = [UMSCloud getMessageID];
UMSFileAttachment *fattach = [[UMSFileAttachment alloc] initWithFileUrl:@"" thumb:nil contentType:[UMSCloudContentType valueOf:contentType] fileSize:fsize fname:filePath.lastPathComponent];
NSMutableDictionary *attr = [NSMutableDictionary dictionaryWithDictionary:@{@"fid": @(msgId).description}];
NSDictionary *dimens = dimesdict[filepath];
if (dimens) {
attr[@"dimensions"] = dimens;
}
attr[@"localimg"] = [UIImage imageWithContentsOfFile:filePath];
UMSAttachment *attach = [[UMSAttachment alloc] initWith:UMSProtoAttachmentTypeAttachmentTypeFile text:@"" fallback:@"" attributes:attr];
[attach setAttachmentBody:fattach];
[msgo addAttachments:@[attach.dictValue]];
//创造一个信号量 用于将异步的上传改造成同步的
if (!semaphore) {
semaphore = dispatch_semaphore_create(0);
}
if (!queue) {
queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
}
//加一个这个 其实是担心内存上涨
@autoreleasepool{
dispatch_async(queue, ^{
[[UMSCloud shareInstance] uploadFileWithPath:filePath public:YES progress:^(UMSFileProgress *resp) {
} response:^(UMSUploadFileResponse *resp) {
if (!resp.isSuccess) {
msgo.sendStates = KMsgSendFail;
[[PDCvsMan shareInstance] notifySyncDataUpdate:msgo folderID:ws.folderID];
return ;
}
//信号加1
dispatch_semaphore_signal(semaphore);
UMSFileAttachment *fattach = [[UMSFileAttachment alloc] initWithFileUrl:resp.fileUrl thumb:resp.thumbUrl contentType:[UMSCloudContentType valueOf:contentType] fileSize:resp.fileSize fname:filePath.lastPathComponent];
attr[@"localimg"] = @"";
UMSAttachment *attach = [[UMSAttachment alloc] initWith:UMSProtoAttachmentTypeAttachmentTypeFile text:@"" fallback:@"" attributes:attr];
[attach setAttachmentBody:fattach];
[attachinfo addObject:attach.dictValue];
NSString *path = [PDCommonUtil getDownloadFilePathby:attach];
[[NSFileManager defaultManager] copyItemAtURL:url toURL:[NSURL fileURLWithPath:path] error:nil];
[msgo setRelpyID:@""];
[msgo ums_setAttachments:attachinfo];
[[PDCvsMan shareInstance] updateMsgsDraft:msgo at:_folderID];
[[PDCvsMan shareInstance] removeAttachsDraft:msgo.attributes[@"localID"]];
[[PDCvsMan shareInstance] sendMessage:msgo at:_folderID];
NSURL *url = [NSURL URLWithString:filepath];
[[NSFileManager defaultManager] removeItemAtURL:url error:nil];
}];
//信号减1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
});
}
[[PDCvsMan shareInstance] notifySyncDataAdd:msgo folderID:self.folderID];
}
// ********************* 发送单张图片 end *********************
网上看到一段对信号量的 解释 很有意思:
停车场剩余4个车位,那么即使同时来了四辆车也能停的下。如果此时来了五辆车,那么就有一辆需要等待。
信号量的值就相当于剩余车位的数目,dispatch_semaphore_wait函数就相当于来了一辆车,dispatch_semaphore_signal
就相当于走了一辆车。停车位的剩余数目在初始化的时候就已经指明了(dispatch_semaphore_create(long value)),
调用一次dispatch_semaphore_signal,剩余的车位就增加一个;调用一次dispatch_semaphore_wait剩余车位就减少一个;
当剩余车位为0时,再来车(即调用dispatch_semaphore_wait)就只能等待。有可能同时有几辆车等待一个停车位。
网友评论