我的 UIActivityIndi​​catorView 消失得太快,使其无用,延迟是解决此问题的最佳方法吗?

Posted

技术标签:

【中文标题】我的 UIActivityIndi​​catorView 消失得太快,使其无用,延迟是解决此问题的最佳方法吗?【英文标题】:My UIActivityIndicatorView disappears too soon making it useless, would delay be the best way to fix this? 【发布时间】:2014-02-27 01:06:06 【问题描述】:

需要一个加载器和微调器来显示在我的页面上,以显示我的 parse.com 数据库中的人员列表。现在我专注于 UITableViewController 的一个控制器。

这是我的代码:

- (void)viewDidLoad

    [super viewDidLoad];
    dispatch_queue_t downloadQueue = dispatch_queue_create("downloader", NULL);
    UIView *taggedView = [[LoadingView alloc] initWithFrame:[[self view] bounds]];
    [taggedView setTag:17];
    [[self view] addSubview:taggedView];

    dispatch_async(downloadQueue, ^
        //Load my data from parse.com here into an NSMutableArray
        //which is the used in my datasource methods
        NSLog(@"downloading");


        dispatch_async(dispatch_get_main_queue(), ^
            //Here is where I hide the loader view
            NSLog(@"downloading done.");
            UIView *viewToRemove = [[self view] viewWithTag:17];
            [viewToRemove removeFromSuperview];
        );
    );

我已经删除了从 parse.com 加载我的数据的代码,以使事情变得更干净,但 commeting 清楚地表明了它的去向。

除非我注释掉 viewToRemove 行,否则我永远不会看到加载程序。然后它显然停留在屏幕上。问题是它只是加载并且被带走太快。同样出于某种原因,我还可以看到表格行线,但我不想看到它们。我希望加载器视图视图覆盖整个区域,直到加载数据,然后可能一两秒后自行删除。

LoaderView 文件(在网上找到):

#import "LoadingView.h"

@implementation LoadingView

#define LABEL_WIDTH 80
#define LABEL_HEIGHT 20

- (id)initWithFrame:(CGRect)frame

    self = [super initWithFrame:frame];
    if (self) 
        [self setBackgroundColor:[UIColor whiteColor]];
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake((self.bounds.size.width-LABEL_WIDTH)/2+20,
                                                                   (self.bounds.size.height-LABEL_HEIGHT)/2,
                                                                   LABEL_WIDTH,
                                                                   LABEL_HEIGHT)];
        label.text = @"Loading…";
        label.center = self.center;
        UIActivityIndicatorView* spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        spinner.frame = CGRectMake(label.frame.origin.x - LABEL_HEIGHT - 5,
                                   label.frame.origin.y,
                                   LABEL_HEIGHT,
                                   LABEL_HEIGHT);
        [spinner startAnimating];
        [self addSubview: spinner];
        [self addSubview: label];
    
    return self;

所以我的任务是创建一个带有微调器和“正在加载”字样的白色背景视图。我的方法是有效的还是有更好的方法来做到这一点?如果是这样,我将不胜感激。

亲切的问候

更新

解析为我获取数据的代码。

// Grab data for datasource and store in people array
 NSLog(@"view will appear");
people = [[NSMutableArray alloc] init];

PFQuery *query = [PFQuery queryWithClassName:@"People"];
[query whereKey:@"active" equalTo:@1];
[query orderByDescending:@"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) 

    if (!error) 
        for (PFObject *object in objects) 
          //  NSLog(@"%@", object);
            Person *person = [[Person alloc] init];
            [person setName:[object objectForKey:@"name"]];
            [person setNotes:[object objectForKey:@"notes"]];
            [person setAge:[[object objectForKey:@"age"] intValue]];
            [person setSince:[object objectForKey:@"since"]];
            [person setFrom:[object objectForKey:@"from"]];
            [person setReferenceNumber:@"14-334544"];

            PFFile *userImageFile = object[@"image"];
            [userImageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) 
                if (!error) 
                    UIImage *image = [UIImage imageWithData:imageData];
                    [person setImage:image];
                
            ];


            [person setActive:[[object objectForKey:@"active"] intValue]];
            [person setObjectId:[object objectId]];
            [people addObject:person];


        


        dispatch_async(dispatch_get_main_queue(), ^ 
            [[self tableView] reloadData];
        );


     else 
        // Log details of the failure
        NSLog(@"Error: %@ %@", error, [error userInfo]);


    


];

