1

In each loop, I initialize a connector class with an id that is used to perform a JSON call. The problem is, is that this loop continues to iterate before the connectionDidFinishLoading delegate method of the connector class completes, parses the JSON as needed then uses a delegate method with information that it retrieved.

for(NSDictionary *item in views){

   NSInteger myID = [[item valueForKey:@"id"] integerValue];

 //filter contains these two dictionaries
   NSDictionary *ownerDictionary = [filterDictionary valueForKey:@"owner"];
   NSString *ownerDisplayName = [ownerDictionary valueForKey:@"displayName"];

   self.projectName = projectName;
   self.ownerName = ownerDisplayName;


   //value inside dictionary for owner
   NSString *ownerDisplayName = [ownerDictionary valueForKey:@"displayName"];

   //I initialize the connector class here
   self.sprintConnector = [[SprintConnector alloc] initWithId:myID];
   [self.sprintConnector setDelegate:self];



//**I do not want to continue this loop until the delegate method that i implement is called**/
}

//implementation of delegate method 
-(void)didFinishLoadingStuff:(MyObject *)obj{

    Project *newProject = [[Project alloc] init];
    newProject.projectName = self.projectName;
    newProject.projectOwner = self.ownerName;
    newProject.sprint = sprint;
   //Ok now i have the information that i need, lets continue our loop above
}

//The method of connector class to set up the request is here:

-(void)retrieveSprintInfoWithId{

    NSURLConnection *conn;
    NSString *urlString = @"myJSONURL";
    NSURL *url = [NSURL URLWithString:[urlString stringByAppendingString:self.ID]];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//    conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    NSLog(@"data coming from request: %@", data );
    [self.data appendData:data];

}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection{

    NSLog(@"we finished loading");
    NSError *error = nil;

    self.projectsDict = [[NSDictionary alloc] initWithDictionary:[NSJSONSerialization JSONObjectWithData:self.data options:NSJSONReadingMutableContainers error:&error]];

    NSLog(@"Our sprint array with id: %@ %@", self.ID, self.projectsDict);

//this is where we parse the JSON then use the delegate method that the above class will implement
    [self parseJSON];

}



-(void)parseJSON{

[self.delegate didFinishLoadingStuff:SomeObject];
}

I want to be able to force the connectionDidFinishLoading method to be called ->parseJSON->delegate method and for the implementation of that method as mentioned above to complete before the loop continues.

What are my options? Best practices? etc?

cspam
  • 2,911
  • 2
  • 23
  • 41
  • You don't "block" code, you let it complete, go back to the "run loop", then wait for an event that tells you to continue with whatever operation you were doing. – Hot Licks Feb 25 '15 at 22:24
  • the connectionDidFinishLoading method in the connector class never executes though, not once until the loop is complete and i need it to so that i can build my custom object in the delegate method that I implement – cspam Feb 25 '15 at 22:29
  • Then maybe you're looping at an inappropriate time. – Hot Licks Feb 25 '15 at 22:36

1 Answers1

2

What you want to do is synchronously make the requests, I will show you how to do that, but you should not be doing that, so after I show you how to make a synchronous request I will show you how you should handle this

1- To issue requests synchronously you can use the sendSynchronousRequest method of NSURLConnection, this will block until data is received and return the data, here is are the docs. You should not do this as you may block the main thread which would cause a bad user experience (also other reasons why this is bad practice)

2- You should be issuing your requests async as you do in your sample code, in your callback you should fetch the appropriate object (which you should know by the item id), and then do whatever it is you need to do to that object... If you need everything to be loaded in order for some action to take place, then you should keep track of that (sent requests vs responses received)

Hope that helps

Daniel

Daniel
  • 22,363
  • 9
  • 64
  • 71
  • Thanks Daniel. My main problem is, is that I am losing the project name and owner being that I only get those values after the loop is complete because the json parsing and thus the delegate method calls happen afterward. I need for the connection finished delegate method to be called -> Json parsing -> etc as the code shows before the loop continues. Since you say do everything async then I'm not sure I understand the part about keeping track of requests/responses – cspam Feb 25 '15 at 23:25
  • 1
    @cspam You havent designed it correctly, not sure what filterDictionary nad ownerDictnary are but you need to keep the whole state of the object you are processing , so maybe instead of assigning an id to SprintConnector assign an object with all the data you might need, or have the extra data store in your items.. – Daniel Feb 25 '15 at 23:58
  • Because I have to make 2 separate json calls. After making the first one I can get the id along with other info (like owner etc) then I have to use the id for a separate json call (different end point), which is the code we are discussing now. I decided to do it this way instead of keeping up with different NSURL connections in the 'connectionDidFinishLoading' and to keep everything modular. – cspam Feb 26 '15 at 00:07
  • daniel, sorry was on phone earlier and didnt see the last part of your comment. that makes sense to me. Thanks for the help. Ill try it out – cspam Feb 26 '15 at 01:15