0

UPDATE: I just found a tricky part... if I do something like this, it works:

[_friendsArrayInBlock insertObject:@"Bla" atIndex:itemIndex];

But it doesn't:

[_friendsArrayInBlock insertObject:friend atIndex:itemIndex];

Why I cannot add a custom object, but I can add NSString? What's the problem

ORIGINAL PART: Here you can see the relevant code part:

@implementation ORGFriendsTableViewController
{
    NSMutableArray *_friendsArray;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    _friendsArray = [NSMutableArray array];
    __block NSMutableArray *_friendsArrayInBlock = _friendsArray;

    [FBRequestConnection startForMyFriendsWithCompletionHandler: ^(FBRequestConnection *connection,
                                                                   id result,
                                                                   NSError *error) {
        FBGraphObject *fbGraphObject = (FBGraphObject *)result;

        NSMutableArray *userArray = fbGraphObject[@"data"];
        for (FBGraphObject *user in userArray) {

            ORGFBUser *friend = [[ORGFBUser alloc] initWithId:user[@"id"] name:user[@"name"] andPhotoURL:@"someurl"];

            NSInteger itemIndex = 0;
            [_friendsArrayInBlock insertObject:friend atIndex:itemIndex];
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForItem:itemIndex inSection:0]] withRowAnimation:UITableViewRowAnimationRight];
        }
    }];
}

The problem appears with on this line:

[_friendsArrayInBlock insertObject:friend atIndex:itemIndex];

Program recieving signal "EXC_BAD_ACCESS"

I think it's related with block concept, and altering a non thread-safe NSMutableArray from it.

Do you have any idea how to fix this?

0

2 Answers 2

3

Blocks can access instance variables without using __block (see this). Therefore this should work:

- (void)viewDidLoad
{
    [super viewDidLoad];

    _friendsArray = [NSMutableArray array];

    [FBRequestConnection startForMyFriendsWithCompletionHandler: ^(FBRequestConnection *connection,
                                                                   id result,
                                                                   NSError *error) {
        FBGraphObject *fbGraphObject = (FBGraphObject *)result;

        NSMutableArray *userArray = fbGraphObject[@"data"];
        for (FBGraphObject *user in userArray) {

            ORGFBUser *friend = [[ORGFBUser alloc] initWithId:user[@"id"] name:user[@"name"] andPhotoURL:@"someurl"];

            NSInteger itemIndex = 0;
            [_friendsArray insertObject:friend atIndex:itemIndex];
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForItem:itemIndex inSection:0]] withRowAnimation:UITableViewRowAnimationRight];
        }
    }];
}
Sign up to request clarification or add additional context in comments.

2 Comments

Not only that, but if we wanted to keep _friendsArrayInBlock, he would still not need __block, because he's not assigning to it anywhere.
Technically, using _friendsArrayInBlock and using _friendsArray directly are different; the former stores the value of _friendsArray at the time the block is created, whereas the latter uses the value when the block is run; though it probably doesn't matter in this case.
-1

try this

@implementation ORGFriendsTableViewController
{
    NSMutableArray *_friendsArray;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    _friendsArray = [NSMutableArray array];
    __block NSMutableArray *_friendsArrayInBlock = _friendsArray;

    [FBRequestConnection startForMyFriendsWithCompletionHandler: ^(FBRequestConnection *connection,
                                                                   id result,
                                                                   NSError *error) {
        FBGraphObject *fbGraphObject = (FBGraphObject *)result;

        NSMutableArray *userArray = fbGraphObject[@"data"];
        for (FBGraphObject *user in userArray) {

            ORGFBUser *friend = [[ORGFBUser alloc] initWithId:user[@"id"] name:user[@"name"] andPhotoURL:@"someurl"];

            [_friendsArrayInBlock addObject:friend];
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:_friendsArrayInBlock.count-1 inSection:0]] withRowAnimation:UITableViewRowAnimationRight];
        }
    }];
    [self.tableView reloadData];
}

2 Comments

I gather you're replacing insertObject:AtIndex: with addObject? I wish you'd also tell us what you did so we don't have to do our own mental diff in order to figure it out...
1. The problem the OP describes could not be caused by insertObject, and thus replacing insertObject with addObject will not help, but changes the behavior of the app; 2. I now notice that you're doing reloadData, too, but that's not necessary if you've done insertRowsAtIndexPaths.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.