2

I am using NSOperationQueue and NSOperation to perform requests to twitter. However when I am performing this request, and receiving results, the application freezes for a few seconds until all the results have been downloaded.

Is there a way to stop this happening?

Edit----

My Code is:

- (void)getPublicTimeline {
    TwitterRequest *request = [[TwitterRequest alloc] initWithRequestType:publicTimelineRequest andManager:self];
    [queue addOperation:request];
    [queueArray addObject:request];
    [request release];
}

TwitterRequest (NSOperation)

- (id)initWithRequestType:(requestTypeEnum)type andManager:(TwitterManager *)managr {
self = [super init];
if (self) {
    [self setRequestType:type];
    [self setManager:managr];
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
    [self performSelector:@selector(startWithRequest)];
}
return self;

}

- (void)startWithRequest {
if (requestType == statusRequest) {
    [self performSelector:@selector(doStatusRequest)];
}
  else if (requestType == privateMessageRequest) {
    [self performSelector:@selector(doPrivateMessageRequest)];
}
else if (requestType == sentPrivateMessageRequest) {
    [self performSelector:@selector(doSentPrivateMessageRequest)];
}
else if (requestType == allFollowersRequest) {
    [self performSelector:@selector(allFollowersRequest)];
}
else if (requestType == publicTimelineRequest) {
    [self performSelector:@selector(doPublicTimelineRequest)];
}

}

- (void)doPublicTimelineRequest {
    connectionId = [manager.engine getPublicTimeline];
}

Twitter Manager:

- (void)statusesReceived:(NSArray *)statuses forRequest:(NSString *)connectionIdentifier {
     TwitterRequest *lastObj = (TwitterRequest *)[queueArray lastObject];
    if (lastObj.requestType == statusRequest) {
        if ([[self delegate] conformsToProtocol:@protocol(TwitterManagerDelegate)] && [[self delegate] respondsToSelector:@selector(manager:receivedStatuses:)]) {
            [[self delegate] manager:self receivedStatuses:statuses];
        }
    }
    else if (lastObj.requestType == publicTimelineRequest) {
        NSMutableArray *tweets = [[NSMutableArray alloc] init];
        for (int i = 0; i < [statuses count]; i++) {
            TimelineTweet *tt = [[TimelineTweet alloc] init];
            User *user = [[User alloc] init];

            tt.createdAt = [[statuses objectAtIndex:i] objectForKey:@"created_at"];
            if ([[[statuses objectAtIndex:i] objectForKey:@"favorited"] isEqualToString:@"false"]) 
                tt.isFavorited = FALSE;
            else 
                tt.isFavorited = TRUE;
            if ([[[statuses objectAtIndex:i] objectForKey:@"retweeted"] isEqualToString:@"false"]) 
                tt.retweeted = FALSE;
            else 
                tt.retweeted = TRUE;
            tt.retweetCount = [[statuses objectAtIndex:i] objectForKey:@"retweet_count"];
            tt.source = [[statuses objectAtIndex:i] objectForKey:@"source"];
            tt.tweet = [[statuses objectAtIndex:i] objectForKey:@"text"];
            tt.tweetID = [[statuses objectAtIndex:i] objectForKey:@"id"];
            user.createdAt = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"created_at"];
            user.description = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"description"];
            user.favouritesCount = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"favourites_count"];
            user.friendsCount = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"friends_count"];
            if ([[[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"verified"] isEqualToString:@"false"]) 
                user.isVerified = FALSE;
            else
                user.isVerified = TRUE;
            user.lang = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"lang"];
            user.listCount = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"listed_count"];
            user.location = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"location"];
            user.name = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"name"];
            user.profileBackgroundColor = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"profile_background_color"];
            user.profileBackgroundImageURL = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"profile_background_image_url"];
            user.profileImageURL = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"profile_image_url"];
            user.screenName = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"screen_name"];
            user.tweetCount = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"statuses_count"];
            user.url = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"url"];
            user.userID = [[[statuses objectAtIndex:i] objectForKey:@"user"] objectForKey:@"id"];
            user.profileImageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[user profileImageURL]]];
            tt.user = user;
            [user release];
            [tweets addObject:tt];
            if ([[self delegate] conformsToProtocol:@protocol(TwitterManagerDelegate)] && [[self delegate] respondsToSelector:@selector(manager:didReceivePublicTimelineObject:)]) {
                [[self delegate] manager:self didReceivePublicTimelineObject:tt];
            }
            [tt release];
        }
        if ([[self delegate] conformsToProtocol:@protocol(TwitterManagerDelegate)] && [[self delegate] respondsToSelector:@selector(manager:didRecievePublicTimeline:)]) {
            [[self delegate] manager:self didRecievePublicTimeline:tweets];
        }
        [tweets release];
    }
}

I have only posted the code for getting the public timeline.

max_
  • 24,076
  • 39
  • 122
  • 211
  • Could you show the code used to handle the twitter requests? – Wolfgang Schreurs May 01 '11 at 16:41
  • Why do you keep using `[self performSelector:@selector(foo)]` rather than just `[self foo]`? – Rob Napier May 01 '11 at 16:47
  • I implemented the method declaration later on, and did not update the code. do you think this could be a cause? – max_ May 01 '11 at 16:50
  • This is not the cause, just unnecessary. If you need to call private methods prior to their implementation, just declare them in a private extension at the top of the .m file. There's a good example in this question. http://stackoverflow.com/questions/647079/is-it-possible-to-declare-a-method-as-private-in-objective-c – Rob Napier May 01 '11 at 18:07
  • 1
    You may have meant here that you implemented them later in time. If that's the case, don't do it this way. Comment out the call and put `NSAssert(NO, @"Implement");` before it. This is a better way to remind yourself to implement things that need implementing and gives you an easy thing to search for when you think you're done. – Rob Napier May 01 '11 at 18:09
  • hey, yes I was doing the private interface methods anyway. Thanks for the idea, it will definitely come in usefull. Please could you provide me with an example as to what needs to be going on to give an asychronous NSURLConnection before I accept your answer? – max_ May 01 '11 at 18:34
  • See the URL Loading System Programming Guide. It includes full sample code for using NSURLConnection. http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.htm – Rob Napier May 02 '11 at 15:03

1 Answers1

3

You're probably using a non-concurrent NSOperation. See Operation Queues in the Concurrency Programming Guide, especially the section on "Concurrent Versus Nonconcurrent Operations."

Typically, though, I'd strongly recommend using an asynchronous NSURLConnection rather than your own NSOperation to perform this kind of function. This is exactly what NSURLConnection does very well.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610