2013-12-08 4 views
0

내 응용 프로그램에서 웹 서비스 (안심 웹 서비스)를 사용하고 있습니다. 사용자 인증을 위해 하나의 서비스를 사용하여 로그인하는 방법, 웹 서비스를 호출하는 IBAction이있는 UIButton이 있습니다. 여기에이 웹 서비스를 호출하는 메서드가 있습니다. :멀티 스레딩을 사용하여 iphone에 로그인 하시겠습니까?

-(void)LogInMethod{ 
    NSString * password=passwordTextField.text; 
    NSString * mobileNumber=MobileTextField.text; 
    if (password.length==0 || mobileNumber.length==0) { 
     if (mobileNumber.length==0) { 
      [wrongNoteLable setText:@"please enter a valid mobile number"]; 
      [wrongNoteLable setHidden:NO]; 
     } 
     else if (password.length==0){ 
      [wrongNoteLable setText:@"please enter a valid password"]; 
      [wrongNoteLable setHidden:NO]; 
     } 
    } 
    else{ 

     NSString*UrlString=[[NSString alloc]initWithFormat:@"http://192.168.1.1:8080/test2/eattel/customers/signin/%@/123/%@",mobileNumber,password]; 
     NSURL *url = [[NSURL alloc] initWithString:UrlString ]; 
     NSError *error = nil; 
     NSStringEncoding encoding = 0; 
     customerID =[[NSString alloc]initWithContentsOfURL:url encoding:encoding error:&error]; 
     if (customerID) { 
      if (![customerID isEqualToString: @"-1"]) { 
       [self performSegueWithIdentifier:@"toMainMenuViewController" sender:self]; 
       NSLog(@"customer loged in with ID :%@",customerID); 
      } 
      else if ([customerID isEqualToString:@"-1"]){ 
       [wrongNoteLable setText:@"neither mobile number or password is wrong"]; 
       [wrongNoteLable setHidden:NO]; 
       NSLog(@"customer tried to log in with wrong password or phone Number :%@",customerID); 
      } 
     } 
     else{ 
      [wrongNoteLable setText:@"no connection to the server"]; 
      [wrongNoteLable setHidden:NO]; 
      NSLog(@"customer tried to log in but there is no server connection :%@",customerID); 
     } 
    } 

    // NSLog([dispatch_get_main_queue() description]) 

} 

와 나는이 같은 IBAction를에 스레드를 사용하여 이전 메소드를 호출하는 것을 시도하고있다 :

- (IBAction)signInAction:(id)sender { 

    NSThread* myThread = [[NSThread alloc] initWithTarget:self 
               selector:@selector(LogInMethod) 
                object:nil]; 
    [myThread start]; // Actually create the thread 


} 

하지만이 오류 데 :

WebThreadLockFromAnyThread(bool), 0xa08cf60: Obtaining the web lock from a thread other than the main thread or the web thread. UIKit should not be called from a secondary thread.

,536,913을
+0

주의 : 코드와 웹 서비스 API는 로그인 작업에 전혀 적절하지 않습니다. 1. 로그인 및 비밀번호를 리소스의 * 경로 * 요소로 만드는 것은 좋지 않습니다. URI 경로는 없습니다. https에서도 암호화되므로 항상 일반 텍스트로 보내십시오. 2. POST 요청이 필요할 것입니다. 3. 원격 리소스를로드하는 데'initWithContentsOfURL'을 사용하지 마십시오. 대리자 방식을 사용하는 NSURLConnection 또는 NSURLSession을 사용하십시오. – CouchDeveloper

답변

2

이것은 실제로 네트워크 코드와 전혀 관련이 없습니다. 문제는 백그라운드 스레드에서 UI를 업데이트하려고하는 것입니다 ... UIKit은 일반적으로 주 스레드에서 사용해야합니다. WebThreadLockFromAnyThread이 나타나는 이유는 일부 버전의 UIKit의 일부 컨트롤이 내부적으로 Webkit을 사용하여 자신을 그려서 잠금 장치의 이름을 지정하기 때문입니다.

URL 로딩에서 UI 업데이트를 분리하려면 (실제로 KVO 또는 알림을 사용하여 업데이트를 처리하기 위해) 코드를 리팩토링해야합니다. UIKit을 호출하는 모든 컨텍스트를 래핑하여 현재 코드가 작동하도록 할 수는 있지만 실제로는 아래 코드를 컴파일하려고하지는 않았지만 작동해야합니다.

-(void)LogInMethod{ 
    __block NSString * password; 
    __block NSString * mobileNumber; 

    dispatch_sync(dispatch_get_main_queue(), ^{ 
     password=passwordTextField.text; 
     mobileNumber =MobileTextField.text; 
    } 

    if (password.length==0 || mobileNumber.length==0) { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      if (mobileNumber.length==0) { 
       [wrongNoteLable setText:@"please enter a valid mobile number"]; 
       [wrongNoteLable setHidden:NO]; 
      } 
      else if (password.length==0){ 
       [wrongNoteLable setText:@"please enter a valid password"]; 
       [wrongNoteLable setHidden:NO]; 
      } 
     }); 
    } 
    else{ 

     NSString*UrlString=[[NSString alloc]initWithFormat:@"http://192.168.1.1:8080/test2/eattel/customers/signin/%@/123/%@",mobileNumber,password]; 
     NSURL *url = [[NSURL alloc] initWithString:UrlString ]; 
     NSError *error = nil; 
     NSStringEncoding encoding = 0; 
     customerID =[[NSString alloc]initWithContentsOfURL:url encoding:encoding error:&error]; 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      if (customerID) { 
       if (![customerID isEqualToString: @"-1"]) { 
        [self performSegueWithIdentifier:@"toMainMenuViewController" sender:self]; 
        NSLog(@"customer loged in with ID :%@",customerID); 
       } 
       else if ([customerID isEqualToString:@"-1"]){ 
        [wrongNoteLable setText:@"neither mobile number or password is wrong"]; 
        [wrongNoteLable setHidden:NO]; 
        NSLog(@"customer tried to log in with wrong password or phone Number :%@",customerID); 
       } 
      } 
      else{ 
       [wrongNoteLable setText:@"no connection to the server"]; 
       [wrongNoteLable setHidden:NO]; 
       NSLog(@"customer tried to log in but there is no server connection :%@",customerID); 
      } 
     }); 
    } 

    // NSLog([dispatch_get_main_queue() description]) 

} 



    //Update UI control. 
}); 
+0

대단히 잘되어 주셔서 감사합니다. 하지만 더 복잡한보기로 더 많은 문제가 발생할 것 같습니다. @Louis Gerbarg – Ammar

+1

솔직히이 코드는 UIKit 메서드를 주 스레드로 디스패치하는 방법을 설명하기에 적합하지 않습니다. 덜 유해한 표본을 사용하여 OP 코드와 전혀 관련이없는 것으로 제안 할 것입니다. – CouchDeveloper

+0

내가 코멘트에서 말했듯이, 그는 정말로 자신의 코드를 완전히 리팩터링해야합니다. 그리고 이것은 그가 정말로 원한다면 어떻게 코드를 작동시킬 수 있는지 보여줍니다. OPs 코멘트에 따르면, 그는 이것이 유지 보수 할 수 없다는 것을 이해합니다. 개인적으로 저는 UIKit을 백그라운드 스레드로 파견해야 할 필요가있는 방식으로 아키텍쳐를 작성하지 않을 것입니다. 포 그라운드에서 모든 UI 업데이트를 포 그라운드에서 백그라운드로 전달할 것입니다. –

관련 문제