美文网首页iOS技术深度文章
iOS多图批量顺序上传

iOS多图批量顺序上传

作者: Hither | 来源:发表于2018-04-10 14:09 被阅读569次

这几天遇到一个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)就只能等待。有可能同时有几辆车等待一个停车位。

相关文章

网友评论

    本文标题:iOS多图批量顺序上传

    本文链接:https://www.haomeiwen.com/subject/uhtnhftx.html