2013-09-22 5 views
0

У меня очень проблематичная проблема с NSURLConnection. Он возвращает данные в другой поток или что-то в этом роде, вещи не работают в правильном порядке. Я должен получить данные json, затем проанализировать его, но данные фактически принимаются после сбоя анализатора. Вот журнал.NSURLConnection Data Retrieval

2013-09-22 14:44:40.454 WebServiceExample[39306:a0b] Parsing Error: Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (No value.) UserInfo=0xa0b47e0 {NSDebugDescription=No value.} 2013-09-22 14:44:41.312 WebServiceExample[39306:a0b] Succeeded! Received 112 bytes of data

Я делаю небольшую структуру, чтобы облегчить свою жизнь, чтобы подключиться к рельсам API, я звоню это объективные рельсы ИЛИ, но я уже провел весь уик-энд, пытаясь понять, что я делаю неправильно , Вот код:

@interface ORObject : NSObject 

@property (nonatomic, retain) NSMutableDictionary *properties; 
@property (nonatomic, retain) ORWebManager *webManager; 
@property (nonatomic, retain) NSString *route; 
@property (nonatomic, retain) NSString *singularClassName; 

- (id) initWithRoute:(NSString *) route webManager:(ORWebManager *) webManager; 
- (id) initWithRoute:(NSString *) route; 
- (ORObject *) find:(NSInteger) identifier; 
@end 

Здесь реализация находке:

- (ORObject *) find:(NSInteger) identifier 
{ 

    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/%@/%ld.%@", [ ORConfig sharedInstance].baseURL, self.route, (long)identifier, self.webManager. parser.contentType]]; 

    ORObject *object = [self.webManager httpGet:url]; 

    if (object) { 
     object.route = self.route; 
     object.webManager = self.webManager; 
    } 

    return object; 
} 

Вот метод HttpGet класса ORWebManager

- (ORObject *) httpGet:(NSURL *)url 
{ 
    ORGetRequester *requester = [[ORGetRequester alloc] init]; 
    NSMutableData *data = [requester request:url]; 
    return [self.parser toObject:data]; 
} 

Суперкласс ORGetRequester является ORHTTPRequester и реализует методы протокола NSURLConnectionDelegate

@interface ORHTTPRequester : NSObject<NSURLConnectionDelegate> 
@property (nonatomic, retain) NSMutableData *receivedData; 
@property (nonatomic, retain) NSMutableURLRequest *req; 
@property (nonatomic, retain) NSURLConnection *connection; 
@end 

@implementation ORHTTPRequester 
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse 
    [self.receivedData setLength:0]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    [self.receivedData appendData:data]; 
} 

- (void)connection:(NSURLConnection *)connection 
    didFailWithError:(NSError *)error 
{ 
    NSLog(@"Connection failed! Error - %@ %@", 
      [error localizedDescription], 
      [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]); 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    NSLog(@"Succeeded! Received %d bytes of data",[self.receivedData length]); 
} 
@end 

И, наконец, здесь ORGetRequester, здесь происходит «волшебство».

@interface ORGetRequester : ORHTTPRequester 
- (NSMutableData *) request:(NSURL *)url; 
@end 

@implementation ORGetRequester 
- (NSMutableData *) request:(NSURL *)url 
{ 
    self.req = [NSMutableURLRequest requestWithURL:url 
               cachePolicy:NSURLRequestUseProtocolCachePol icy 
              timeoutInterval:60.0]; 
    self.receivedData = [[NSMutableData alloc] init]; 
    self.connection = [[NSURLConnection alloc] initWithRequest:self.req delegate:self]; 

    if (!self.connection) { 
     NSLog(@"Connection Failed"); 
    } 

    return self.receivedData; 
} 
@end 

ответ

1
self.connection = [[NSURLConnection alloc] initWithRequest:self.req delegate:self]; 

возвращается немедленно, потому что она начинает операцию асинхронной. Вам необходимо проанализировать данные, когда вызывается connectionDidFinishLoading:.

Или рассмотреть вопрос об использовании:

+ (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue *)queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler 

Блок завершения будет вызываться, когда операции HTTP завершена. Обработайте данные в блоке завершения и сообщите об объекте, который нуждается в данных. Вероятно, это хорошая ставка, если вам не нужны другие методы делегата.

+0

Теперь, когда я думаю об этом, нет никакого способа сделать API ActiveRecord-ish, он должен быть синхронным, и это не хорошо. Я хотел упростить вещи и не иметь раздутый ViewController с миллионом методов, но похоже, что iOS способ обработки HTTP-запросов асинхронно. Я должен переделать все объекты Objective Rails. Большое спасибо за вашу помощь @Zaph, это очень ценится. * EDIT * Просто вспомнил шаблон наблюдателя, это может быть то, что мне нужно :) –