亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

iOS多線程應用開發中自定義NSOperation類的實例解析

2020-07-26 03:30:23
字體:
來源:轉載
供稿:網友

一、實現一個簡單的tableView顯示效果

實現效果展示:

20161393952592.png (348×532)

代碼示例(使用以前在主控制器中進行業務處理的方式)

1.新建一個項目,讓控制器繼承自UITableViewController。

復制代碼 代碼如下:

//
//  YYViewController.h
//  01-自定義Operation
//
//  Created by apple on 14-6-26.
//  Copyright (c) 2014年 itcase. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface YYViewController : UITableViewController

@end


2.處理storyboard中得界面,如下:

20161394021020.png (718×367)

3.根據plist文件,字典轉模型

20161394039602.png (714×372)

新建一個類,繼承自NSObject,作為數據的模型

YYappModel.h文件

復制代碼 代碼如下:

//
//  YYappModel.h
//  01-自定義Operation
//
//  Created by apple on 14-6-26.
//  Copyright (c) 2014年 itcase. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface YYappModel : NSObject
/**
 *應用名稱
 */
@property(nonatomic,copy)NSString *name;
/**
 *  應用圖片
 */
@property(nonatomic,copy)NSString *icon;
/**
 *  應用的下載量
 */
@property(nonatomic,copy)NSString *download;

+(instancetype)appModelWithDict:(NSDictionary *)dict;
-(instancetype)initWithDict:(NSDictionary *)dict;
@end


YYappModel.m文件
復制代碼 代碼如下:

//
//  YYappModel.m
//  01-自定義Operation
//
//  Created by apple on 14-6-26.
//  Copyright (c) 2014年 itcase. All rights reserved.
//

#import "YYappModel.h"

@implementation YYappModel

-(instancetype)initWithDict:(NSDictionary *)dict
{
    if (self=[super init]) {
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}

//工廠方法
+(instancetype)appModelWithDict:(NSDictionary *)dict
{
    return [[self alloc]initWithDict:dict];
}
@end


主控制器中得邏輯控制部分,YYViewController.m文件
復制代碼 代碼如下:

//
//  YYViewController.m
//  01-自定義Operation
//
//  Created by apple on 14-6-26.
//  Copyright (c) 2014年 itcase. All rights reserved.
//

#import "YYViewController.h"
#import "YYappModel.h"

@interface YYViewController ()
@property(nonatomic,strong)NSArray *apps;

@end


復制代碼 代碼如下:

@implementation YYViewController
#pragma mark- 懶加載
-(NSArray *)apps
{
    if (_apps==nil) {
        NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil];
        NSArray *tempArray=[NSArray arrayWithContentsOfFile:path];
       
        //字典轉模型
        NSMutableArray *array=[NSMutableArray array];
        for (NSDictionary *dict in tempArray) {
            YYappModel *app=[YYappModel appModelWithDict:dict];
            [array addObject:app];
        }
        _apps=array;
    }
    return _apps;
}

#pragma mark-數據源方法
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.apps.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *ID=@"ID";
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];
    if (cell==nil) {
        cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    }
    YYappModel *app=self.apps[indexPath.row];
    cell.textLabel.text=app.name;
    cell.detailTextLabel.text=app.download;
   
    //下載圖片數據
    NSLog(@"加載圖片數據---%@", [NSThread currentThread]);
    NSURL *url=[NSURL URLWithString:app.icon];
    NSData *data=[NSData dataWithContentsOfURL:url];
    UIImage *imgae=[UIImage imageWithData:data];
    cell.imageView.image=imgae;
    NSLog(@"完成顯示");
    return cell;
}

@end


打印查看:

20161394102297.png (771×144)

二、自定義NSOperation

說明:上面的下載圖片數據部分是一個非常耗時的操作,這個操作任務在主線程完成,會嚴重的影響到用戶體驗,造成UI卡的現象。下面通過自定義NSOperation,新開線程,讓加載圖片的任務異步執行。

1.通過代理

在上面的基礎上,新建一個類,讓其繼承自NSOperation。

YYdownLoadOperation.h文件

復制代碼 代碼如下:

//
//  YYdownLoadOperation.h
//  01-自定義Operation
//
//  Created by apple on 14-6-26.
//  Copyright (c) 2014年 itcase. All rights reserved.
//

#import <Foundation/Foundation.h>

#pragma mark-設置代理和代理方法
@class YYdownLoadOperation;
@protocol YYdownLoadOperationDelegate <NSObject>
-(void)downLoadOperation:(YYdownLoadOperation*)operation didFishedDownLoad:(UIImage *)image;
@end


