最近做的iPhone项目中有一如下功能:

app在用户许可后将本地Photos的照片上传到服务器,期间用户可以做其他任何操作,等上传成功后弹出一个toast通知用户。

原先的代码结构是:

  1. 获取照片的操作放在NSOperation的子类A中
  2. 获取完照片后,逐个生成一个上传类B(此上传类是ASIFormDataRequest的子类),并把它添加到NSOperationQueue中。

其中operationqueue设置了最大运行数是1,但是实际测试下来发现所有的上传都是并发的,一查代码,发现上传类B居然没有实现main,就一个init函数。初始化完之后直接startAsynchronous了,然后返回self。真是奇葩~~

于是将上传类B修改,添加了main函数,但是运行的时候出错:

- (void)reportFinished
{
if (delegate && [delegate respondsToSelector:didFinishSelector]) {
[delegate performSelector:didFinishSelector withObject:self];
}---------------------->提示bad_access的错误 #if NS_BLOCKS_AVAILABLE
if(completionBlock){
completionBlock();
}
#endif if (queue && [queue respondsToSelector:@selector(requestFinished:)]) {
[queue performSelector:@selector(requestFinished:) withObject:self];
}
}

查看delegate的值,发现已经overrelease了。B在设置的时候,将delegate设置为A的实例了,A的实例怎么会不等B的返回就结束了呢?

原来A本身是一个operation,假设运行在次线程 M中。B因为是继承ASIFormDataRequest,其实也是一个NSOperation,也就是说B运行的时候也是运行在次线程N中的。因为B使用的是异步运行,N必然不同于M。而A在将上传操作结束完以后,就结束了,系统就会回收A的内存。这个时候在N中运行的B尚未收到响应。等到response返回的时候,A早就已经释放了,所以就会有如上的错误。

怎么解决呢?有同事是把A设置为property。这样可以解决,但是当需要调用A的类很多的时候,就会比较麻烦。

其实解决的办法很简单,就是在A中重载isFinished方法,当确定所有的照片上传上去后返回YES否则返回NO,这样我们就可以控制A,避免系统“过早”的释放。

与此同时我们发现,ASIHttpRequest的delegate响应都会路由到主线程:

- (void)requestFinished
{
#if DEBUG_REQUEST_STATUS || DEBUG_THROTTLING
NSLog(@"[STATUS] Request finished: %@",self);
#endif
if ([self error] || [self mainRequest]) {
return;
}
if ([self isPACFileRequest]) {
[self reportFinished];
} else {
[self performSelectorOnMainThread:@selector(reportFinished) withObject:nil waitUntilDone:[NSThread isMainThread]];
}
}

stackoverflow上有关于这样做的讨论,这里要说明的是因为B是运行在后台,delegate是A,不需要在主线程响应。我们可以在B中重载上述函数,将performSelectorOnMainThread:函数去掉,直接调用reportFinished。

进一步考虑,iOS上获取本地照片现在一般用ALAssetsLibrary,这个库一般是用block去枚举,换言之获得照片内容的操作已经是在次线程中操作的了。

这样一来A也就可以不需要是NSOperation,是个一般的NSObject即可。

最近项目添加了很多“奇葩”的功能,可是参与的决定权不在自己这边,虽然我列出了很多不应该这样做的理由和依据。但是需求人员都以本国的用户需求为借口——看来公司越来越成为外资公司在华的外包公司了。这个职位也变得越来越乏味,虽然不见得能马上跳槽,但是也学会了在“逆境”中坚强:学习产品的设计,和非开发人员的沟通,重构代码。觉得有句话说的真好:要想做自己想做的事,就得先做自己不想做的事。

与诸君共勉!

