NSOperation 实现 HTTP多线程访问
1。 从 NSOperation 派生出自己的类
#define TWITTER_URL_GET_LIST_NUMS @"http://www.xxxyyy.com/ports/miniblog/get_counts_by_account?a=%@&t=%@&f=iphone"
@protocol TwitterGetListNumsDelegate<NSObject> - (void) doneTwitterGetListNumbs:(NSData *) data; @end @interface TwitterGetListNumsOperation : NSOperation { id<TwitterGetListNumsDelegate> delegate; NSString * nsAccount; NSString * token_signature; NSString * queryAccount; } @property(retain) id delegate; @property(retain) NSString * nsAccount; @property(retain) NSString * token_signature; @property(retain) NSString * queryAccount; @end
@implementation TwitterGetListNumsOperation @synthesize delegate; @synthesize nsAccount; @synthesize token_signature; @synthesize queryAccount; - (void) cleanup: (NSData*) data { if (self.delegate && [self.delegate respondsToSelector:@selector(doneTwitterGetListNumbs:)]) [self.delegate doneTwitterGetListNumbs:data]; } - (void) main { NSString* token_url_encoded = URLENCODING(token_signature); NSString* baseUrl = [NSString stringWithFormat:TWITTER_URL_GET_LIST_NUMS, nsAccount,token_url_encoded]; // Establish the Twitter API request NSURL *url = [NSURL URLWithString:baseUrl]; NSLog(@"xxx - TWITTER_URL_GET_LIST_NUMS, url=%@", url); NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url]; if (!urlRequest) NOTIFY_AND_LEAVE(nil);//Error creating the URL Request [urlRequest setHTTPMethod: @"POST"]; [urlRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; [urlRequest setValue:@"XXXYYY" forHTTPHeaderField:@"X-XXXYYY-Client"]; NSString* strData = [NSString stringWithFormat:@"account=%@", queryAccount]; NSLog(@"xxx - strData=%@", strData); NSData* postData = [strData dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; [urlRequest setHTTPBody:postData]; NSError *error; NSURLResponse *response; NSData *tw_result = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error]; if (!tw_result) { NSString *tw_output = [NSString stringWithFormat:@"Submission error: %@", [error localizedDescription]]; NSLog(@"%@", tw_output); NOTIFY_AND_LEAVE(nil); } else { //std::string output = (char*)[ bytes]; [self cleanup:tw_result]; } } @end
2. 在类里面 实现 TwitterGetListNumsDelegate, SBJsonStreamParserAdapterDelegate 两个代理。
类里面声明以下变量:
SBJsonStreamParser *num_parser;
SBJsonStreamParserAdapter *num_adapter;
实现 TwitterGetListNumsDelegate 协议:
- (void) doneTwitterGetListNumbs:(NSData *) data { [self performSelectorOnMainThread:@selector(jsonParserFetchData:) withObject:data waitUntilDone:NO]; }
- (void) jsonParserFetchData : (NSData*) data { FLOG(@"xxx - http get lsitnums done."); if(data.length == 0) { [num_parser release]; [num_adapter release]; num_parser = nil; num_adapter = nil; return; } // Parse the new chunk of data. The parser will append it to // its internal buffer, then parse from where it left off in // the last chunk. std::string a = (char*)[data bytes]; LOG(LS_VERBOSE)<<a; SBJsonStreamParserStatus status = [num_parser parse:data]; if (status == SBJsonStreamParserError) { NSLog(@"Parser error: %@", num_parser.error); } else if (status == SBJsonStreamParserWaitingForData) { NSLog(@"Parser waiting for more data"); } [num_parser release]; [num_adapter release]; num_parser = nil; num_adapter = nil; }
在这个函数里面,调用JSON PARSER 去解析结果。
下面是 实现 JSON PArser 协议:
- (void)parser:(SBJsonStreamParser *)parser foundArray:(NSArray *)array { NSLog(@"ArrayTweet: '%@'", array); }
- (void)parser:(SBJsonStreamParser *)parser foundObject:(NSDictionary *)dict { //获得列表数量 if (parser==num_parser) { NSNumber *result = [dict objectForKey:@"result"]; FLOG(@"xxx - SBJsonStreamParser result: '%d'", [result intValue]); if ([result intValue]) { NSDictionary *data = [dict objectForKey:@"data"]; NSLog(@"xxx - tableView reloadData", data); NSNumber* BlogNum= [data objectForKey:@"blog_num"]; NSNumber* FollowNum=[data objectForKey:@"follow_num"]; NSNumber* FansNum=[data objectForKey:@"fans_num"]; NSString *strBlogNum=[[BlogNum stringValue] UTF8String]; NSString *strFollowNum=[[FollowNum stringValue] UTF8String]; NSString *strFansNum=[[FansNum stringValue] UTF8String]; } } }
3. 如何调用这个呢?
- (void) getListNum { num_adapter = [SBJsonStreamParserAdapter new]; num_adapter.delegate = self; num_parser = [SBJsonStreamParser new]; num_parser.delegate = num_adapter; num_parser.multi = YES; std::string username = @""; std::string token_signature = @""; TwitterGetListNumsOperation *operation = [[[TwitterGetListNumsOperation alloc] init] autorelease]; operation.delegate = self; operation.nsAccount = [NSString stringWithCString:username.c_str() encoding:NSUTF8StringEncoding]; operation.token_signature = [NSString stringWithCString:token_signature.c_str() encoding:NSUTF8StringEncoding]; operation.queryAccount= [NSString stringWithCString:twitter_item_.account.c_str() encoding:NSUTF8StringEncoding]; NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease]; [queue addOperation:operation]; }
如果有多个类型的NSOperation同时在一个类中进行,就创建多个 adapter和 parser,通过这个来判断是那个Operation的结果。而且由于
是多线程,所以在返回结果的时候,可能会导致crash,采取的办法是,等一个HTTP Operation操作结果返回以后,再进行下一个HTTP Opeation操作。