復制代碼 代碼如下:

@interface YYdownLoadOperation : NSOperation
@property(nonatomic,copy)NSString *url;
@property(nonatomic,strong)NSIndexPath *indexPath;
@property(nonatomic,strong)id <YYdownLoadOperationDelegate> delegate;
@end

YYdownLoadOperation.m文件
復制代碼 代碼如下:

//
//  YYdownLoadOperation.m
//  01-自定義Operation
//
//  Created by apple on 14-6-26.
//  Copyright (c) 2014年 itcase. All rights reserved.
//

#import "YYdownLoadOperation.h"

@implementation YYdownLoadOperation
-(void)main
{
    NSURL *url=[NSURL URLWithString:self.url];
    NSData *data=[NSData dataWithContentsOfURL:url];
    UIImage *imgae=[UIImage imageWithData:data];
   
    NSLog(@"--%@--",[NSThread currentThread]);
    //圖片下載完畢后,通知代理
    if ([self.delegate respondsToSelector:@selector(downLoadOperation:didFishedDownLoad:)]) {
        dispatch_async(dispatch_get_main_queue(), ^{//回到主線程,傳遞數據給代理對象
             [self.delegate downLoadOperation:self didFishedDownLoad:imgae];
        });
    }
}
@end


主控制器中的業務邏輯:
復制代碼 代碼如下:

//
//  YYViewController.m
//  01-自定義Operation
//
//  Created by apple on 14-6-26.
//  Copyright (c) 2014年 itcase. All rights reserved.
//

#import "YYViewController.h"
#import "YYappModel.h"
#import "YYdownLoadOperation.h"

@interface YYViewController ()<YYdownLoadOperationDelegate>
@property(nonatomic,strong)NSArray *apps;
@property(nonatomic,strong)NSOperationQueue *queue;

@end


復制代碼 代碼如下:

@implementation YYViewController
#pragma mark- 懶加載apps
-(NSArray *)apps
{
    if (_apps==nil) {
        NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil];
        NSArray *tempArray=[NSArray arrayWithContentsOfFile:path];
       
        //字典轉模型
        NSMutableArray *array=[NSMutableArray array];
        for (NSDictionary *dict in tempArray) {
            YYappModel *app=[YYappModel appModelWithDict:dict];
            [array addObject:app];
        }
        _apps=array;
    }
    return _apps;
}

#pragma mark-懶加載queue
-(NSOperationQueue *)queue
{
    if (_queue==Nil) {
        _queue=[[NSOperationQueue alloc]init];
        //設置最大并發數為3
        _queue.maxConcurrentOperationCount=3;
    }
    return _queue;
}

#pragma mark-數據源方法
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.apps.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *ID=@"ID";
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];
    if (cell==nil) {
        cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    }
    YYappModel *app=self.apps[indexPath.row];
    cell.textLabel.text=app.name;
    cell.detailTextLabel.text=app.download;
    
    //下載圖片數據
//    NSLog(@"加載圖片數據---%@", [NSThread currentThread]);
//    NSURL *url=[NSURL URLWithString:app.icon];
//    NSData *data=[NSData dataWithContentsOfURL:url];
//    UIImage *imgae=[UIImage imageWithData:data];
//    cell.imageView.image=imgae;
   
    //創建一個OPeration對象
    YYdownLoadOperation *operation=[[YYdownLoadOperation alloc]init];
    operation.url=app.icon;
    operation.indexPath=indexPath;
    operation.delegate=self;
   
    //把操作對象添加到隊列中在去
    [self.queue addOperation:operation];

//    NSLog(@"完成顯示");
    return cell;
}
-(void)downLoadOperation:(YYdownLoadOperation *)operation didFishedDownLoad:(UIImage *)image
{
    //返回圖片數據給每行對應的cell的imageview.image
    //取出tableview中indexPath這一行對應的cell
    UITableViewCell *cell=[self.tableView cellForRowAtIndexPath:operation.indexPath];
    //顯示圖片
    cell.imageView.image=image;
//    NSLog(@"cell--index--%@---%@",operation.indexPath,[NSThread currentThread]);
    //一定要刷新表格
    [self.tableView reloadData];
    NSLog(@"--%@--",[NSThread currentThread]);

}
@end


說明:通過打印可以發現上面的代碼存在很大的問題。

問題1:需要保證一個url對應一個operation對象。

問題2:下載完需要移除。移除執行完畢的操作。

問題3:保證一個url對應一個image。
下面對主控制器中得代碼進行改進:

復制代碼 代碼如下:

