0

I have a UITextField which lets the user enter a custom Album name for Facebook Photos. Once textFieldShouldReturn, I take the textField.text and send it to Facebook. Once the completion handler is called, I would like to update my model and reload the data in my tableView.

My problem is that some lines of my completionHandler are never called. I marked all lines with the debugger and once I step through the code line-by-line, some of these lines are never called, especially not the tableView reload method.

Am I doing something wrong thread-wise? Why is my completionHandler in parts cancelled and never called?

Here's my code:

-(BOOL)textFieldShouldReturn:(UITextField *)textField {

NSString *newAlbumName;
newAlbumName = textField.text;

NSMutableDictionary* parameters = [NSMutableDictionary dictionary];
[parameters setObject:newAlbumName forKey:@"name"];
[parameters setObject:newAlbumName forKey:@"message"];

FBRequest* request = [FBRequest requestWithGraphPath:@"me/albums" parameters:parameters HTTPMethod:@"POST"];

FBRequestConnection *connection = [[FBRequestConnection alloc] init];
[connection addRequest:request
     completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
         if (!error) {
             NSDictionary *newAlbum;
             [newAlbum setValue:newAlbumName forKey:@"name"];
             [self.albums addObject:newAlbum];
             NSLog(@"created: %@", [newAlbum objectForKey:@"name"]);
             [self.tableView reloadData];
         }
         else {
             NSLog(@"Error: %@", error.userInfo);
         }


     }];
[connection start];

[textField resignFirstResponder];
[textField removeFromSuperview];



   return YES;

}
n.evermind
  • 11,944
  • 19
  • 78
  • 122
  • Obviously the lines of code in the body of your `if` statement won't be executed if the condition is not met. – jlehr Nov 27 '13 at 20:44
  • @jlehr That is not the issue. the if statement was executed but only a few lines of that statement were executed. The problem, in the end, was how I initialised the NSDictionary. Right would have been: NSDictionary *newAlbum = [[NSDictionary alloc] initWithObjectsAndKeys:newAlbumName, @"name", nil]; – n.evermind Nov 28 '13 at 07:40

2 Answers2

1

You should not call self directly in your block. It may lead to a retain cycle. So before the block declare:

__weak typeof(self) weakSelf = self;

And use weakSelf in your block instead of self.

Franck
  • 742
  • 3
  • 11
  • The OP's question is unrelated to retain cycles. – jlehr Nov 27 '13 at 20:43
  • Thanks Franck. It turned out that the issue was how I was initialising the NSDictionary. This lead to weird skipping of code which I still haven't quite understood, but this fixed it: NSDictionary *newAlbum = [[NSDictionary alloc] initWithObjectsAndKeys:newAlbumName, @"name", nil]; – n.evermind Nov 28 '13 at 07:37
  • In any case, I think you're answer is important as I should not call self in the block. – n.evermind Nov 28 '13 at 07:38
  • it is great that you find the solution! Thanks – Franck Nov 28 '13 at 14:46
1

I believe that this is threading issue. I never worked with FBRequestConnection class but if its block is executed on the background thread you need to update your UI on the main thread like this:

if (!error) {
    NSDictionary *newAlbum;
    [newAlbum setValue:newAlbumName forKey:@"name"];
    [self.albums addObject:newAlbum];
    NSLog(@"created: %@", [newAlbum objectForKey:@"name"]);
    dispatch_async(dispatch_get_main_queue(),^{
        [self.tableView reloadData];
    });
}
Guferos
  • 4,337
  • 5
  • 18
  • 25
  • Thanks for your answer. I haven't considered that this could clock if executed on the background thread. However, the problem was, in the end, how I initialised the NSDictionary. Right way would have been: NSDictionary *newAlbum = [[NSDictionary alloc] initWithObjectsAndKeys:newAlbumName, @"name", nil]; – n.evermind Nov 28 '13 at 07:39