views:

204

answers:

2

I'm stuck with this problem, looks like multithreading one but I'm quite new to this kind of topics. I need some help form experts!!!

[Problem Conditions] (1) Need to call a method which has 3 arguments, one argument is "@selector( myMethod: )"

(2) Need to call (1) for multiple times

(3) Need to make sure each of (1)'s selector is done in order to move on to next steps

(4) @selector( myMethod: ) is setting up xArray, an array of object X to make it simple

(5) So, logically I have one xArray with multithreads accessing it, and somehow need to process all elements of xArray...

[Thoughts]

performSelector isn't helpful because the one I need to put is a method with @selector argument...

[Pseudo-Code]


// The Starting Point of Alghorithm
- (void)initialCallerMethod {

  for(int i=0; i < [calendarArray count]; i++) {
    calendar = [calendarArray objectAtIndex:i];  
    // fetch the events feed
    NSString* alternateLink = [calendar alternateLink];
    NSURL* feedURL = [NSURL URLWithString:alternateLink];
    if (feedURL) {

      [self setEventFeed:nil];

      GDataQueryCalendar *query = [GDataQueryCalendar calendarQueryWithFeedURL:feedURL];
      [query setMaxResults:100]; 

      GDataServiceGoogleCalendar *service = [[[CalendarService alloc] init] calendarService];
      GDataServiceTicket *ticket;
      ticket = [service fetchFeedWithQuery:query 
        delegate:self
        didFinishSelector:@selector(calendarEventsTicket:finishedWithFeed:error:)];

      if ([self eventFetchError] == nil) {
        // query succeeded
 NSLog(@"Querry succeeded");
 [self howToDoThis];    
      }
    }
  }
}

// @selector's method with 3 arguments
- (void)calendarEventsTicket:(GDataServiceTicket *)ticket
            finishedWithFeed:(GDataFeedCalendarEvent *)feed
                       error:(NSError *)error {

 [self setEventFeed:feed];
}

//
// Somewhere I want to do something like this
//
- (void) howToDoThis {
  GDataFeedCalendarEvent* feed = [self eventFeed];
  NSArray *entries = [feed entries];

  // for now, I get's zero...
  NSLog(@"FEED ENTRIES COUNT: %d", [entries count]);

  for (int idx = 0; idx < [entries count]; idx++) {
    // to make it simple, I'm just accumulating elements of array
    id elm = [entries objectAtIndex:idx];
    [anArrayToSumUp addObject: elm ]; 
   }
}

I am truly overflowed... Please advice...

Katsumi

==== some progress, or struggles... 2009/10/29

Tim, I did some reading for NSInvocation and NSInvocationOperation. It sounds useful. Now, do you know how to pass "the address of selector"? you see, I can set target, selector and arguments with NSInvocation but how can I pass the @selector(...)'s address?

[Before using NSInvocation] ticket = [service fetchFeedWithQuery:query delegate:self didFinishSelector:@selector(calendarEventsTicket:finishedWithFeed:error:)];

[Trying to use NSInvocation, getting closer except for passing selector as an argument]

retInvo = [NSInvocation invocationWithMethodSignature: [self methodSignatureForSelector:@selector(finishMethod:withArray:)]]; [retInvo setTarget:self];

// * This is not OK * [retInvo setSelector:@selector(finishMethod:withArray:)]; // This is not OK

[retInvo setArgument:&calendar atIndex:2]; [retInvo setArgument:&events atIndex:3];

NSInvocationOperation* invoFinishOperation = [[NSInvocationOperation alloc] initWithInvocation:retInvo];

A: 

To deal with your need to call methods with selectors as arguments, I'd look at NSInvocation. An instance of NSInvocation is essentially a method call turned into an object - you specify a target and a series of arguments, then call invoke on the invocation and it gets run as though it were a straightfoward method call.

Tim
Very few people ever need to use NSInvocation directly.
Azeem.Butt
Then what would you recommend?
Tim
Tim, thank you for leaving me a keyword, NSInvocation.I did some reading on it and made some progress.I couldn't post long message here so I edited Question.Please check it out.Thank you.
Katsumi
NSInvocation seems like *exactly* the right thing. See the Stanford University iPhone Development video podcast episode #11 which covers this - available in iTunes for free.
JBRWilkinson
@Katsumi: I think you're misunderstanding what the NSInvocation method `setSelector:` does - it alters the selector the invocation *will call*, not a selector used *as an argument*. If you want to pass a selector as an argument, just use `setArgument:atIndex:` like you would for any other argument.
Tim
@TimMy mistake again!So it's like this:invo = [NSInvocation invocationWithMethodSignature:[service methodSignatureForSelector:@selector(fetchFeedWithQuery:delegate:didFinishSelector:)]];[invo setTarget:service];[invo setSelector:@selector(fetchFeedWithQuery:delegate:didFinishSelector:)];SEL aSelector = @selector(calendarEventsTicket:finishedWithFeed:error:);[invo setArgument:id myself = self;[invo setArgument:myself atIndex:3];[invo setArgument:Did I do OK? 1) passing the address of "self"2) pass the address of selecotor
Katsumi
Tim
A: 

Waiting for these methods to return is going to make your UI appear to be hung. That's why they execute asynchronously and give you a callback. The method you supply as said callback is what should be responsible for telling the rest of your app that it's done waiting.

Azeem.Butt
NSD, thank you for your comment.I tried to make use of my callback.Things is that my callback gets called multiple times.The call back is accumulating object into NSMutableArray.Somehow I need to figure out all callbacks are done before calling related UIView setNeedsDisplay.As for now, calling setNeedsDisplay doesn't change the view (it gets called before the callback)Yes the array gets correct result, so one more step to consider...Katsumi
Katsumi