//
//  YYViewController.m
//  01-自定義Operation
//
//  Created by apple on 14-6-26.
//  Copyright (c) 2014年 itcase. All rights reserved.
//

#import "YYViewController.h"
#import "YYappModel.h"
#import "YYdownLoadOperation.h"

@interface YYViewController ()<YYdownLoadOperationDelegate>
@property(nonatomic,strong)NSArray *apps;
@property(nonatomic,strong)NSOperationQueue *queue;
@property(nonatomic,strong)NSMutableDictionary *operations;
@property(nonatomic,strong)NSMutableDictionary *images;

@end


復制代碼 代碼如下:

@implementation YYViewController
#pragma mark- 懶加載apps
-(NSArray *)apps
{
    if (_apps==nil) {
        NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil];
        NSArray *tempArray=[NSArray arrayWithContentsOfFile:path];
       
        //字典轉模型
        NSMutableArray *array=[NSMutableArray array];
        for (NSDictionary *dict in tempArray) {
            YYappModel *app=[YYappModel appModelWithDict:dict];
            [array addObject:app];
        }
        _apps=array;
    }
    return _apps;
}

#pragma mark-懶加載queue
-(NSOperationQueue *)queue
{
    if (_queue==Nil) {
        _queue=[[NSOperationQueue alloc]init];
        //設置最大并發數為3
        _queue.maxConcurrentOperationCount=3;
    }
    return _queue;
}

#pragma mark-懶加載operations
-(NSMutableDictionary *)operations
{
    if (_operations==Nil) {
        _operations=[NSMutableDictionary dictionary];
    }
    return _operations;
}

#pragma mark-懶加載images
-(NSMutableDictionary *)images
{
    if (_images==Nil) {
        _images=[NSMutableDictionary dictionary];
    }
    return _images;
}