多线程-NSOperation中使用ASIHttpRequest注意事项的更多相关文章

  1. C++ 关于MFC多线程编程中的一些注意事项 及自定义消息的处理

    在多线程编程中,最简单的方法,无非就是利用 AfxBeginThread  来创建一个工作线程,看一下这个函数的说明: CWinThread* AFXAPI AfxBeginThread( AFX_T ...

  2. iPhone SDK中多线程的使用方法以及注意事项

    多线程iphonethreadapplication编程嵌入式 然现在大部分PC应用程序都支持多线程/多任务的开发方式,但是在iPhone上,Apple并不推荐使用多线程的编程方式.但是多线程编程毕竟 ...

  3. iOS多线程 NSOperation的用法

    上一篇写了 GCD 的使用,接下来就了解一下 NSOperation ,NSOperation是苹果对 GCD 的 OC 版的一个封装,但是相对于GCD来说可控性更强,并且可以加入操作依赖. NSOp ...

  4. Linux 多线程应用中如何编写安全的信号处理函数

    http://blog.163.com/he_junwei/blog/static/1979376462014021105242552/ http://www.ibm.com/developerwor ...

  5. iOS之多线程NSOperation

    目前在 iOS 和 OS X 中有两套先进的同步 API 可供我们使用:NSOperation 和 GCD .其中 GCD 是基于 C 的底层的 API ,而 NSOperation 则是 GCD 实 ...

  6. iOS 多线程 NSOperation、NSOperationQueue

    1. NSOperation.NSOperationQueue 简介 NSOperation.NSOperationQueue 是苹果提供给我们的一套多线程解决方案.实际上 NSOperation.N ...

  7. iOS 开发多线程 —— NSOperation

    本文是根据文顶顶老师的博客学习而来,转载地址:http://www.cnblogs.com/wendingding/p/3809042.html 一.NSOperation简介 1.简单说明 NSOp ...

  8. iOS多线程---NSOperation介绍和使用

    1.  NSOperation实现多线程编程,需要和NSOperationQueue一起使用. (1)先将要执行的操作封装到NSOperation中 (2)将NSOperation对象添加到NSOpe ...

  9. 四:多线程--NSOperation简单介绍

    一.NSOperation简介 1.NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQu ...

随机推荐

  1. jquery select处理

    JQuery 绑定select标签的onchange事件,弹出选择的值,并实现跳转.传参 js 处理 select :选中,删除,更改等 http://blog.csdn.net/wust_star/ ...

  2. JMeter性能测试介绍学习一

    上一节中,我们了解了jmeter的一此主要元件,那么这些元件如何使用到性能测试中呢.这一节创建一个简单的测试计划来使用这些元件.该计划对应的测试需求. 1)测试目标网站是fnng.cnblogs.co ...

  3. C# 调用Windows API实现两个进程间的通信

    使用Windows API实现两个进程间(含窗体)的通信http://blog.csdn.net/huangxinfeng/article/details/5513608 从C#下使用WM_COPYD ...

  4. node入门开发遇到的问题

    最近在看node入门这本书,https://cnodejs.org/getstart 里面是跟随作者完成一个小的demo,书中不免会有遗漏的,下面是我在实现里面最后一个例子时遇到的问题,希望能够帮助其 ...

  5. ngrok本地反向代理

    ngrok本地反向代理 ngrok本地反向代理 使用ngrok可以把内网服务映射到外网 国内ngrok服务配置如下 在ngrok.exe所在的目录下添加ngrok.cfg文件 ngrok.cfg文件内 ...

  6. div滚动条

    给DIV限定宽度或高度,并指定overflow样式为auto,这样当内空超出后就会自动出现滚动条了.如<div style="width:100px; height:100px; ov ...

  7. VS2012如何更新下载TFS上面的代码到本地

    现在的代码基本上全都放在TFS上面,如何同步TFS上面的code呢? 1. Open "Team Explorer - Home" 2. Click "Source Co ...

  8. spring定时器,5步完成

    spring定时器,5步完成,我们开发的时候会用定时执行任务. 用spring框架时,可以直接使用spring定时功能 1.创建任务调度类,里面一个方法,方法名为work 2. spring配置文件, ...

  9. yii2 增加新的目录结构

    搭建新的目录结构详细点击这里 搭建Restful API 点击这里 1.开发环境操作系统        Windows Server 2012 R2 DatacenterPHP架构        Ap ...

  10. 267. Palindrome Permutation II

    题目: Given a string s, return all the palindromic permutations (without duplicates) of it. Return an ...