美文网首页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