[IOS多線程]的使用:防止進行HTTP數據請求時,UI卡死


原文 http://www.cnblogs.com/rayshen/p/3822960.html

一、非多線程HTTP請求
如果不使用多線程,IOS的HTTP訪問請求,以登錄的模式為例,是這樣:
//此為不正確的代碼
//成功進行登錄驗證后進入到下一ViewController
-(void)presentToNextview{
  //到下一界面
}

//登錄驗證
-(void)loginCheck{
  //包含POST或GET請求來完成數據的驗證,驗證成功就跳轉到下一界面
}

-(void)showindicator{
  //顯示登錄時轉圈圈的菊花
}

//登錄按鈕的點擊事件
-(IBAction)loginBTN:(id)sender{
  //執行的函數有:
  [self showindicator];
  [self loginCheck];
}
這樣寫代碼的結果就是indicator菊花一到logincheck函數執行就會卡主,直到POST或GET請求完成才“卡到下一界面”。

網絡不好的情況下就是類似死機狀態。

二、多線程的實現。

1.子線程的創建:兩種方法

第一種: [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL];

第二種:NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downloadImage:) object:kURL];

[thread start];

差異:第一種直接方便,第二種在啟動前可以對其的stack等參數配置,更具靈活性。

2.在子線程中召喚主線程做事:

[self performSelectorOnMainThread:@selector(函數名) withObject:nil waitUntilDone:YES];

//如果waitUntilDone參數為YES,那么當前線程會被阻攔,直到selector運行完。

3.代碼簡單示例一:登錄
//此為多線程實現登錄放UI卡死的代碼
//成功進行登錄驗證后進入到下一ViewController
-(void)presentToNextview{
  //到下一界面
}

//登錄驗證
-(void)loginCheck{
  //包含POST或GET請求來完成數據的驗證,驗證成功就跳轉到下一界面
   if(賬號密碼匹配){
    //召喚主線程跳轉到下一界面
    [self performSelectorOnMainThread:@selector(presentToNextview) withObject:nil waitUntilDone:YES];
   }
}

-(void)showindicator{
  //顯示登錄時轉圈圈的菊花
}

//登錄按鈕的點擊事件
-(IBAction)loginBTN:(id)sender{
  //執行的函數有:
  [self showindicator];

  //開辟新的線程,執行需要聯網耗時的函數loginCheck
  [NSThread detachNewThreadSelector:@selector(loginCheck) toTarget:self withObject:nil];
}
4.代碼示例二:顯示一張網上的圖片,源代碼:

DownloadViewController.h
#import <UIKit/UIKit.h>
#import "FileConnection.h"
@interface DownloadViewController : UIViewController
@end
DownloadViewController.m
#import "DownloadViewController.h"
#define kURL @"http://b.hiphotos.baidu.com/image/pic/item/32fa828ba61ea8d37ccb6e0e950a304e241f58ca.jpg"
@interface DownloadViewController ()

@property UIImageView *imageView;

@end

UIActivityIndicatorView* activityIndicatorView;

@implementation DownloadViewController

-(void)downloadImage:(NSString *) url{
  NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
  UIImage *image = [[UIImage alloc]initWithData:data];
  if(image == nil){
    NSLog(@"沒有圖片");
  }else{
    NSLog(@"刷新圖片");
    [  activityIndicatorView stopAnimating ];//停止
    //通知主線程做事
    [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:NO];
    //如果waitUntilDone參數為YES,那么當前線程會被阻攔,直到selector運行完。
  }
}

-(void)updateUI:(UIImage*) image{
  self.imageView.image = image;
  //sleep(5);
}


-(void)showindicatior{
  activityIndicatorView = [ [ UIActivityIndicatorView  alloc ] initWithFrame:CGRectMake(250,30,30.0,30.0)];
  activityIndicatorView.activityIndicatorViewStyle= UIActivityIndicatorViewStyleGray;
  [self.view addSubview:activityIndicatorView];
  [activityIndicatorView startAnimating];//啟動

}
- (void)viewDidLoad
{
  [super viewDidLoad];

  self.imageView=[[UIImageView alloc] initWithFrame:CGRectMake(10, 60, 300, 220)];
 
  [self.view addSubview:self.imageView];
 
  //顯示菊花
  [self showindicatior];
 
  //開辟一個新的線程 2種方法
  [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL];
  //NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downloadImage:) object:kURL];
  //[thread start];
}

- (void)didReceiveMemoryWarning
{
  [super didReceiveMemoryWarning];
  // Dispose of any resources that can be recreated.
}

@end


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM