質問

The code below is something almost identical to what I used with ASI, but now I am using AFNetworking. My guess is that it is slow because it is running the success block on the main thread. I tried to set the successCallbackQueue to a new queue, but it does not seem to be working. It is just very slow and does not do this efficiently. How can I speed it up or ensure it is running in the background thread?

#define kPerPage 10

- (void) pullData {
    NSURL *url = [API homeRecentUrlWithPage:self.currentRecentPage limit:kPerPage];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    dispatch_queue_t requestQueue = dispatch_queue_create("requestQueue", NULL);
    AFJSONRequestOperation *operation;
    operation.successCallbackQueue = requestQueue;
    operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        NSArray* modelArray = [JSON objectForKey:@"models"];

        for (int i = 0; i < [modelArray count]; i++)
        {
            Model *b = [Model alloc];
            b = [b initWithDict:[Model objectAtIndex:i]];
            [self.otherArray addObject:b];
        }
        [_modelTable reloadData];

    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
        NSLog(@"%@", [error userInfo]);
    }];
    [operation start];
}


- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString* identifier = @"ModelTableCell";
    cell = (ModelTableCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
    if (cell == nil) {
        cell = [[ModelTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
        cell.selectionStyle = UITableViewCellAccessoryNone;
    }
    if([indexPath row] == (self.currentRecentPage-1) * kPerPage + 5) {
        NSLog(@"%d aaa", self.currentRecentPage);

        self.currentRecentPage++;
        [self pullData];
    }


    Model *b = [self.models objectAtIndex:[indexPath row]];
    [cell populateWithModel:b];
    return cell;
}

正しい解決策はありません

他のヒント

I don't think you are setting a queue for your callback correctly

You assign the callback queue to an operation, but then you create an operation which overwrites it.

// You create the queue
dispatch_queue_t requestQueue = dispatch_queue_create("requestQueue", NULL);

// You declare an operation, but you don't create it.
AFJSONRequestOperation *operation;

// You assign the requestQueue to this uninitialised operation
operation.successCallbackQueue = requestQueue;

// You create the operation here, and it overwrites the requestQueue you have set
operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {

You should be setting the successCallbackQueue after creating the operation.

Edited to add a bit more

And a bit more reading on my part. With GCD and on Mountain Lion or iOS6 apps, if you use ARC, it takes care of the memory management of queues. So when you declare a queue within a method, and assign it to a property that just assigns the value (as the successCallbackQueue property declares in AFNetworking), then the queue gets released, and the operation doesn't hold on to it, so it's left with a NULL queue and you get the bad access.

So, the way to fix this is to have an iVar in your controller that maintains a strong reference to the queue so even though the operation doesn't retain the queue, your controller will, so it won't get cleaned up from under you.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top