iOS网络图片瀑布流(未知图片高度)

做过瀑布流的都清楚,,后台数据会返回图片的宽高,,经过比例处理会整齐的排列。。collectionview的加载图片的过程是先全部设置好没个item的高度,,添加占位图片,,sdwebimage下载图片,,下载完成显示在对应的imageView,,那么后台不返回尺寸该怎么办??有的demo是在数据处理的时候将图片下载下来,获取尺寸,添加进model里。。在collectionview刷新的时候再给item的尺寸,,这样做可以。。但会比较耗时。。有图片缓存还好,,如果是上拉加载新的图片。。用户体验会特别的差。你就等吧。

与后台沟通后 结果是图片太多了 取尺寸太麻烦,,前台想办法。。。。。

安卓和iOS 都采用了同一个思路 先给一个固定相同的高度,,线程获取图片尺寸,,获取结束后,再刷新高度,,虽然用户体验也极差,,会看到图片突然地变大或变小。。但没找到更好的办法。。下面是我的APP用到的关键代码


#pragma mark  加载数据

- (void)addData{

    __weakTuiJianViewController *weakSelf =self;

    dispatch_async(dispatch_get_global_queue(0,0), ^{

        [[CommuncationsharedInstance] loadShouYeTuiJianWithstart:requestStartlimit:limitsucess:^(id result) {

            /// 断网的情况请求出错时走缓存数据

            if ([resultisKindOfClass:[NSErrorclass]]) {

                self.imagewarr = [NSMutableArrayarray];

                self.imageharr = [NSMutableArrayarray];

                requestResultArray = [NSMutableArrayarray];

                requestResultArray = [NSKeyedUnarchiverunarchiveObjectWithFile:[PathToolthePath:@"TuiJianData"]];

                for (NSDictionary *bodyin requestResultArray) {

                    NSString *imageUrl = imageUrl = body[@"video"][@"cover"];

                    /// 获取图片尺寸的方法,,有缓存从缓存中获取

                    CGSize size = [ImageSizeTool downloadImageSizeWithURL:[NSURLURLWithString:[NSStringstringWithFormat:@"%@%@",URLADDRESS,imageUrl]]];

                    [self.imagewarraddObject:[NSStringstringWithFormat:@"%f",size.width]];

                    [self.imageharraddObject:[NSStringstringWithFormat:@"%f",size.height]];

                }

                [weakSelf.tuijianCollectionViewreloadData];

                [weakSelf.tuijianCollectionView.mj_footerendRefreshing];

                [weakSelf.tuijianCollectionView.mj_headerendRefreshing];

            }else{

                if (!result[@"state"]) {

                    if (result[@"customMessage"]) {

                        [[iToastmakeText:result[@"customMessage"]]show];

                    }

                }else{

                    NSInteger num =requestStart;

                    requestStart =requestStart + [result[@"body"]count];

                    self.imagearr = [NSMutableArrayarray];

                    for (NSDictionary *bodyin result[@"body"]) {

                        if (![requestResultArraycontainsObject:body]) {

                            [requestResultArrayaddObject:body];

                        }

                        NSString *imageUrl = body[@"live"][@"cover"];

                        [self.imagearraddObject:imageUrl];

                        // 获取图片尺寸之前 先设置固定相同的尺寸 添加进宽高尺寸数组,,在你的瀑布流高度返回方法里进行按比例缩                         放,,设置瀑布流的高度

                        [self.imageharraddObject:@"500"];

                        [self.imagewarraddObject:@"900"];

                        [SVProgressHUD dismiss];

                    }

                    // 进行缓存 、、、、 这里的缓存是为断网情况有数据 ,,不是图片的缓存

                    [NSKeyedArchiverarchiveRootObject:requestResultArraytoFile:[PathToolthePath:@"TuiJianData"]];

                    dispatch_async(dispatch_get_main_queue(), ^{

                        [weakSelf.tuijianCollectionViewreloadData];

                        /// 回到主线程获取图片的尺寸

                        [selfjisun:self.imagearrnsinteger:num];

                        [weakSelf.tuijianCollectionView.mj_footerendRefreshing];

                        [weakSelf.tuijianCollectionView.mj_headerendRefreshing];

                    });

                    [SVProgressHUDdismiss];

                }

            }

        }];

    });

}


