- 浏览: 192828 次
- 性别:
- 来自: 无锡
文章分类
最新评论
-
luoqianjiang:
很好,谢谢
一些iOS高效开源类库 -
sgjsdf5944:
没看明白。。。。。。。。。。
UIWebView打开doc、pdf文件 -
593864589:
mac 上不支持呢?
cocos2d 粒子设计器 -
寻墨小楼:
多谢了...正在弄这个。
mysql for mac 安装和基本操作 -
yueliancao:
楼主如何联系啊 我的MAC系统 #LoadModule php ...
mac OS x中配置apache + php + mysql
这涉及到 3 方面的关键知识:
¥ ASIHTTPRequest
这部分的内容可以参考作者另一篇博文《ASIHTTPRequest的使用》。
¥ NSOperation 和 Libxml
这部分内容在作者的一篇博文《使用NSOperation实现异步下载》中也有介绍。
背景知识已经具备,下面让我们继续。
一、准备libxml环境
libxml2 是一个开放源码库,默认情况下iPhone SDK 中已经包括在内。 它是一个基于 C 的 API,所以在使用上比 cocoa 的 NSXML 要麻烦许多(一种类似 c 函数的使用方式),但是该库同时支持 DOM 和 SAX 解析,其解析速度较快,而且占用内存小,是最适合使用在 iphone 上的解析器。 从性能上讲,所有知名的解析器中,TBXML 最快,但在内存占用上,libxml 使用的内存开销是最小的。因此,我们决定使用 libxml 的sax接口。
首先,我们需要在 project 中导入 framework:libxml2.dylib。
虽然 libxml 是 sdk 中自带的,但它的头文件却未放在默认的地方,因此还需要我们设置 project 的 build 选项:HEADER_SEARCH_PATHS = /usr/include/libxml2,否则 libxml 库不可用。
然后,我们就可以在源代码中 #import <libxml/tree.h> 了。
至于 ASIHTTPRequest 的使用环境,请参考 《ASIHTTPRequest的使用》 进行。
二、线程管理
首先,我们肯定要使用线程来进行实现。多线程的操作使用NSOperation子类。
新建 o-c class,命名为 SyncRequestParseOperation ,它必需继承NSOperation。
我们决定不使用继承而使用聚合来让它同时具有 ASIHTTPRequest 和 Xml 解析的功能,因此我们导入了libxml/tree.h 和 ASIHTTPRequest.h 。
由 于服务器使用了GBK 编码,所以我们也使用了 NSStringEncoding 。 kRequestStatus 定义了一个枚举,用来表 示 SyncRequestParseOperation 的不同状态:请求完毕、请求失败、收到数据包。这3种可能状态会被成员变量 status 使用,实际上它是个int。头文件定义如下:
#import <libxml/tree.h>
#import "BaseXmlParser.h"
#import "ASIHTTPRequest.h"
enum kRequestStatus {
kRequestStatusFinished ,
kRequestStatusFailed ,
kRequestStatusDataReceived
};
@interface SyncRequestParseOperation : NSOperation
{
NSURL * _url ;
NSDictionary * _data ;
// 构建 gb2312 的 encoding
NSStringEncoding enc ;
//Xml 解析器指针
xmlParserCtxtPtr _parserContext ;
BaseXmlParser * baseParser ;
id delegate , progressDelegate ;
int status ;
}
@property ( nonatomic , retain ) NSDictionary *data;
@property ( nonatomic , retain ) NSURL *url;
@property ( assign ) int status;
- ( id )initWithURLString:( NSString *) url xmlParser:( BaseXmlParser *) parser delegate:( id )obj;
-( void )setProgressDelegate:( id )progress;
-( void )statusChangedNotify;
@end
BaseXmlParser 是一个Xml解析器的基类,我们使用它的子类来进行Xml解析,在其中定义了一些使用 libxml 时特有的结构体和函数声明。有了它,我们就可以在其子类中覆盖某些方法来解析各种不同的XML 文件。
BaseXmlParser 及其子类我们后面会介绍。
delegate和 progressDelegate 保存两个对象的 id 引用。前者是负责响应 SyncRequestParseOperation 类的一些特殊的通知消息,比如某个状态的改变;后者负责根据收到的数据实时进行进度显示。
接下来我们看实现,首先是初始化 init 方法:
initWithURLString :xmlParser: delegate:( id )obj 方法是个便利的初始化方法,分别对3个成员进行初始化,而不必要对它们一一调用setter方法:http请求地址url、解析器、通知消息的委托对象。
- ( id )initWithURLString:( NSString *) url xmlParser:( BaseXmlParser *)parser delegate:( id )obj{
if ( self = [ super init ]) {
_url =[[ NSURL alloc ] initWithString : url ];
delegate =obj;
baseParser =[parser retain ];
// 构建 gb2312 的 encoding
enc = CFStringConvertEncodingToNSStringEncoding ( kCFStringEncodingGB_18030_2000 );
}
return self ;
}
除了init方法外,我们也提供了 setProgressDelegate 方法:
-( void )setProgressDelegate:( id )progress{
progressDelegate =progress;
}
用于对 progressDelegate 进行初始化。
接下来是最主要的部分,NSOperation的生命周期方法:
#pragma mark NSOperation 的生命周期方法
// 开始线程 - 本类的主方法
- ( void )start {
NSLog ( @"operation start!" );
if (![ self isCancelled ]) {
// 创建 XML 解析器指针
_parserContext = xmlCreatePushParserCtxt (& _saxHandlerStruct , baseParser , NULL , 0 ,NULL );
// 以异步方式处理事件,并设置代理块
__block ASIHTTPRequest *request = [ ASIHTTPRequest requestWithURL : _url ];
// 设置进度代理
if ( progressDelegate != nil ) {
[request setDownloadProgressDelegate : progressDelegate ];
}
// 使用 complete 块,在下载完时做一些事情
[request setCompletionBlock :^( void ){
[ self setStatus : kRequestStatusFinished ];
NSLog ( @"request completed!" );
// 添加解析数据(结束),注意最后一个参数 terminate
xmlParseChunk ( _parserContext , NULL , 0 , 1 );
// 添加解析数据(结束),
if ( baseParser != nil ){
[ self setData :[[ baseParser getResult ] copy ]];
} else {
NSLog ( @"baseparser is nil" );
}
// 释放 XML 解析器
if ( _parserContext ) {
xmlFreeParserCtxt ( _parserContext ), _parserContext = NULL ;
}
[ self statusChangedNotify ];
}];
// 使用 failed 块,在下载失败时做一些事情
[request setFailedBlock :^( void ){
[ self setStatus : kRequestStatusFailed ];
NSLog ( @"request failed !" );
// 释放 XML 解析器指针
if ( _parserContext ) {
xmlFreeParserCtxt ( _parserContext ), _parserContext = NULL ;
}
[ self statusChangedNotify ];
}];
// 使用 received 块,在接受到数据时做一些事情
[request setDataReceivedBlock :^( NSData * data ){
[ self setStatus : kRequestStatusDataReceived ];
NSLog ( @"received data:%d" , data . length );
// 添加解析数据(结束),注意最后一个参数 terminate
if ( baseParser != nil && baseParser != NULL ){
[ self setData :[[ baseParser getResult ] copy ]];
} else {
NSLog ( @"baseparser is nil" );
}
// 使用 libxml 解析器进行 xml 解析
xmlParseChunk ( _parserContext , ( const char *)[ data bytes], [ data length ], 0 );
[ self statusChangedNotify ];
}];
[request startAsynchronous ];
}
}
// 停止线程
- ( void )cancel
{
[ super cancel ];
}
对 于一个NSOperation 来说,最主要的是start 方法,因为线程在这里启动。由于使用了 ASIHTTPRequest 的异步方式,所以在start方法中我们没有使用 NSRunLoop 循环( 这个问题参考http://www.cocoabuilder.com /archive/cocoa/279826-nsurlrequest-and-nsoperationqueue.html )。因为 ASIHTTPRequest 的startAsynchronous 方法提供了额外的线程。我们在 start 方法中使用了一个ASIHTTPRequest ,利用 BaseXmlParser 解析器来提供一系列符合 libxml 规范的回调函数,以响应 sax 解析事件。当然,由于我们要实现“边接收数据,边解析Xml”的目的,我们在 ASIHTTPRequest 的三个委托块中,就对数据进行了处理(使用 libxml 的函数)。
比较怪异的是对 ASIHTTPRequest 的3个事件委托中使用了块语法,块语法介绍可以参考作者另一篇(翻译)博文《块编程指南》。
为了把3个委托事件通知给delegate,我们需要在3个事件委托块中调用delegate 的相应方法:
// status 状态变化通知
-( void )statusChangedNotify{
if ( delegate != nil ) {
SEL sel= NSSelectorFromString ( @"syncRequestParseStatusNofity:" );
if ([ delegate respondsToSelector :sel]){
[ delegate performSelector :sel withObject : self ]; // 注意冒号说明带 1 个参数
}
}
}
为了简便,我没有定义新的协议,而只是使用方法名 syncRequestParseStatusNofity: 作为内部协议。如果delegate要想接收通知,就必需实现该方法。作为一种技巧,其中使用了反射机制,避免运行时错误。
三、Sax 异步解析
libxml 是C函数库,其中很多函数需要使用令人生畏的结构体定义。为了便于扩展,这些定义被放到了 BaseXmlParser 类中:
#import <Foundation/Foundation.h>
#import <libxml/tree.h>
@interface BaseXmlParser : NSObject {
NSStringEncoding enc ;
NSMutableDictionary * _root ;
}
// Property
- ( void )startElementLocalName:( const xmlChar *)localname
prefix:( const xmlChar *)prefix
URI:( const xmlChar *)URI
nb_namespaces:( int )nb_namespaces
namespaces:( const xmlChar **)namespaces
nb_attributes:( int )nb_attributes
nb_defaulted:( int )nb_defaultedslo
attributes:( const xmlChar **)attributes;
- ( void )endElementLocalName:( const xmlChar *)localname
prefix:( const xmlChar *)prefix URI:( const xmlChar *)URI;
- ( void )charactersFound:( const xmlChar *)ch
len:( int )len;
-( NSDictionary *)getAtributes:( const xmlChar **)attributes withSize:( int )nb_attributes;
-( NSDictionary *)getResult;
@end
//3 个静态方法的实现,其实是调用了 ctx 的成员方法,其中 ctx 在 _parserContext 初始化时传入
static void startElementHandler(
void * ctx,
const xmlChar * localname,
const xmlChar * prefix,
const xmlChar * URI,
int nb_namespaces,
const xmlChar ** namespaces,
int nb_attributes,
int nb_defaulted,
const xmlChar ** attributes)
{
[( BaseXmlParser *)ctx
startElementLocalName :localname
prefix :prefix URI :URI
nb_namespaces :nb_namespaces
namespaces :namespaces
nb_attributes :nb_attributes
nb_defaulted :nb_defaulted
attributes :attributes];
}
static void endElementHandler(
void * ctx,
const xmlChar * localname,
const xmlChar * prefix,
const xmlChar * URI)
{
[( BaseXmlParser *)ctx
endElementLocalName :localname
prefix :prefix
URI :URI];
}
static void charactersFoundHandler(
void * ctx,
const xmlChar * ch,
int len)
{
[( BaseXmlParser *)ctx
charactersFound :ch len :len];
}
//libxml 的 xmlSAXHandler 结构体定义,凡是要实现的 handler 函数都写在这里,不准备实现的用 null代替。一般而言,我们只实现其中 3 个就够了
static xmlSAXHandler _saxHandlerStruct = {
NULL , /* internalSubset */
NULL , /* isStandalone */
NULL , /* hasInternalSubset */
NULL , /* hasExternalSubset */
NULL , /* resolveEntity */
NULL , /* getEntity */
NULL , /* entityDecl */
NULL , /* notationDecl */
NULL , /* attributeDecl */
NULL , /* elementDecl */
NULL , /* unparsedEntityDecl */
NULL , /* setDocumentLocator */
NULL , /* startDocument */
NULL , /* endDocument */
NULL , /* startElement*/
NULL , /* endElement */
NULL , /* reference */
charactersFoundHandler, /* characters */
NULL , /* ignorableWhitespace */
NULL , /* processingInstruction */
NULL , /* comment */
NULL , /* warning */
NULL , /* error */
NULL , /* fatalError //: unused error() get all the errors */
NULL , /* getParameterEntity */
NULL , /* cdataBlock */
NULL , /* externalSubset */
XML_SAX2_MAGIC , /* initialized 特殊常量,照写 */
NULL , /* private */
startElementHandler, /* startElementNs */
endElementHandler, /* endElementNs */
NULL , /* serror */
};
在 BaseXmlParser 类的头文件中,可以分为两部分。
1. 第一部分是 interface 定义,定义了BaseXmlParser类的成员,包括:
¥ 成员变量
enc:基于和前面同样的原因,用于定义GBK编码。
_root:一个Dictionary,用于保存解析后Xml对象,一个xml文档只有一个root 元素,因此用一个Dictionary对象即可。
¥ 成员方法
libxml 回调方法:前3个很像是C语言函数的方法其实都是被libxml回调的,它们会在3个静态函数(在第二部分)中调用。
getAttributes方法:这个是一个方便的获取 xml 元素属性的方法。由于本例中的 XML 文档大量使用了属性,所以这个方法很实用。
getResult方法:用于获得 XML 文档解析结果,即 _root 对象。
2. 第二部分是 libxml 回调函数和结构体定义,包括:
¥ 回调函数
本例我们决定实现3个回调函数,分别用于响应 Sax 解析中的3个事件:
处理 XML 元素开始标记、处理 XML 元素结束标记、处理 XML 元素体。
为了更 OO 一些,我们没有直接在这 3 个函数中写对应的 XML 解析代码,而是调用了类的成员方法进行处理。这样,我们可以在 implement 部分写入具体的代码。
¥ 结构体
只 需要填充一个结构体 xmlSAXHandler 即可。这个结构成员数量众多(31个),但我们只需填充你要实现的几个。例如,我们要实现3个回调函 数,那么只消在对应的地方填充这3个函数名即可(此外有一个特殊的成员叫XML_SAX2_MAGIC ,你照填就是了)。为了便于大家理解这些成员所代 表的意义,我们也在旁边做了注释,你可以对照着看。
接下来是implement (实现)。
#import "BaseXmlParser.h"
@implementation BaseXmlParser
// Property
-( id )init{
if ( self =[ super init ]){
// 构建 gb2312 的 encoding
enc = CFStringConvertEncodingToNSStringEncoding ( kCFStringEncodingGB_18030_2000 );
_root =[[ NSMutableDictionary alloc ] init ];
}
return self ;
}
-( void )dealloc{
[ _root release ], _root = nil ;
[ super dealloc ];
}
// 一个便利方法,用于获取元素的属性值
-( NSDictionary *)getAtributes:( const xmlChar **)attributes withSize:( int )nb_attributes{
NSMutableDictionary * atts=[[ NSMutableDictionary alloc ] init ];
NSString *key,*val;
for ( int i= 0 ; i<nb_attributes; i++){
key = [ NSString stringWithCString :( const char *)attributes[ 0 ] encoding : NSUTF8StringEncoding];
val = [[ NSString alloc ] initWithBytes :( const void *)attributes[ 3 ] length :(attributes[ 4 ] - attributes[ 3 ]) encoding : NSUTF8StringEncoding ];
[atts setObject :val forKey :key];
[key release ],[val release ];
attributes += 5 ; // 指针移动 5 个字符串,到下一个属性
}
return atts;
}
//--------------------------------------------------------------//
#pragma mark -- libxml handler ,主要是 3 个回调方法 , 空方法,等待子类实现 --
//--------------------------------------------------------------//
// 解析元素开始标记时触发 , 在这里取元素的属性值
- ( void )startElementLocalName:( const xmlChar *)localname
prefix:( const xmlChar *)prefix
URI:( const xmlChar *)URI
nb_namespaces:( int )nb_namespaces
namespaces:( const xmlChar **)namespaces
nb_attributes:( int )nb_attributes
nb_defaulted:( int )nb_defaultedslo
attributes:( const xmlChar **)attributes
{
}
// 解析元素结束标记时触发
- ( void )endElementLocalName:( const xmlChar *)localname
prefix:( const xmlChar *)prefix URI:( const xmlChar *)URI
{
}
// 解析元素体时触发
- ( void )charactersFound:( const xmlChar *)ch
len:( int )len
{
}
// 返回解析结果
-( NSDictionary *)getResult{
return _root ;
}
@end
可 以看到,除了 getAttributes 和 getResult 方法外,我们都没有进行其它方法的实现。这是因为 Sax 解析跟 Dom 解析不同,针对不同的 XML 文档很难使用相同的逻辑解析,因此我们准备把剩下的内容留给子类来实现,这样不同的XML 文档可以通过不同的子类来进行解析,而不用在每个子类中都写一遍那些怪异的 C 回调函数和结构体声明。
我们要解析的 XML 文档可能是这样的:
<root>
<List Name="同事">
<user name="t2" phone="13884831140"/>
<user name="t3" phone="15877103548"/>
<user name="t1" phone="13399459990"/>
</List>
<List Name="好友">
<user name="f2" phone="13828831140"/>
<user name="f3" phone="15886103548"/>
<user name="f1" phone="13019459990"/>
</List>
</root>
也就是说,这是一个通讯录类似的东西。通讯录把电话号码按性质分成不同的组,就像Windows mobile智能手机上的的通讯录,把电话号码按“家庭”、“好友”、“同事”等进行划分。
我们新建一个 BaseXmlParser的子类 TelNoXmlParser ,让这个 TelNoXmlParser 去实现 3 个回调方法:
#import <Foundation/Foundation.h>
#import <libxml/tree.h>
#import "BaseXmlParser.h"
@interface TelNoXmlParser : BaseXmlParser {
BOOL loginSuccess ;
NSMutableArray * groups ,* members ;
NSMutableDictionary * _group ;
NSDictionary * _user ;
}
@end
#import "TelNoXmlParser.h"
@implementation TelNoXmlParser
-( id )init{
if ( self =[ super init ]) {
// 一个 groups 数组,代表了所有 List
groups =[[ NSMutableArray alloc ] init ];
[ _root setObject : groups forKey : @"items" ];
loginSuccess = YES ;
}
return self ;
}
-( void )dealloc{
[ _group release ], _group = nil ;
[ super dealloc ];
}
//--------------------------------------------------------------//
#pragma mark -- libxml handler ,主要是 3 个回调方法 --
//--------------------------------------------------------------//
// 解析元素开始标记时触发 , 在这里取元素的属性值以及设置标志变量
- ( void )startElementLocalName:( const xmlChar *)localname
prefix:( const xmlChar *)prefix
URI:( const xmlChar *)URI
nb_namespaces:( int )nb_namespaces
namespaces:( const xmlChar **)namespaces
nb_attributes:( int )nb_attributes
nb_defaulted:( int )nb_defaultedslo
attributes:( const xmlChar **)attributes
{ // 我们关心 8 个元素标签,所以设置了 8 个标志位
// login_status
if ( strncmp (( char *)localname, "login_status" , sizeof ( "login_status" )) == 0 ) {
loginSuccess = NO ;
return ;
}
if ( loginSuccess ) {
// List
if ( strncmp (( char *)localname, "List" , sizeof ( "List" )) == 0 ) {
NSDictionary * atts=[ self getAtributes :attributes withSize :nb_attributes]; // 获取 List 的所有属性
_group =[[ NSMutableDictionary alloc ] init ];
members =[[ NSMutableArray alloc ] init ];
[ _group setObject : members forKey : @"members" ];
[ _group setObject :[[ NSString alloc ] initWithString :( NSString *)[atts objectForKey : @"Name" ]]forKey : @"groupname" ];
[ groups addObject : _group ]; // 把 group 加入数组
return ;
}
// user
if ( strncmp (( char *)localname, "user" , sizeof ( "user" )) == 0 ) {
NSDictionary * atts=[ self getAtributes :attributes withSize :nb_attributes]; // 获取 List 的所有属性
_user =[[ NSDictionary alloc ] initWithDictionary :atts];
[ members addObject : _user ];
return ;
}
}
}
// 解析元素结束标记时触发
- ( void )endElementLocalName:( const xmlChar *)localname
prefix:( const xmlChar *)prefix URI:( const xmlChar *)URI
{
if ( strncmp (( char *)localname, "root" , sizeof ( "root" )) == 0 ){ //root 结束时置 login_status 标志
if ( loginSuccess ) {
[ _root setObject : @"true" forKey : @"login_status" ];
} else {
[ _root setObject : @"false" forKey : @"login_status" ];
}
}
if ( loginSuccess ) {
// 我们还关心 <List> 的结束标记
if ( strncmp (( char *)localname, "List" , sizeof ( "List" )) == 0 ) {
[ _group release ], _group = nil ; // 回收 _group 对象,以便重复利用
} else if ( strncmp (( char *)localname, "user" , sizeof ( "user" )) == 0 ){
[ _user release ], _user = nil ; // 回收 _user 对象,以便重复利用
}
}
}
// 解析元素体时触发
- ( void )charactersFound:( const xmlChar *)ch
len:( int )len
{
// 没有元素体需要关心
}
@end
接下来我们看如何在 ViewController 中使用。
四、在 UI 中测试
在 ViewController 中放入一个按钮和一个 WebView,当点击按钮时,请求http服务器,获取通讯录XML 数据,并解析为 Dictionary 对象。把解析结果显示在 WebView 中。
这是按钮的 touch up inside 事件代码:
-( IBAction )go{
if ( _queue == nil ){
_queue = [[ NSOperationQueue alloc ] init ];
}
[ button setEnabled : NO ];
[ progress setProgress : 0 ];
[ webView loadHTMLString : @"" baseURL :[ NSURL URLWithString : URL ]];
// 构造 xmlparser
TelNoXmlParser * parser=[[ TelNoXmlParser alloc ] init ];
// 把 self 注册为 delegate ,这样 self 必需实现 syncRequestParseStatusNofity: 方法 , 以接收statusChanged 方法
SyncRequestParseOperation * operation=[[ SyncRequestParseOperation alloc ]
initWithURLString : URL
xmlParser :parser
delegate : self ];
// 把 progress 设置为 progressDelegate ,这样会显示进度
[operation setProgressDelegate : progress ];
[parser release ]; // opertaion 已 retain ,可以 release
[ _queue addOperation :operation]; // 开始处理
[operation release ]; // 队列已 retain ,可以 release ;
}
这是异步消息到达时的处理代码,当数据接收完时,我们把解析结果在WebView 中显示:
// 实现 statusChanged 通知方法
-( void )syncRequestParseStatusNofity:( id )sender{
SyncRequestParseOperation * operation=( SyncRequestParseOperation *)sender;
int status=[operation status ];
NSLog ( @"status:%d" ,status);
if (status== kRequestStatusFinished ){ // 如数据接收完成
[ button setEnabled : YES ];
NSDictionary * d=[operation data ];
[ webView loadHTMLString :[d description ] baseURL :[ NSURL URLWithString : URL ]];
}
}
这是程序运行时 WebView 显示效果:
注意,当xml 文档比较大时,WebView 的内容是从上到下逐渐刷新的。
这是控制台输出,可以看到服务器响应的数据是被分成很多次下载的:
发表评论
-
IOS7 小技巧
2013-11-17 21:04 9281.设置navigationBar的字体颜色 se ... -
开发小技巧
2013-06-05 14:10 10211.设置View阴影 button.layer.shad ... -
iPhone 路径大全
2012-01-30 13:44 14671、【/Applications】常用软件的安装目录 2. 【 ... -
CABasicAnimation
2012-01-20 19:36 1008//移动 CABasicAnimati ... -
IOS 5手势识别教程:二指拨动、拖移以及更多手势
2012-01-29 16:04 1678免责申明(必读!):教程的翻译原稿均来自于互联网,仅供学习交流 ... -
iPhone图形开发绘图小结
2011-12-29 09:34 9531、绘图总结: 绘图前设置: CGContextS ... -
math.h里的数学计算公式介绍
2011-12-14 10:27 14391、 三角函数 double sin (do ... -
UItableView 详细讲解
2011-11-06 18:40 1022-、建立 UITableView DataTable = [[ ... -
UIView to UIImage resize 图片
2011-10-24 15:10 96501 有时候你想把某个view上的内容截取下来,变 ... -
自定义NavgationController动画
2011-10-14 11:08 1478只要把这两个方法作为UINavigationControlle ... -
在程序运行中调整UITableViewCell高度
2011-09-19 23:22 1572最近要实现下面的效果,就是在UITableView中有很多 ... -
在iphone工程属性设置时,使用相对路径
2011-09-19 23:21 896"$(SRCROOT)" 这个代表工 ... -
ios设置时区转换
2011-09-19 23:20 1756有的时候为了在系统中统一时间,需要在服务器和客户端统一交换 ... -
ios通过google map显示地图和乘车信息
2011-09-19 23:19 754添加一个UIWebView控件,UIWebView *my ... -
ios实现汉字拼音首字母类库
2011-09-19 23:18 1173phone的通讯录是按照字母进行排序的,那么中文需要知道第一个 ... -
捕获 iPhone 电话呼叫事件的方法
2011-09-19 23:15 1060这是 iOS 4.0 以后才公开的接口,用于捕获 iPho ... -
在 iPhone 静音情况下,播放 MP3 文件的代码
2011-09-19 23:14 1429在 iPhone 静音情况下,播放 MP3 文件的代码 ... -
向iPhone模拟器中添加视频
2011-09-19 23:14 1274NSString *path=[[NSBundle mai ... -
适合显示时间的字体
2011-09-19 23:11 1025UILabel *label = [[UILabe ... -
UIWebView显示gif图片
2011-09-19 23:10 1364在适当的地方加入下面的代码: NSString* ...
相关推荐
在“ASIHTTPRequest和libxml结合,实现边请求边解析”这篇文章中,作者可能探讨了如何利用ASIHTTPRequest库来发起HTTP请求,并结合libxml库进行XML数据的解析。libxml是开源的XML和HTML解析器,能够高效地处理XML...
通过学习和理解这个示例,你将能够熟练掌握ASIHttpRequest进行队列下载以及与UITableView结合的技巧。记得在实际开发中,考虑到性能和内存管理,适当使用异步操作和通知机制,确保用户体验流畅。虽然ASIHttpRequest...
在本文中,我们将深入探讨ASIHTTPRequest的核心功能、异步与同步请求的实现,以及如何在项目中集成和使用它。 1. ASIHTTPRequest的核心特性 - 简单的API:ASIHTTPRequest提供了直观的方法来发起GET、POST、PUT、...
本项目使用了ASIHTTPRequest库与UITableView相结合来实现这一功能。ASIHTTPRequest是一个广泛使用的HTTP请求库,它提供了简单易用的API,使得网络请求操作变得相对简单。而UITableView则是iOS中用于展示列表数据的...
ASIHTTPRequest是一个Objective-C库,专为iOS和Mac OS X平台设计,用于简化...尽管已不再更新,但其设计理念和实现方式仍值得学习和借鉴。在实践中,结合现代框架的特性,我们可以更好地优化网络交互,提升应用性能。
6. **请求队列管理**:可以将多个请求放入请求队列,实现批处理和顺序执行,避免同时发起大量请求导致服务器压力过大。 7. **自定义请求头和请求体**:允许开发者添加自定义的HTTP头和POST数据,适应各种API接口的...
ASIHTTPRequest是iOS开发中早期广泛使用的一个网络请求库,由美国...总之,ASIHTTPRequest是一个经典的网络请求库,它的设计理念和实现方法对于iOS开发者来说,无论是历史回顾还是实际应用,都具有一定的学习价值。
3. **自动处理Cookie**:ASIHttpRequest会自动管理服务器返回的Cookie,方便下次请求时自动携带,实现了Cookie的持久化。 4. **请求缓存**:支持本地缓存策略,当网络不畅时,可以从本地缓存读取数据,提高了应用的...
2. **初始化请求**:创建ASIHTTPRequest对象,指定URL和请求方法(GET、POST等)。 3. **设置参数**:如果需要发送数据,可以通过setPostValue或setRequestData设置POST参数。 4. **开始请求**:调用start方法启动...
- 当请求完成时,你可以通过实现 `ASIRequestDelegate` 协议中的方法来接收结果,如 `requestFinished:` 和 `requestFailed:`。 - `-[ASIHTTPRequest setCompletionBlock:]` 和 `-[ASIHTTPRequest setErrorBlock:]...
创建ASIHttpRequest对象,并指定请求类型(GET/POST)和URL地址。 ```objective-c ASIHttpRequest *request = [ASIHttpRequest requestWithURL:[NSURL URLWithString:@"https://example.com"]]; ``` 3. **设置...
ASIHTTPRequest 是一个Objective-C编写的网络请求库,广泛应用于iOS和Mac OS X开发中,它为开发者提供了简单易用的接口来发起HTTP请求。这个源码包包含了ASIHTTPRequest库的完整源代码,对于深入理解网络请求处理...
关于Git官方示例,它可能包含了一些使用ASIHTTPRequest的代码示例,这些示例展示了如何发起GET和POST请求,处理响应,设置请求头,以及如何使用队列等。通过阅读和运行这些示例,你可以更好地理解ASIHTTPRequest的...
本主题将深入探讨一个基于标题“iOS解析xml通用类”的知识点,这个通用类使用了libxml库来实现XML的解析,并且结合ASI开源库实现了边下载边解析的功能。 首先,让我们了解一下XML解析的基本概念。XML是一种自描述性...
6. **请求队列管理**:ASIHTTPRequest支持请求队列,可以方便地管理和控制多个并发请求,避免过度消耗系统资源。 7. **错误处理**:当请求失败时,ASIHTTPRequest会提供详细的错误信息,帮助开发者定位问题所在。 ...
- **libxml2.dylib** - XML解析库 #### 三、创建和执行请求 ##### 1. 同步请求 同步请求会在当前线程中执行,可能导致UI卡顿或无响应。使用`error`属性来检查请求是否成功完成: ```objective-c - (IBAction)...
ASIHTTPRequest 是一个基于苹果的 CFNetwork 框架开发的开源网络库,它为 iOS 和 Mac OS X 平台提供了简单而强大的 HTTP 请求处理。这个库由 Ben Copsey 创建,旨在简化网络通信任务,尤其在处理异步请求、队列管理...