iOS内存崩溃,UIScrollview使用异步映像加载

iOS内存崩溃,UIScrollview使用异步映像加载,ios,multithreading,memory-management,uiscrollview,sdwebimage,Ios,Multithreading,Memory Management,Uiscrollview,Sdwebimage,我通过使用PSCollectionView并使用异步加载图像来呈现类似于Pinterest的两列滚动图像视图 在iPhone5上,它持续运行,没有崩溃,但在iPhone4上,我遇到了内存警告,在不断向下滚动的同时,应用程序最终崩溃 SDWebImage声称他们在收到内存警告时释放缓存,PSCollectionView通过对可重用视图进行排队来管理视图,因此我不确定到底是什么触发了内存中的问题 我已经运行了内存分析,但我没有看到任何明显的东西——内存最密集的操作来自SDWebImage异步加载图像

我通过使用PSCollectionView并使用异步加载图像来呈现类似于Pinterest的两列滚动图像视图

在iPhone5上,它持续运行,没有崩溃,但在iPhone4上,我遇到了内存警告,在不断向下滚动的同时,应用程序最终崩溃

SDWebImage
声称他们在收到内存警告时释放缓存,
PSCollectionView
通过对可重用视图进行排队来管理视图,因此我不确定到底是什么触发了内存中的问题

我已经运行了内存分析,但我没有看到任何明显的东西——内存最密集的操作来自
SDWebImage
异步加载图像。从我的
PFObjects
(来自parse.com)获取数据的
objectForKey
方法似乎也占用了大量内存

我在下面特别附上了设置每个
PSCollectionView
单元格内容的代码片段

如果您发现代码中存在任何可能导致内存问题的特定问题,请告诉我&如果您对如何更好地诊断此内存问题有任何建议,请告诉我