【问题讨论】:

您下载时使用的 Parse 方法是什么?是downloadInBackground 方法还是阻塞了它所在的线程? 是的,它是 findObjectsInBackgroudWithBlock 【参考方案1】:

您的所有 Parse 代码都是异步的,因此几乎可以立即完成。当视图实际出现时(在viewDidLoadviewWillAppearviewWillLayoutSubviewsviewDidLayoutSubviews 全部完成之后),所有 Parse 代码都已完成,因为它会立即返回。

对于您正在寻找的效果,您应该阻止您的后台 Parse 线程。

例如,改变:

[userImageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) 
    if (!error) 
        UIImage *image = [UIImage imageWithData:imageData];
        [person setImage:image];
    
];

到:

NSError *error;
NSData *imageData = [userImageFile getData:&error];
if (!error) 
    UIImage *image = [UIImage imageWithData:imageData];
    [person setImage:image];

您需要类似地更改 [PFQuery -findObjectsInBackgroundWithBlock:] 以使用同步版本。

但是,请考虑另一种选择:不显示加载器,继续使用背景块,然后在数据进入时显示数据。这比显示加载器的体验要好得多。

tl;dr:您同时使用 GCD 异步块和 Parse 的背景块。只需使用其中一个即可。

【讨论】:

我考虑过使用替代方法,但我注意到在加载数据之前的一瞬间,我看到“标题”和“副标题”这两个词代替了实际数据的位置。这就是我想要一个装载机的主要原因。隐藏所有正在发生的事情。 只需在您的 xib/storyboard 中将这些字符串设置为空白即可。 您也可以在您的 awakeFronNib 方法中以编程方式更改它们。 前几天我在情节提要选项中尝试了这个。删除了子标题和标题中的文本,然后我的数据停止显示在表格中,所以我撤消了删除操作,它们再次显示。 我不想偏离主题(编辑标签将是一个单独的问题),但您应该能够做到这一点。删除文本后可能是帧大小的问题?无论如何,我相信我已经回答了这个问题。如果您想处理情节提要,您应该在此处标记一个答案已接受并为此发布一个单独的问题。【参考方案2】:

由于您使用的是findObjectsInBackgroundWithBlock,因此要在主线程上执行的代码会立即执行,并在找到对象时执行该块。您删除加载程序的代码应该在该块中已经存在的调度异步中执行:

[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) 
    // do something with the objects
    dispatch_async(dispatch_get_main_queue(), ^
            [[self tableView] reloadData];
            // remove the loader
            NSLog(@"downloading done.");
            UIView *viewToRemove = [[self view] viewWithTag:17];
            [viewToRemove removeFromSuperview];
    );
];

关于在加载对象之前查看单元格的问题,您应该确保您正在重用单元格并且您的 tableViewController 的委托方法正确响应对象的数量,以便在您下载对象之前没有返回要放入 tableview 的数据。

【讨论】:

以上是关于我的 UIActivityIndi​​catorView 消失得太快,使其无用,延迟是解决此问题的最佳方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 UIActivityIndi​​cator 在 UIButton 中以负 x 坐标作为子视图

UIActivityIndi​​catorView 不会在正确的时间停止

UIActivityIndi​​catorView 不工作(获取影响 UIActivityIndi​​catorView 的 Facebook 权限)

UIActivityIndi​​catorView 正确使用

我的 UIActivityIndi​​catorView 消失得太快,使其无用,延迟是解决此问题的最佳方法吗?

UIActivityIndi catorView未在webview中显示