iOS开发的时候,经常会用到延时执行,比如:
[self performSelector:@selector(initContentView) withObject:nil afterDelay:2];
在这里会延时2秒执行initContentView方法。
有时候,需要取消延时操作。尤其当这个延时比较长的时候。比如:
- 延时10秒显示一个动画,可未到10秒,用户操作退出了当前的视图
- 演示10秒隐藏当前的工具条菜单,在此期间,又对菜单做了操作,也许只是touch了菜单区域
上述情况,都需要取消延时调用,后一种情况,还需要启动新的延时调用。
解决办法很简单:
[NSObject cancelPreviousPerformRequestsWithTarget:self]
这样就取消了self对象所有的延时操作。
在使用NSOperationQueue简化多线程开发中介绍了iOS的操作队列使用方法。这里补充一下队列的优先级功能。
假设现在队列中有多个操作(NSOperation),现在再向队列中加入新的操作,并且希望新增加的操作排在未执行操作的最前面。这时就需要设置操作的优先级了。
编写了个最简单的NSOperation,头文件:
#import <Foundation/Foundation.h>
@interface MyOperation : NSOperation{
NSString *name;
}@property (nonatomic,retain) NSString *name;
@end
以下内容翻译自:
CocoaAsyncSocket支持tcp和udp。其中:
- AsyncSocket类是支持TCP的
- AsyncUdpSocket是支持UDP的
AsyncSocket是封装了CFSocket和CFSteam的TCP/IP socket网络库。它提供了异步操作,本地cocoa类的基于delegate的完整支持。主要有以下特性:
- 队列的非阻塞的读和写,而且可选超时。你可以调用它读取和写入,它会当完成后告知你
- 自动的socket接收。如果你调用它接收连接,它将为每个连接启动新的实例,当然,也可以立即关闭这些连接
- 委托(delegate)支持。错误、连接、接收、完整的读取、完整的写入、进度以及断开连接,都可以通过委托模式调用
- 基于run loop的,而不是线程的。虽然可以在主线程或者工作线程中使用它,但你不需要这样做。它异步的调用委托方法,使用NSRunLoop。委托方法包括socket的参数,可让你在多个实例中区分
- 自包含在一个类中。你无需操作流或者socket,这个类帮你做了全部
- 支持基于IPV4和IPV6的TCP流
AsyncUdpSocket是UDP/IP socket网络库,包装自CFSocket。它的工作很像TCP版本,只不过是用于处理UDP的。它包括基于非阻塞队列的发送接收操作,完整的委托支持,基于runloop,自包含的类,以及支持IPV4和IPV6。
使用Grails和Groovy,实现了这样的需求:
- zip文件上传
- zip文件上传后,在zip文件中加入自定义文本文件
在Grails实现复杂的数据录入上实现的本示例。示例如图:
准备工作:文件上传
首先说一下文件上传,在Grails中,借助Spring MVC的底层支持,实现还是很容易的。
视图:
<body>
<div style="margin-left: 15px;">
<g:message code="${flash.message}" />
<g:form action="uploadFile" method="post" enctype="multipart/form-data">
<input type="file" name="myFile" />
<input type="submit" value="上传" />
<input type="hidden" name="id" value="1"/>
</g:form>
</div>
</body>
在这里hidden了一个参数,是用于服务器端使用的。
多线程开发是一件需要特别精心的事情,即使是对有多年开发经验的工程师来说。
为了能让初级开发工程师也能使用多线程,同时还要简化复杂性。各种编程工具提供了各自的办法。对于iOS来说,建议在尽可能的情况下避免直接操作线程,使用比如NSOperationQueue这样的机制。
可以把NSOperationQueue看作一个线程池,可往线程池中添加操作(NSOperation)到队列中。线程池中的线程可看作消费者,从队列中取走操作,并执行它。
你可以设置线程池中只有一个线程,这样,各个操作就可以认为是近似的顺序执行了。为什么说是近似呢,后面会做解释。
编写最简单的示例
先写个最简单的示例。
日志引用
在Grails实现复杂的数据录入示例中,如果删除一个图书对象,而这个对象是另一个或多个对象的相关图书。这时就会报错。
当然,我们可以根据这个异常来提示客户,不能删除,虽然这不是个好方法。但是客户需要知道它到底被哪几个对象关联了。
可以使用hql的join子句实现这样的功能。
这里再把Book实体代码列出来:
class Book {
static mapping = {
//id generator:’uuid.hex’, params:[separator:'-']
//relativeBooks cascade:"delete"
}
static hasMany=[relativeBooks:Book]
//String id
String name
List<Book> relativeBooks=[]
}
ASIHTTPRequest可以实现断点续传。网上有一些介绍类似使用:
[request setAllowResumeForFileDownloads:YES];
方法的。但是它不是真正意义的断点续传。它只能让应用在下载过程中,暂停和继续。如果退出应用再进入是无效的。
不过,通过ASIHTTPRequest的异步请求以及delegate还是可以实现断点续传的。
本文还是以Grails编写断点续传服务器端为例。
异步请求的代码:
如果要在ios中实现类似最简单的HttpClient应用的功能,可以直接用Cocoa的CFNetwork framework,但是,因为它是将C语言编写的BSD网络库做的封装,因此使用起来很繁琐。
ASIHTTPRequest是第三方HTTP编程的ObjC库。基于CFNetwork framework。网址在这里:
要使用该库,首先是下载部署。下载zip包解压缩即可。部署可见官方文档:
这里也说一下,首先该库还依赖其他框架和库:
一般来说,是增加画红线的几个框架。