- (UIView *)collectionView:(PSCollectionView *)collectionView cellForRowAtIndex:(NSInteger)index withRect:(CGRect) recttouse {


    FPCollectionViewCell *thefpcell = (FPCollectionViewCell *)
    [collectionView dequeueReusableViewForClass:[FPCollectionViewCell class]];

    thefpcell.frame = recttouse;

    if (thefpcell == nil) {


        thefpcell = [[FPCollectionViewCell alloc] initWithFrame:recttouse];

        //NSLog(@"creating this cell: %i", index);

        UILabel *cellText = [[UILabel alloc] initWithFrame:CGRectMake(2,0,143,20)];

        thefpcell.cellText = cellText;
        thefpcell.cellText.textAlignment = NSTextAlignmentCenter;


        UIImageView *cellImage = [[UIImageView alloc] initWithFrame:CGRectMake(0,20,recttouse.size.width, recttouse.size.height-20)];

        thefpcell.cellImage = cellImage;

         thefpcell.backgroundColor = [UIColor whiteColor];
        thefpcell.cellText.font = [UIFont fontWithName:@"HelveticaNeue-LightItalic" size:9];

        thefpcell.cellText.backgroundColor = [UIColor clearColor];


        [thefpcell addSubview:cellText];
        [thefpcell addSubview:cellImage];

        }

    //@Brian note--consider moving more of this to other blocks to try and improve performance
    [[NSOperationQueue mainQueue] addOperation:[NSBlockOperation blockOperationWithBlock:^{

            PFObject *thisobj = [self.contentObjectsArray objectAtIndex:index];

         thefpcell.cellText.frame = CGRectMake(2,0,143,20);


        thefpcell.cellImage.frame = CGRectMake(0,20,recttouse.size.width, recttouse.size.height-20);


        thefpcell.cellText.text = [thisobj objectForKey:@"Caption"];

        NSString *imglink = [thisobj objectForKey:@"imgLink"];
        NSString *imgurl;
        if(imglink.length<2)
        {
            PFFile *mydata = [thisobj objectForKey:@"imageFile"];
            imgurl = mydata.url;

        }
        else
        {
            imgurl =imglink;
        }

              UIImage *cellplaceholder = [UIImage imageWithContentsOfFile:@"placeholder.png"];
        [thefpcell.cellImage setImageWithURL:[NSURL URLWithString:imgurl] placeholderImage:cellplaceholder];


        thefpcell.layer.cornerRadius = 9.0;
        thefpcell.layer.masksToBounds = YES;

        }]];


    //NSLog(@"got it: %i", index);

    return thefpcell;
}
-(UIView*)collectionView:(PSCollectionView*)collectionView cellForRowAtIndex:(NSInteger)索引带rect:(CGRect)recttose{
FPCollectionViewCell*FfpCell=(FPCollectionViewCell*)
[collectionView出列ReusableViewForClass:[FPCollectionViewCell类]];
thefpcell.frame=recttouse;
if(offpcell==nil){
thefpcell=[[FPCollectionViewCell alloc]initWithFrame:recttouse];
//NSLog(@“创建此单元格:%i”,索引);
UILabel*cellText=[[UILabel alloc]initWithFrame:CGRectMake(2,0143,20)];
thefpcell.cellText=cellText;
thefpcell.cellText.textAlignment=NSTextAlignmentCenter;
UIImageView*cellImage=[[UIImageView alloc]initWithFrame:CGRectMake(0,20,recttouse.size.width,recttouse.size.height-20)];
thefpcell.cellImage=cellImage;
thefpcell.backgroundColor=[UIColor whiteColor];
thefpcell.cellText.font=[UIFont fontWithName:@“HelveticaNeue LightItalic”大小:9];
thefpcell.cellText.backgroundColor=[UIColor clearColor];
[thefpcell addSubview:cellText];
[小区添加子视图:小区图像];
}
//@Brian note--考虑将更多这类内容移动到其他块,以尝试提高性能
[[NSOperationQueue mainQueue]添加操作:[NSBlockOperation blockOperationWithBlock:^{
PFObject*thisobj=[self.contentObjectsArray objectAtIndex:index];
thefpcell.cellText.frame=CGRectMake(2,0143,20);
thefpcell.cellImage.frame=CGRectMake(0,20,recttouse.size.width,recttouse.size.height-20);
thefpcell.cellText.text=[ThisObjectForkey:@“Caption”];
NSString*imglink=[ThisObjectForkey:@“imglink”];
NSString*imgurl;

如果(imglink.length嗯,这里没有什么明显的

SDWebImage
UIApplicationIDReceiveMemoryWarningNotification
注册(这很重要,因为在iOS7中,
NSCache
不像以前那样对内存压力做出响应)。您可以通过在
SDImageCache
中的
clearMemory
中放置一个断点来确认这一点,然后运行应用程序,模拟/再现内存警告和确认,并确认调用了此功能。但我想您会发现它。我无法与parse.com处理
NSCache
不再自动调用这一事实进行对话像过去一样被催促

您应该在仪器中执行一些heapshot/生成,如WWDC 2012视频中所示。因此,请运行应用程序,使其处于静止状态,模拟内存警告,标记heapshot/生成,稍微使用应用程序,再次模拟内存警告,并再次标记heapshot/生成。然后查看分配的对象,它们仍然在两代人之后,您就可以确定哪些内容没有发布到您的身上。您可能可以确定parse.com是否有未清理的内容,或者它是在您的代码中还是在SDWebImage中


一些不相关的观察结果:

  • 考虑到您正试图减少内存影响,这听起来像是一个奇怪的建议,但是
    cellplaceholder
    可能是您真正想使用
    imageNamed
    ,而不是
    imageWithContentsOfFile
    。假设这个占位符需要很多,它将(a)更快;和(b)如果占位符被临时大量使用(而不是使用同一占位符的一堆短期实例),实际上可能会降低您的高水位线

  • 这是极不可能的,但如果您要自己异步更新单元格,则确实应该重新检索集合视图单元格,以确保此单元格没有从屏幕上滚动(调用
    [collectionView cellForItemAtIndexPath:indexPath]
    ,不要与类似名称的
    UICollectionViewDataSource
    方法混淆,并确保该方法不是
    nil

    坦白地说,我不知道你为什么要把它发回主队列。SDWebImage将已经异步地检索图像,所以你通常不必自己做任何异步处理,如果你真的需要一些异步处理,你可以将其发送到某个后台队列(而不是回到主队列)

    无论这种构造如何:

    [[NSOperationQueue mainQueue] addOperation:[NSBlockOperation blockOperationWithBlock:^{
        // ...
    }]];
    
    可以简化为

    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        // ...
    }];
    

  • 嗯,这里没什么明显的

    SDWebImage
    UIApplicationIDReceiveMemoryWarningNotification
    注册(这很重要,因为在iOS7中,
    NSCache
    不像以前那样响应内存压力)。您可以通过