你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> ios多線程操作(三)—— 線程通訊

ios多線程操作(三)—— 線程通訊

編輯:IOS開發綜合
一個進程中,線程並非單獨存在,往往需要與其他線程進行通訊以執行特定的任務。接下來就用一個簡單的例子來實現線程之間最簡單的通訊,並借此探究一下UI控件下得常見設置 需求:從網絡上下載一張圖片在屏幕上顯示,圖片可以滾動,可以捏合縮放大小 項目開搞 新建一個新項目。 因為視圖有滾動的需求,所以需要添加一個UIScrollView以及一個顯示圖片的UIImageView
@interface ViewController () 
@property (nonatomic,strong) UIScrollView *scrollView;
@property (weak,nonatomic) UIImageView *imgV;
@end

在loadView方法裡面初始化UI控件,將scrollView設為根視圖
- (void)loadView
{
    _scrollView = [[UIScrollView alloc] init];
    self.view = _scrollView;
    self.view.backgroundColor = [UIColor brownColor];
    // 初始化UIImageView
    UIImageView *imgV = [[UIImageView alloc] init];
    [self.view addSubview:imgV];
    self.imgV = imgV;
}

設置scrollView的代理,圖片的縮放操作將由代理的方法來實現,在後台開啟一條線程執行下載圖片的耗時操作:
- (void)viewDidLoad {
    [super viewDidLoad];

    _scrollView.delegate = self;
    // 最小縮放比例
    _scrollView.minimumZoomScale = 0.5;
    // 最大縮放比例
    _scrollView.maximumZoomScale = 2.0;
    // 在後台開啟一條線程執行下載圖片的耗時操作
    [self performSelectorInBackground:@selector(downloadImage) withObject:nil];
    // 打印所在線程
    NSLog(@"viewDidLoad - %@",[NSThread currentThread]);
}

將下載圖片抽取為一個方法downloadImage,該方法中實現了線程間的通信 ———— 讓主線程更新UI,通知主線程區執行setImage:方法,通訊對象是從網絡上下載的image圖片對象
- (void)downloadImage
{

    NSURL *url = [NSURL URLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/4afbfbedab64034f06bd8359acc379310a551d78.jpg"];

    NSData *data = [NSData dataWithContentsOfURL:url];

    UIImage *image = [UIImage imageWithData:data];
    // 更新UI都要在主線程執行
    [self performSelectorOnMainThread:@selector(setImg:) withObject:image waitUntilDone:NO];
    NSLog(@"downloadImage - %@",[NSThread currentThread]);
}

在setImg:方法裡面讓圖片顯示
- (void)setImg:(UIImage *)img
{
    self.imgV.image = img;
    // 設置UIImageView根據image自動調節frame的大小
    [self.imgV sizeToFit];
    // 設置scrollView滾動范圍
    self.scrollView.contentSize = img.size;
    NSLog(@"setImg - %@",[NSThread currentThread]);

}

代理方法:
/**
 *  該方法返回需要縮放的view
 */
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return self.imgV;
}


如此這般就簡單實現了線程間的通訊,程序會從網絡上下載圖片顯示,控制台打印的結果如下
\
number = 1 代表在主線程上執行。 number = 2(只要number!=1)代表在子線程上執行。
耗時操作在後台子線程執行,更新UI在主線程執行。 為何在後台子線程執行,如果在主線程執行耗時操作,那麼該操作執行期間,主線程一直被占用,用戶的操作就無法響應,這樣的後果可想而知。 為什麼更新UI要在主線程執行?在子線程中是不能進行UI 更新的,而可以更新的結果只是一個幻像:因為子線程代碼執行完畢了,又自動進入到了主線程,執行了子線程中的UI更新的函數棧,這中間的時間非常的短,就讓大家誤以為分線程可以更新UI。如果子線程一直在運行,則子線程中的UI更新的函數棧 主線程無法獲知,即無法更新。只有極少數的UI能更新,因為開辟線程時會獲取當前環境,如點擊某個按鈕,這個按鈕響應的方法是開辟一個子線程,在子線程中對該按鈕進行UI 更新是能及時的,如換標題,換背景圖,但這沒有任何意義。












  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved