dinesh
dinesh

Reputation: 837

refreshcontrol endrefreshing has to wait for the subclass

I have a implemented a refreshcontrol for my tableview and it works fine. But I wanna achieve to invoke another class execute the process within that class. I want my refreshcontrol should wait until the execution of that class.

Eg: I have some database changes in the Player class. Now the refreshcontrol ends the refresh while the database changes are in progress.

-(void)pullToRefresh{
    UpdOther *updO = [[UpdOther alloc] initWithProfile:@"Player"];
    [updO release];
    [refreshControl endRefreshing];
}

Upvotes: 1

Views: 736

Answers (1)

Rob
Rob

Reputation: 437622

Rather than having the pullToRefresh method wait for the update, it would be better if you simply used a completion block in your update process, so pullToRefresh could tell the update process what to do when the update was done.

For example, rather than having the initWithProfile perform the update process, you could have some method, say performUpdateWithCompletion do it, but give it a completion block:

- (void)performUpdateWithCompletion:(void (^)(void))completionBlock
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // do synchronous update here

        // when done, perform the `completionBlock`

        if (completionBlock) {
            dispatch_async(dispatch_get_main_queue(), ^{
                completionBlock();
            });
        }
    });
}

Then your pullToRefresh can specify what it wants the update process to do upon completion, for example:

- (void)pullToRefresh{
    UpdOther *updO = [[UpdOther alloc] initWithProfile:@"Player"];
    __weak typeof(self) weakSelf = self;
    [updO performUpdateWithCompletion:^{
        typeof(self) strongSelf = weakSelf;
        [strongSelf.refreshControl endRefreshing];
    }];
    [updO release];
}

There are other approaches, too, (delegate pattern, notification pattern), but I prefer the in-line immediacy of the block-based solution.


By the way, if UpdOther is using the NSURLConnectionDataDelegate methods, you obviously need to call the completionBlock from some other method (e.g., connectionDidFinishLoading). So, in that case, you'd define a block property in UpdOther as so:

@property (nonatomic, copy) void (^updateCompletionBlock)(void);

Or, you can define a typedef for this block:

typedef void (^UpdateCompletionBlock)(void);

and then use that in your property declaration:

@property (nonatomic, copy) UpdateCompletionBlock updateCompletionBlock;

Anyway, in that case, your performUpdateWithCompletion would save a copy of the block in that property:

- (void)performUpdateWithCompletion:(void (^)(void))completionBlock
{
    self.updateCompletionBlock = completionBlock;

    // now initiate time consuming asynchronous update here
}

And then, however you complete your download, you can call the saved completion block there:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // do whatever extra steps you want when completing the update

    // now call the completion block

    if (self.updateCompletionBlock) {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.updateCompletionBlock();
        });
    }
}

Upvotes: 1

Related Questions