- (void)jisun:(NSMutableArray *)arr nsinteger:(NSInteger)nsinteger{

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{

        // 耗时的操作

        for (NSInteger i =0; i<arr.count; i++) {

            CGSize size = [ImageSizeTooldownloadImageSizeWithURL:[NSURLURLWithString:[NSStringstringWithFormat:@"%@%@",URLADDRESS,arr[i]]]];

            // 因为之前设置了相同的固定的尺寸  在这里获取到后进行替换

            [self.imagewarrreplaceObjectAtIndex:nsinteger + iwithObject:[NSStringstringWithFormat:@"%f",size.width]];

            [self.imageharrreplaceObjectAtIndex:nsinteger + iwithObject:[NSStringstringWithFormat:@"%f",size.height]];

        }

        dispatch_async(dispatch_get_main_queue(), ^{

            // 更新界面  尺寸获取后再刷新一遍

                [self.tuijianCollectionViewreloadData];

        });

    });

}



获取尺寸方法 来自网络  先从缓存中找 没有再网络获取 可以节省时间
+(CGSize)downloadImageSizeWithURL:(id)imageURL {

    NSURL* URL =nil;

    if([imageURLisKindOfClass:[NSURLclass]]){

        URL = imageURL;

    }

    if([imageURLisKindOfClass:[NSStringclass]]){

        URL = [NSURLURLWithString:imageURL];

    }

    if(URL ==nil)

        returnCGSizeZero;

    

    NSString* absoluteString = URL.absoluteString;

    

#ifdef dispatch_main_sync_safe   从缓存中获取

    if([[SDImageCachesharedImageCache] diskImageExistsWithKey:absoluteString]){

        UIImage* image = [[SDImageCachesharedImageCache] imageFromMemoryCacheForKey:absoluteString];

        if(!image){

          NSData* data = [[SDImageCachesharedImageCache] performSelector:@selector(diskImageDataBySearchingAllPathsForKey:)withObject:URL.absoluteString];

            image = [UIImageimageWithData:data];

        }

        if(image){

            return image.size;

        }

    }

#endif  从网络获取

    NSMutableURLRequest *request = [[NSMutableURLRequestalloc] initWithURL:URL];

    NSString* pathExtendsion = [URL.pathExtensionlowercaseString];

    

    CGSize size =CGSizeZero;

    if([pathExtendsionisEqualToString:@"png"]){

        size =  [selfdownloadPNGImageSizeWithRequest:request];

    }elseif([pathExtendsionisEqual:@"gif"]){

        size =  [selfdownloadGIFImageSizeWithRequest:request];

    }else{

        size = [selfdownloadJPGImageSizeWithRequest:request];

    }

    if(CGSizeEqualToSize(CGSizeZero, size)){

        NSData* data = [NSURLConnectionsendSynchronousRequest:[NSURLRequestrequestWithURL:URL] returningResponse:nilerror:nil];

        UIImage* image = [UIImageimageWithData:data];

    if(image){

#ifdef dispatch_main_sync_safe

        [[SDImageCachesharedImageCache] storeImage:image recalculateFromImage:YESimageData:data forKey:URL.absoluteStringtoDisk:YES];

#endif

            size = image.size;

        }

    }

    return size;

}

+(CGSize)downloadPNGImageSizeWithRequest:(NSMutableURLRequest*)request{

    [request setValue:@"bytes=16-23"forHTTPHeaderField:@"Range"];

    NSData* data = [NSURLConnectionsendSynchronousRequest:requestreturningResponse:nilerror:nil];

    if(data.length ==8){

        int w1 =0, w2 = 0, w3 =0, w4 = 0;

        [data getBytes:&w1range:NSMakeRange(0,1)];

        [data getBytes:&w2range:NSMakeRange(1,1)];

        [data getBytes:&w3range:NSMakeRange(2,1)];

        [data getBytes:&w4range:NSMakeRange(3,1)];

        int w = (w1 <<24) + (w2 << 16) + (w3 <<8) + w4;

        int h1 =0, h2 = 0, h3 =0, h4 = 0;

        [data getBytes:&h1range:NSMakeRange(4,1)];

        [data getBytes:&h2range:NSMakeRange(5,1)];

        [data getBytes:&h3range:NSMakeRange(6,1)];

        [data getBytes:&h4range:NSMakeRange(7,1)];

        int h = (h1 <<24) + (h2 << 16) + (h3 <<8) + h4;

        returnCGSizeMake(w, h);

    }

    returnCGSizeZero;

}

