服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - iOS多线程应用开发中自定义NSOperation类的实例解析

iOS多线程应用开发中自定义NSOperation类的实例解析

2021-01-03 16:31文顶顶 IOS

这篇文章主要介绍了iOS多线程应用开发中自定义NSOperation类的实例解析,代码基于传统的Objective-C,需要的朋友可以参考下

一、实现一个简单的tableview显示效果

实现效果展示:

iOS多线程应用开发中自定义NSOperation类的实例解析

代码示例(使用以前在主控制器中进行业务处理的方式)

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中得界面,如下:

 

iOS多线程应用开发中自定义NSOperation类的实例解析

3.根据plist文件,字典转模型

iOS多线程应用开发中自定义NSOperation类的实例解析

新建一个类,继承自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


打印查看:

 

iOS多线程应用开发中自定义NSOperation类的实例解析

二、自定义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


打印查看:

 

iOS多线程应用开发中自定义NSOperation类的实例解析

延伸 · 阅读

精彩推荐
  • IOSiOS APP实现微信H5支付示例总结

    iOS APP实现微信H5支付示例总结

    这篇文章主要介绍了iOS APP实现微信H5支付示例总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下...

    一张小A11332021-06-01
  • IOSiOS中时间与时间戳的相互转化实例代码

    iOS中时间与时间戳的相互转化实例代码

    这篇文章主要介绍了iOS中时间与时间戳的相互转化实例代码,非常具有实用价值,需要的朋友可以参考下。...

    张无忌!4812021-03-09
  • IOS谈一谈iOS单例模式

    谈一谈iOS单例模式

    这篇文章主要和大家谈一谈iOS中的单例模式,单例模式是一种常用的软件设计模式,想要深入了解iOS单例模式的朋友可以参考一下...

    彭盛凇11872021-01-19
  • IOSiOS逆向教程之logify跟踪方法的调用

    iOS逆向教程之logify跟踪方法的调用

    这篇文章主要给大家介绍了关于iOS逆向教程之logify跟踪方法调用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学...

    Mr.Guo11472021-04-28
  • IOSiOS常见的几个修饰词深入讲解

    iOS常见的几个修饰词深入讲解

    这篇文章主要给大家介绍了关于iOS常见的几个修饰词的相关资料,iOS修饰词包括assign、weak、strong、retain、copy、nonatomic、atomic、readonly、readwrite,文中通过示...

    郡王丶千夜7422021-05-10
  • IOSxcode8提交ipa失败无法构建版本问题的解决方案

    xcode8提交ipa失败无法构建版本问题的解决方案

    xcode升级到xcode8后发现构建不了新的版本。怎么解决呢?下面小编给大家带来了xcode8提交ipa失败无法构建版本问题的解决方案,非常不错,一起看看吧...

    Cinna丶7542021-02-03
  • IOSIOS网络请求之AFNetWorking 3.x 使用详情

    IOS网络请求之AFNetWorking 3.x 使用详情

    本篇文章主要介绍了IOS网络请求之AFNetWorking 3.x 使用详情,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    总李写代码6892021-03-04
  • IOSiOS10 Xcode8适配7个常见问题汇总

    iOS10 Xcode8适配7个常见问题汇总

    这篇文章主要为大家详细汇总了iOS10 Xcode8适配7个常见问题,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    索马里猫10332021-02-01