原文 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