草庐IT

ios - uitableview更新错误

coder 2024-01-16 原文

我使用以下方法更新表格 View 单元格:


- (void)imageDownloader:(SDWebImageDownloader *)downloader didFinishWithIndexPath:(NSIndexPath *)indexPath
{
    NSArray *arr = [self.tableView indexPathsForVisibleRows];
    if ([arr containsObject:indexPath]) 
    {
        UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];//received error here
        UIImageView *imageView = (UIImageView *)[cell viewWithTag:'ICON'];
        SDWebImageManager *manager = [SDWebImageManager sharedManager];
        UIImage *image = [manager imageWithURL:downloader.url];
        imageView.image = image;
    }
}

这是 SDWebImageDownloader 的委托(delegate),更新时收到错误:

thread9:  Program received signal: "SIGABRT".

Form the device console, there is:

: *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 7 beyond bounds [0 .. 6]'
    *** First throw call stack:
    (0x335a38bf 0x300971e5 0x334ecb6b 0x30ff0eb1 0xaa0a7 0x334fd435 0xb5b13 0x30d91a91 0x30e255a1 0x36fa0c1d 0x36fa0ad8)

Then I print the arr which holds the current visible index path:

Printing description of arr:
(
    " 2 indexes [0, 1]",
    " 2 indexes [0, 2]",
    " 2 indexes [0, 3]",
    " 2 indexes [0, 4]",
    " 2 indexes [0, 5]",
    " 2 indexes [0, 6]",
    " 2 indexes [0, 7]"
)

and the received indexPath

 2 indexes [0, 7]

The indexPath is included in the visible index path, and why it still cause the NSRangeException? It looks like a bug for cellForRowAtIndexPath:indexPath, as the row of index path is 7 which is beyond the visible index path arr, am I right?

Add the eatableview delegate method:


- (UITableViewCell *)tableView:(UITableView *)inTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    NSString *path;
    NSString *filename;

    BOOL download = YES;
    NSDictionary *tempDic = nil;
    @synchronized (documentDirectoryFileList) {
        tempDic = [self.documentDirectoryFileList objectAtIndex:indexPath.row];
        filename = [tempDic objectForKey:@"filename" ];

        NSURL *url = [tempDic objectForKey:@"url" ];
        if ( url ) {
            path = [ url path ];
            download= [ self downloadedFile:url ];

        } else {

                path = [tempDic objectForKey:@"filepath" ];
        }
    }

    BOOL isDirectory = FALSE;

    NSFileManager *fileManager = [[NSFileManager alloc] init];
    BOOL found = [fileManager fileExistsAtPath: path isDirectory: &isDirectory];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

        CGRect rect;
        rect = CGRectMake(5,14, 32, 32);

        cell.userInteractionEnabled = YES;

        UIImageView *imageView = [[UIImageView alloc] initWithFrame:rect];
        imageView.tag = 'ICON';
        [cell.contentView addSubview:imageView];
        [imageView release];        

        rect = CGRectMake(42, 10, 238, 22);

        UILabel *labelView = [[UILabel alloc] initWithFrame:rect];
        labelView.tag = 'NAME';
        labelView.font = [UIFont boldSystemFontOfSize:18];
        if ( download == NO )
            labelView.textColor = [UIColor lightGrayColor ];
         [cell.contentView addSubview:labelView];
        [labelView release];

        rect = CGRectMake(42, 34, 200, 20);
        labelView = [[UILabel alloc] initWithFrame:rect];
        labelView.tag = 'TIME';
        labelView.font = [UIFont systemFontOfSize:12];
        if ( download == NO )
            labelView.textColor = [UIColor lightGrayColor ];
        [cell.contentView addSubview:labelView];
        [labelView release];

        rect = CGRectMake(200, 34, 75, 20);
        labelView = [[UILabel alloc] initWithFrame:rect];
        labelView.tag = 'SIZE';
        labelView.font = [UIFont systemFontOfSize:12];
        if ( download == NO )
            labelView.textColor = [UIColor lightGrayColor ];
        labelView.textAlignment = UITextAlignmentRight;
        [cell.contentView addSubview:labelView];
        [labelView release];

    }


    // Get the time zone wrapper for the row
    UIImageView *imageView = (UIImageView *)[cell viewWithTag:'ICON'];
    imageView.image = NULL;

    NSString* extension = [[path pathExtension] lowercaseString];
    if ([extension isEqualToString: @"png"] ||
        [extension isEqualToString: @"jpg"] ||
        [extension isEqualToString: @"jpeg"] ||
        [extension isEqualToString: @"bmp"] ||
        [extension isEqualToString: @"gif"] ||
        [extension isEqualToString: @"tiff"] ||
        [extension isEqualToString: @"thm"])
    {
        NSString *realFilePath = [ fileManager destinationOfSymbolicLinkAtPath:path error:nil ];
        if ( realFilePath )
            path = realFilePath;

        NSURL *url = [[NSURL fileURLWithPath:path] URLByAppendingPathComponent:@"thumb.th"];
        SDWebImageManager *manager = [SDWebImageManager sharedManager];
        UIImage *temp = [manager imageWithURL:url];
        if (temp) {
            imageView.image = temp;
        }
        else
        {
            SDWebImageDownloader *downloader = [SDWebImageDownloader downloaderWithURL:url delegate:self indexPath:indexPath];
        }

    } else {

        imageView.image = [ self determineFileIcon : path ];

    }

    // Configure the cell.
    UILabel *labelView = (UILabel *)[cell viewWithTag:'NAME'];
    labelView.text = filename;
    cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
    if ( isDirectory ) {
        if ( isLink( path ) )
            labelView.font = [UIFont italicSystemFontOfSize:16.0];
        else
            labelView.font = [UIFont boldSystemFontOfSize:16.0];
    } else {
        if ( isLink( path ) )
            labelView.font = [UIFont italicSystemFontOfSize:16.0];
        else
            labelView.font = [UIFont systemFontOfSize:16.0];
    }

    labelView = (UILabel *)[cell viewWithTag:'TIME'];
    NSCalendar *theCalendar= [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSCalendarUnit unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;

    NSDate *date = [tempDic objectForKey:@"date" ];
    NSDateComponents *dateComponents = [theCalendar components:unitFlags fromDate:date];

    NSInteger year = [dateComponents year];
    NSInteger month = [dateComponents month];
    NSInteger day = [dateComponents day];
    NSInteger hour = [dateComponents hour];
    NSInteger minute = [dateComponents minute];
    NSInteger second = [dateComponents second];

    [theCalendar release];
    labelView.text = [NSString stringWithFormat:@"%d/%02d/%02d %02d:%02d:%02d", year,month,day,hour,minute,second ];

    if ( !isDirectory ) {
        labelView = (UILabel *)[cell viewWithTag:'SIZE'];
        [labelView setHidden:NO];
        NSNumber *size = [tempDic objectForKey:@"filesize" ];
        float value = [ size floatValue ];
        NSString *str;
        if ( value > ( 1024*1024 ) ) {
            value = value / 1024 / 1024;
            str = [NSString stringWithFormat:@"%0.1f MB", value ];
        } else if ( value > 1024 ) {
            value = value / 1024;
            str = [NSString stringWithFormat:@"%0.1f KB", value ];
        } else {
            str = [NSString stringWithFormat:@"%d Bytes", [ size integerValue ] ];
        }
        labelView.text = str;
    }
    else
    {
        labelView = (UILabel *)[cell viewWithTag:'SIZE'];
        [labelView setHidden:YES];
    }

    [fileManager release];

    return cell;
}

添加于 11-17 日: 当“SIGABRT”收到时,documentDirectoryFileList 有对象,例如 30+。接收到的indexPath存在于可见索引路径数组中。但是我注意到:滚动tableview时很容易发生。没有新对象添加到数据源。我所做的只是更新单元格上的图像。

我猜可能是: 当接收到的索引路径开始更新相应的单元格时,我碰巧滚动它并且单元格或索引路径不再可见。然后它崩溃了。

最佳答案

好像是多线程的问题。


- (void)imageDownloader:(SDWebImageDownloader *)downloader didFinishWithIndexPath:(NSIndexPath *)indexPath
{


    @synchronized(tableView)
    {
        NSArray *arr = [self.tableView indexPathsForVisibleRows];
        if ([arr containsObject:indexPath]) 
        {

            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
            if (!cell) 
            {
                return;
            }

            UIImageView *imageView = (UIImageView *)[cell viewWithTag:'ICON'];
            SDWebImageManager *manager = [SDWebImageManager sharedManager];
            UIImage *image = [manager imageWithURL:downloader.url];
            if (image) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    imageView.image = image;
                });

            }
        }

    }
}

或者你可以


- (void)imageDownloader:(SDWebImageDownloader *)downloader didFinishWithIndexPath:(NSIndexPath *)indexPath
{


    @synchronized(tableView)
    {
        NSArray *arr = [self.tableView indexPathsForVisibleRows];
        if ([arr containsObject:indexPath]) 
        {

            dispatch_async(dispatch_get_main_queue(), ^{
                    [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
                });//must be in main thread; reloadRowsAtIndexPaths: is not thread safe



        }

    }
}

关于ios - uitableview更新错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8148811/

有关ios - uitableview更新错误的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  3. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  4. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  5. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  6. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  7. ruby-on-rails - 错误 : Error installing pg: ERROR: Failed to build gem native extension - 2

    我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby​​'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe

  8. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  9. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  10. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

    我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

随机推荐