+(CGSize)downloadGIFImageSizeWithRequest:(NSMutableURLRequest*)request{

    [request setValue:@"bytes=6-9"forHTTPHeaderField:@"Range"];

    NSData* data = [NSURLConnectionsendSynchronousRequest:requestreturningResponse:nilerror:nil];

    if(data.length ==4){

        short w1 =0, w2 = 0;

        [data getBytes:&w1range:NSMakeRange(0,1)];

        [data getBytes:&w2range:NSMakeRange(1,1)];

        short w = w1 + (w2 <<8);

        short h1 =0, h2 = 0;

        [data getBytes:&h1range:NSMakeRange(2,1)];

        [data getBytes:&h2range:NSMakeRange(3,1)];

        short h = h1 + (h2 <<8);

        returnCGSizeMake(w, h);

    }

    returnCGSizeZero;

}

+(id)diskImageDataBySearchingAllPathsForKey:(id)key{returnnil;}

+(CGSize)downloadJPGImageSizeWithRequest:(NSMutableURLRequest*)request{

    [request setValue:@"bytes=0-209"forHTTPHeaderField:@"Range"];

    NSData* data = [NSURLConnectionsendSynchronousRequest:requestreturningResponse:nilerror:nil];

    if ([datalength] <= 0x58) {

        returnCGSizeZero;

    }

    if ([datalength] < 210) {//肯定只有一个DQT字段

        short w1 =0, w2 = 0;

        [data getBytes:&w1range:NSMakeRange(0x60,0x1)];

        [data getBytes:&w2range:NSMakeRange(0x61,0x1)];

        short w = (w1 <<8) + w2;

        short h1 =0, h2 = 0;

        [data getBytes:&h1range:NSMakeRange(0x5e,0x1)];

        [data getBytes:&h2range:NSMakeRange(0x5f,0x1)];

        short h = (h1 <<8) + h2;

        returnCGSizeMake(w, h);

    } else {

        short word =0x0;

        [data getBytes:&wordrange:NSMakeRange(0x15,0x1)];

        if (word ==0xdb) {

            [data getBytes:&wordrange:NSMakeRange(0x5a,0x1)];

            if (word ==0xdb) {//两个DQT字段

                short w1 =0, w2 = 0;

                [data getBytes:&w1range:NSMakeRange(0xa5,0x1)];

                [data getBytes:&w2range:NSMakeRange(0xa6,0x1)];

                short w = (w1 <<8) + w2;

                short h1 =0, h2 = 0;

                [data getBytes:&h1range:NSMakeRange(0xa3,0x1)];

                [data getBytes:&h2range:NSMakeRange(0xa4,0x1)];

                short h = (h1 <<8) + h2;

                returnCGSizeMake(w, h);

            } else {//一个DQT字段

                short w1 =0, w2 = 0;

                [data getBytes:&w1range:NSMakeRange(0x60,0x1)];

                [data getBytes:&w2range:NSMakeRange(0x61,0x1)];

                short w = (w1 <<8) + w2;

                short h1 =0, h2 = 0;

                [data getBytes:&h1range:NSMakeRange(0x5e,0x1)];

                [data getBytes:&h2range:NSMakeRange(0x5f,0x1)];

                short h = (h1 <<8) + h2;

                returnCGSizeMake(w, h);

            }

        } else {

            returnCGSizeZero;

        }

    }

}



下面是一个大神用SDWebImage 实现的瀑布流 github地址:https://github.com/songhailiang/DynamicWaterfall

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343