2013-12-08 19 views
0

在我的應用程序中我使用的是web服務(restful webservice),任何使用一個服務登錄操作的身份驗證用戶的方式,我有一個IBAction的UIButton將調用Web服務,這裏是調用此Web服務的方法:使用多線程登錄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.

+0

注意:您的代碼和Web服務API對於登錄任務來說並不合適:1.將登錄名和密碼設置爲資源的* path *元素不是一個好主意:URI路徑aren即使在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方法派發到主線程。我建議,使用危害較小的樣本,可能完全與OPs代碼無關。 – CouchDeveloper

+0

就像我在評論中所說的那樣,他真的應該完全重構他的代碼,這只是向他展示瞭如果他真的想要如何讓他的代碼工作。基於OP的評論,似乎他明白這是不可維護的。就我個人而言,我不會以這樣的方式構建它,以至於他需要爲後臺線程分派UIKit,我將通過前臺通知所有UI更新,併發布從後臺到前臺的通知。 –