#pragma mark-數據源方法
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.apps.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *ID=@"ID";
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];
    if (cell==nil) {
        cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    }
    YYappModel *app=self.apps[indexPath.row];
    cell.textLabel.text=app.name;
    cell.detailTextLabel.text=app.download;
   
    //保證一個url對應一個image對象
    UIImage *image=self.images[app.icon];
    if (image) {//緩存中有圖片
        cell.imageView.image=image;
    }else       //  緩存中沒有圖片,得下載
    {
        //先設置一張占位圖片
        cell.imageView.image=[UIImage imageNamed:@"57437179_42489b0"];
        YYdownLoadOperation *operation=self.operations[app.icon];
        if (operation) {//正在下載
            //什么都不做
        }else  //當前沒有下載,那就創建操作
        {
            operation=[[YYdownLoadOperation alloc]init];
            operation.url=app.icon;
            operation.indexPath=indexPath;
            operation.delegate=self;
            [self.queue addOperation:operation];//異步下載
            self.operations[app.icon]=operation;
        }
    }
   

    return cell;
}
-(void)downLoadOperation:(YYdownLoadOperation *)operation didFishedDownLoad:(UIImage *)image
{
    //1.移除執行完畢的操作
    [self.operations removeObjectForKey:operation.url];
   
    //2.將圖片放到緩存中
    self.images[operation.url]=image;

    //3.刷新表格(只刷新下載的那一行)
    
    [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    NSLog(@"--%d--%@--",operation.indexPath.row,[NSThread currentThread]);

}
@end


打印查看:

20161394130477.png (849×396)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品久久久久福利| 亚洲人成在线观看网站高清| 亚洲男人天堂2019| 69av成年福利视频| 国产精品久久久av久久久| 亚洲欧美中文字幕在线一区| 久久精品视频在线观看| 亚洲www视频| 国产一区视频在线播放| 精品久久久久久中文字幕| 国产小视频91| 国产精品扒开腿做爽爽爽的视频| 国产精品女人久久久久久| 国产精品电影一区| 日韩欧美亚洲一二三区| 亚洲精品美女网站| 欧美午夜丰满在线18影院| 成人黄色在线观看| 久久五月情影视| 亚洲精品xxx| 大量国产精品视频| 欧美成人精品在线观看| 欧美成人免费网| 亚洲国产日韩一区| 亚洲欧美日本精品| 久久人人爽亚洲精品天堂| 精品亚洲一区二区三区四区五区| 亚洲最新av在线| 日韩电影中文字幕在线| 精品久久久国产| 国产精品久久久亚洲| 亚洲欧美国产精品| 国产精品男女猛烈高潮激情| 亚洲最新在线视频| 亚洲а∨天堂久久精品喷水| 国产一区二区三区高清在线观看| www.欧美精品一二三区| 日本高清+成人网在线观看| 一本一道久久a久久精品逆3p| 国产+成+人+亚洲欧洲| 欧洲成人在线视频| 亚洲欧美另类人妖| 亚洲石原莉奈一区二区在线观看| 久久久精品久久久久| 欧美日韩一区二区在线播放| 欧美性xxxx18| 亚洲欧美成人精品| 欧美日韩一区二区免费在线观看| 欧美丰满片xxx777| 欧美激情亚洲另类| 精品国产一区二区三区久久久狼| 日韩中文字幕不卡视频| 97国产精品视频人人做人人爱| 高跟丝袜一区二区三区| 黑人狂躁日本妞一区二区三区| 91九色单男在线观看| 欧美最猛性xxxxx免费| 欧美激情精品久久久久| 欧美综合在线第二页| 亚洲欧洲午夜一线一品| 日韩在线视频线视频免费网站| 亚洲精品国产精品自产a区红杏吧| 久久精品国亚洲| 日韩欧美精品免费在线| 88国产精品欧美一区二区三区| 成人免费视频xnxx.com| 国产亚洲激情视频在线| 国产精品999999| 最近2019年手机中文字幕| 欧美日韩国产成人在线观看| 亚洲娇小xxxx欧美娇小| 欧美插天视频在线播放| 高清亚洲成在人网站天堂| 亚洲激情视频网站| 日本精品免费一区二区三区| 亚洲自拍欧美另类| 久久精品成人欧美大片古装| 午夜精品福利在线观看| 欧美日韩精品中文字幕| 九九九热精品免费视频观看网站| 日本不卡免费高清视频| 日韩电影中文字幕av| 国产精品激情自拍| 欧美极品xxxx| 久久精品国产亚洲一区二区| 亚洲精品久久7777777| 91tv亚洲精品香蕉国产一区7ujn| 日韩成人在线视频观看| 亚洲xxxx视频| 亚洲欧美日韩中文在线制服| 国产999精品久久久影片官网| 国产999在线观看| 亚洲sss综合天堂久久| 国产日韩欧美在线播放| 精品色蜜蜜精品视频在线观看| 亚洲视频在线观看视频| 久久精品电影一区二区| 国产精品一区电影| www.久久久久| 91av国产在线| 久久99热精品| 国产精品美女呻吟| 国产欧美在线播放| 色婷婷综合久久久久| 97国产一区二区精品久久呦| 97精品国产aⅴ7777| 国产精品免费一区二区三区都可以| 国产69久久精品成人| 欧美不卡视频一区发布| 中文日韩在线观看| 成人啪啪免费看| 国产精品高潮呻吟久久av野狼| 亚洲大胆人体在线| 国产亚洲精品日韩| 欧美视频专区一二在线观看| 国产精品久久久久久搜索| 亚洲精品自拍视频| 国产精品中文久久久久久久| 欧美精品videosex牲欧美| 成人免费看片视频| 中文字幕一区日韩电影| 国产精品久久久久久av福利软件| 亚洲欧美三级在线| 国产精品福利无圣光在线一区| 亚洲国产精品久久久久秋霞不卡| 亚洲欧美国产高清va在线播| 日韩高清av一区二区三区| 国产精品视频自拍| 日韩电影免费在线观看| 久久久免费观看视频| 性色av一区二区三区在线观看| 亚洲无av在线中文字幕| 亚洲电影免费观看高清完整版在线观看| 国产丝袜一区二区三区免费视频| 国产精品久久综合av爱欲tv| 亚洲人午夜精品免费| 久久91超碰青草是什么| 中文字幕无线精品亚洲乱码一区| 永久免费毛片在线播放不卡| 精品国产成人av| 91精品国产高清久久久久久久久| 国产精品爽爽爽爽爽爽在线观看| 国产精品嫩草影院久久久| 色噜噜亚洲精品中文字幕| 日韩综合视频在线观看| 欧美在线视频观看免费网站| 伦伦影院午夜日韩欧美限制| 国产精品视频色| 国产精品扒开腿爽爽爽视频| 欧美在线国产精品| zzijzzij亚洲日本成熟少妇| 久久青草精品视频免费观看| 日韩精品亚洲元码| 久久久久久一区二区三区| 国产乱肥老妇国产一区二| 国产视频在线观看一区二区| 性金发美女69hd大尺寸| 亚洲国产天堂久久综合| 久久精品夜夜夜夜夜久久| 亚洲国产精品久久久久秋霞蜜臀| 久久国产加勒比精品无码| 日韩精品中文字幕有码专区| 亚洲黄色有码视频| 一区二区三区动漫|