2013-06-11 2 views
0

여기 백엔드로 푸시하려는 일부 템플릿 (개체)이있는 상황이 있습니다. 이제 사용자가 동기화 버튼을 누르면 모든 템플릿을 얻는 백엔드 양식에 대한 연결이 있습니다. IPAD 앱의 템플릿은 백엔드에서 전송 된 템플릿과 비교됩니다. IPAD 앱의 템플릿에 ID (0)가있는 경우 백엔드에 대한 게시물이 있습니다. 그런 다음 백엔드는 ID가있는 저장된 템플리트를 리턴합니다 (로컬 저장된 템플리트에 추가).API에 대한 여러 게시물에 대해 NSURLconnection을 사용하십시오.

이제 내 문제는 내가 동일한 연결 (templateupdateconnection => 나쁜 이름 ...)을 사용하고 있다는 것입니다. 백엔드에 대한 모든 게시물에 대해. 실제 문제는 connectiondidfinishloading connection 메서드에서 백엔드에 게시 된 마지막 템플릿에서만 응답을 얻는다는 것입니다.

어떻게 해결할 수 있는지 아는 사람은 누구입니까?

미리 감사드립니다.

하는 코드

-(void)syncRegistrations:(NSArray *)arrayOfRegistrations{ 

    NSFetchRequest *request = [[NSFetchRequest alloc]init]; 
    [request setEntity:[NSEntityDescription entityForName:@"Registration" inManagedObjectContext:self.managedObjectContext]]; 

    NSError *error; 

    NSArray *Data = [self.managedObjectContext executeFetchRequest:request error:&error]; 

    BOOL old=FALSE; 


    for(int registrationCounter = 0; registrationCounter < arrayOfRegistrations.count; registrationCounter ++){ 

     NSDictionary *dictRegistration = [arrayOfRegistrations objectAtIndex:registrationCounter]; 

     for(Registration *registration in Data){ 

      if([dictRegistration objectForKey:@"id"] == registration.id){ 

       old = TRUE; 

      } 
      else if ([registration.id intValue]==0){ 

       NSString *jsonRequest = [NSString stringWithFormat:@"{\"form\":%@}",registration.form.id]; 
       NSLog(@" de jsonrequest: %@",jsonRequest); 

       NSURL *url = [NSURL URLWithString:@"http://mybackend/registrations"]; 

       NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; 
       NSData *requestData = [NSData dataWithBytes:[jsonRequest UTF8String] length:[jsonRequest length]]; 

       [request setHTTPMethod:@"POST"]; 
       [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; 
       [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 
       [request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"]; 
       [request setHTTPBody: requestData]; 

       self.registrationtoupdate = registration; 
       self.registrationUpdateConnection = NULL; 
       self.registrationUpdateConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
       [self.registrationUpdateConnection start]; 

       registration.id=[NSNumber numberWithInteger:-1]; 
       [self.managedObjectContext save:&error]; 
       old=TRUE; 

      } 


     } 

     if(old==FALSE){ 
      //nieuwe template toevoegen 
      Registration *registration = [NSEntityDescription insertNewObjectForEntityForName:@"Registration" inManagedObjectContext:self.managedObjectContext]; 
      registration.id = [dictRegistration objectForKey:@"id"]; 
      registration.form = [self getFormByID:[dictRegistration objectForKey:@"form"]]; 
      [self.managedObjectContext save:&error]; 
     } 

     old=FALSE; 

    } 

    //[self getRC]; 
    [self performSelector:@selector(getRC) withObject:nil afterDelay:3]; 

} 

CONNECTIONDIDFINISHLOADING 방법

else if([connection isEqual:self.registrationUpdateConnection]){ 

    NSDictionary *dictRegistration = [NSJSONSerialization JSONObjectWithData:self.registrationdata options:kNilOptions error:&error]; 

    NSLog(@"de data van de registratie is: %@",dictRegistration); 

    NSLog(@"de registration to update is: %@",self.registrationtoupdate); 
    self.registrationtoupdate.id = [dictRegistration objectForKey:@"id"]; 

    [self.managedObjectContext save:&error]; 


} 

답변

1

당신은 클래스로 NSURLConnection 및 모든 관련 상태 데이터를 캡슐화한다. 그 클래스가 비동기 적으로 연결을 시작하는 start 메쏘드와 요청의 결과를 나타내는 결과 인을 가진 완료 블록을 갖도록합시다. 이렇게하면 다른 연결과 응답 데이터가 일치하지 않습니다.

완료 블록에서 해당 컨텍스트를 참조하고 (업데이트 할 등록) JSON 표현을 가져 와서 을 올바른 스레드 또는 대기열에 적절하게 업데이트합니다 (아래의 "스레드 제한 ") :

그래서, 기본적으로 :

 else if ([registration.id intValue]==0) { 
      // setup the request 
      NSMutableURLRequest *request = ... 
      MyHTTPRequestOperation* op = 
       [[MyHTTPRequestOperation alloc] initWithRequest:request 
                completion:^(void)(id result)    
       { 
        if (![result isKindOfClass:[NSError class]]) { 
         assert(result != nil && [result isKindOfClass:[NSData class]]); 
         NSDictionary* dictRegistration = 
          [NSJSONSerializationJSONObjectWithData:result 
                  options:kNilOptions 
                  error:&error]; 
         // Todo: check if dictRegistration has the required type 

         id newRegistrationID = [dictRegistration objectForKey:@"id"]; 

         // Update the model on the thread/queue you defined for the 
         // NSManagedObjectContext: 
         [self updateRegistration:registration withID: newRegistrationID]; 
        } 
        else { 
         // an error occurred 
        }       
       }]; 
      [op start]; 

      registration.id=[NSNumber numberWithInteger:-1]; 
     } 

당신은 NSModelObjectContext에 익숙해야하고"감금 스레드 ".

도 참조 : WWDC/2012에서 -(id)initWithConcurrencyType:(NSManagedObjectContextConcurrencyType)ct

Core Data Release Notes for OS X v10.7 and iOS 5.0

코어 데이터 모범 사례를 바른 길에 나를 넣어 주셔서

+0

답변 해 주셔서 감사합니다! 어디로 가고 싶은지보고 있지만 새 연결 클래스에 대한 전체 예제를 제공 할 수는 있습니다. 원인을 파악할 수 없기 때문입니다. – leke

0

@CouchDeveloper, 감사 (dev에 계정이 필요합니다)!

최종 해결책은 NSURLConnection의 하위 클래스를 만들지 않고 단순한 NSURLConnection과 함께 완료 블록을 사용하는 것입니다. 다음 코드를 확인하십시오.

NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) 
{ 
    if ([data length] > 0 && error == nil){ 

     NSDictionary *dictrc = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; 
     NSLog(@"de data van de rc is: %@",dictrc); 
     rc.id = [dictrc objectForKey:@"id"]; 

     [self.managedObjectContext save:&error]; 
    } 


}]; 
+0

이것은 완전히 유효합니다. 인증과 같은 고급 사용 사례, 파일에 데이터 저장 등의 편리한 방법으로는 편리한 방법이 없습니다. MyHTTPRequestOperation 권한을 직접 생성하는 방법은 간단하지만 _ 취할 수있는 방법이 될 수 있습니다. – CouchDeveloper

+0

다음은 HTTP 요청 클래스의 매우 단순한 구현 예입니다 : https://gist.github.com/couchdeveloper/5764723 이것은'sendAsynchronousRequest : queue : completionHandler : ' – CouchDeveloper

+0

중요 : sendAsynchronousRequest : queue : completionHandler :에 대한 completionBlock의 실행 컨텍스트는 _unspecified_입니다. 즉, 스레드 일 수 있습니다. 반드시 "Core Data and Thread Refinement"를 읽고 올바른 스레드 또는 대기열에서'save :'를 실행해야합니다! 위의 코드는 충돌하고 예상치 못한 동작을 나타낼 가능성이 큽니다. – CouchDeveloper

관련 문제