typedef的用法总结

不管实在C还是C++代码中,typedef这个词都不少见,当然出现频率较高的还是在C代码中。typedef与#define有些相似,但更多的是不同,特别是在一些复杂的用法上,就完全不同了,看了网上一些C/C++的学习者的博客,其中有一篇关于typedef的总结还是很不错,由于总结的很好,我就不加修改的引用过来了,以下是引用的内容(红色部分是我自己写的内容)。

用途一:

定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。比如:

char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针,

// 和一个字符变量;

以下则可行:

typedef char* PCHAR;

PCHAR pa, pb;

这种用法很有用,特别是char pa, pb的定义,初学者往往认为是定义了两个字符型指针,其实不是,而用typedef char\ PCHAR就不会出现这样的问题,减少了错误的发生。

用途二:

用在旧的C代码中,帮助struct。以前的代码中,声明struct新对象时,必须要带上struct,即形式为: struct 结构名对象名,如:

1
2
3
4
5
6
7
8
9
struct tagPOINT1
{
int x;
int y;
};
struct tagPOINT1 p1;

而在C++中,则可以直接写:结构名对象名,即:tagPOINT1 p1;

1
2
3
4
5
6
7
8
9
typedef struct tagPOINT
{
int x;
int y;
}POINT;
POINT p1;

这样就比原来的方式少写了一个struct,比较省事,尤其在大量使用的时

候,或许,在C++中,typedef的这种用途二不是很大,但是理解了它,对掌握以前的旧代

码还是有帮助的,毕竟我们在项目中有可能会遇到较早些年代遗留下来的代码。

用途三:

用typedef来定义与平台无关的类型。

比如定义一个叫 REAL 的浮点类型,在目标平台一上,让它表示最高精度的类型为:

typedef long double REAL;

在不支持 long double 的平台二上,改为:

typedef double REAL;

在连 double 都不支持的平台三上,改为:

typedef float REAL;

也就是说,当跨平台时,只要改下 typedef 本身就行,不用对其他源码做任何修改。

标准库就广泛使用了这个技巧,比如size_t。另外,因为typedef是定义了一种类型的新别名,不是简单的字符串替换,所以它比宏来得稳健。
这个优点在我们写代码的过程中可以减少不少代码量哦!

用途四:

为复杂的声明定义一个新的简单的别名。方法是:在原来的声明里逐步用别名替换一部

分复杂声明,如此循环,把带变量名的部分留到最后替换,得到的就是原声明的最简化

版。举例:

原声明:void (*b[10]) (void (*)());

变量名为b,先替换右边部分括号里的,pFunParam为别名一:

typedef void (*pFunParam)();

再替换左边的变量b,pFunx为别名二:

typedef void (*pFunx)(pFunParam);

原声明的最简化版:

pFunx b[10];

原声明:doube(*)() (*e)[9];

变量名为e,先替换左边部分,pFuny为别名一:

typedef double(*pFuny)();

再替换右边的变量e,pFunParamy为别名二

typedef pFuny (*pFunParamy)[9];

原声明的最简化版:

pFunParamy e;

理解复杂声明可用的“右左法则”:从变量名看起,先往右,再往左,碰到一个圆括号

就调转阅读的方向;括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直

到整个声明分析完。举例:

int (func)(int \p);

首先找到变量名func,外面有一对圆括号,而且左边是一个*号,这说明func是一个指针

;然后跳出这个圆括号,先看右边,又遇到圆括号,这说明(*func)是一个函数,所以

func是一个指向这类函数的指针,即函数指针,这类函数具有int*类型的形参,返回值

类型是int。

int (*func[5])(int *);

func右边是一个[]运算符,说明func是具有5个元素的数组;func的左边有一个*,说明

func的元素是指针(注意这里的*不是修饰func,而是修饰func[5]的,原因是[]运算符

优先级比*高,func先跟[]结合)。跳出这个括号,看右边,又遇到圆括号,说明func数

组的元素是函数类型的指针,它指向的函数具有int*类型的形参,返回值类型为int。

这种用法是比较复杂的,出现的频率也不少,往往在看到这样的用法却不能理解,相信以上的解释能有所帮助。

*以上为参考部分,以下为本人领悟部分*

使用示例:

1.比较一:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
using namespace std;
typedef int (*A) (char, char);
int ss(char a, char b)
{
cout<<"功能1"<<endl;
cout<<a<<endl;
cout<<b<<endl;
return 0;
}
int bb(char a, char b)
{
cout<<"功能2"<<endl;
cout<<b<<endl;
cout<<a<<endl;
return 0;
}
void main()
{
A a;
a = ss;
a('a','b');
a = bb;
a('a', 'b');
}

2.比较二:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef int (A) (char, char);
void main()
{
A *a;
a = ss;
a('a','b');
a = bb;
a('a','b');
}

两个程序的结果都一样:

功能1

a

b

功能2

b

a

*以下是参考部分*

参考自:http://blog.hc360.com/portal/personShowArticle.do?articleId=57527

typedef 与 #define的区别:

案例一:

通常讲,typedef要比#define要好,特别是在有指针的场合。请看例子:

1
2
3
4
5
6
7
8
typedef char *pStr1;
#define pStr2 char *;
pStr1 s1, s2;
pStr2 s3, s4;

在上述的变量定义中,s1、s2、s3都被定义为char *,而s4则定义成了char,不是我们

所预期的指针变量,根本原因就在于#define只是简单的字符串替换而typedef则是为一

个类型起新名字。

案例二:

下面的代码中编译器会报一个错误,你知道是哪个语句错了吗?

1
2
3
4
5
6
7
8
9
10
11
12
typedef char * pStr;
char string[4] = "abc";
const char *p1 = string;
const pStr p2 = string;
p1++;
p2++;

  是p2++出错了。这个问题再一次提醒我们:typedef和#define不同,它不是简单的

文本替换。上述代码中const pStr p2并不等于const char * p2。const pStr p2和

const long x本质上没有区别,都是对变量进行只读限制,只不过此处变量p2的数据类

型是我们自己定义的而不是系统固有类型而已。因此,const pStr p2的含义是:限定数

据类型为char *的变量p2为只读,因此p2++错误。虽然作者在这里已经解释得很清楚了,可我在这个地方仍然还是糊涂的,真的希望哪位高手能帮忙指点一下,特别是这一句“只不过此处变量p2的数据类型是我们自己定义的而不是系统固有类型而已”,难道自己定义的类型前面用const修饰后,就不能执行更改运算,而系统定义的类型却可以?

原文:http://www.cnblogs.com/csyisong/archive/2009/01/09/1372363.html

void (\*b[10]) (void (\*)())

void (*b[10]) (void (*)());

看到这行代码,相信程序员们都会倒吸一口冷气吧。如果非常不幸的在维护的代码中看到类似的表述,除了想办法找出写出这种天书的猛人来,只能自己硬着头皮搞清楚了。

在C和C++中,构造这类声明表达式只有一条简单的规则:按照使用的方式来声明。

C变量的声明都是由两部分组成的:类型,以及一组类似表达式的声明符(declarator)。声明符类似于表达式,对它求值应该返回一个声明中给定类型的结果。例如,我们来看一个简单的声明:

float f;

这里f就是声明符,对其求值,应该得到一个float型的数值。

然后看括号的作用,比如:

float ((f));

很简单,这个声明的含义就是,((f))的类型为浮点类型。因为括号和f之间没有其他的修饰了,所以,我们可以推知,f也是浮点型。

再来看稍微复杂点的:

float f();

我们注意到有一个()表达式出现,这个声明符的含义是一个函数。所以这个声明的含义就是,f()的求值结果是一个浮点数,也就是说,f是个返回值为浮点数的函数。

OK,这些都很简单,再看一个:

float *f();

这个就是表示*f()是个浮点表达式,而()的结合优先级高于*,所以,*f()也就是*(f()),f是个函数,返回值是个指针,这个指针指向一个浮点数。

如果*f是先结合的呢?比如:

float (*f)();

这时,f就不是和()结合而成为一个函数名,而是和*结合成为一个指针名,这个指针,是指向函数入口的函数指针,而这个函数,返回值是浮点型。

现在我们知道怎么声明一个指定类型的变量了。在这个声明表达式中,把变量名,和声明末尾的分号去掉,剩余的部分用一个括号整个括起来,这样就得到了这个变量的类型声明了,比如:

float (*f)();

这个表示f是一个指向返回值为浮点型的函数指针。而我们把f这个变量名,和最后的;号去掉,就得到:

( float (*)() )

这个就表示,这个表达式是一个类型,即“指向返回值为浮点型的函数的指针”。如果用这个类型去修饰一个变量名,我们就叫它类型转换符。

现在有了这些预备知识,我们可以回头看标题的声明到底是什么意思了:

void (*b[10]) (void (*)());

首先,表达式的后半部分被两个()分隔开了,我们分别分析它们。( *b[10] ),其中出现了变量名b,很容易就知道,b是一个有10个元素的数组,每个元素都是一个指针。

然后,看(void(*)()),其中没有出现变量名,所以它代表了一个类型,即“指向返回值为void型的函数的指针“,而我们知道,C语法中,类型修饰符是必须出现在变量名的左边的,而在整个表达式中这个类型符是在变量名b的右边,所以, (void(*)())最外层的这个(),表示了定义了一个函数,这个函数有一个参数,就是一个指针,具体来说,就是“指向返回值为void型的函数的指针“。

这样就很清楚了,b数组里,每一个指针元素,都是一个函数指针,这个函数有一个参数,这个参数是一个函数指针。整个表达式最左边的void,则定义了b数组中函数指针所指向函数的返回值类型。

在一串绕口令式的解说后,我们终于看到了事实的真相:这行代码就是逗你玩…

如果不是故意偷懒,这样代码的作者真是在玩弄阅读者的感情,如果非要实现这样一个复杂的定义的话,我们也是有更好的方法的,就是使用typedef来进行类型声明。

在面对void (*b[10]) (void (*)());时,我们可以先声明后半部分的类型:

typdef void (*pFunParam)();

即表示,类型pFunParam,是一个函数指针。

然后,针对整个表达式声明一个类型:

typedef void (*pFun)(pFunParam);

即表示,类型pFun,是一个函数指针。此函数的参数类型为pFunParam。

最后,进行变量的声明:

pFun b[10];

这样,就清晰许多了吧。最重要的时,利用这样的方式,将编写者的设计思路也体现在了代码中。

最后,介绍一个更快速的阅读方法:从右向左。

编译器在进行代码扫描时是从左向右的,而我们在解读这个表达式的时候,从右向左的方法会更容易些,如:

从右向左扫描以上表达式,首先我们看到一个“)”,因为其右边再没有变量,所以我们知道这是一个函数定义,然后,又看到一对“()“,显然也是函数定义,在就是(*),显然和后面的()联合起来表达了一个函数指针,再左边的void,即修饰了此指针的类型;然后出现了和最右边”)”对应的”(”,显然这个函数定义也完成了,再左边的[10]表达了一个数组,左边是它的名字b,而更左边的“*”和后面的“(“一起表达了一个函数指针,这个函数指针定义了b数组中元素的类型。再往左,指针元素的定义void也出现了。这样,我们就又看到了此表达式的真相。

C实现简单的面向对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <stdio.h>
#include <stdlib.h>
//Object begin>>>>>>>>>>>>
#define ObjectField \
void(*onDelete)(void*);
typedef struct Object{
ObjectField
} Object;
#define ObjectCreate(TYPE) malloc(sizeof(TYPE))
#define ObjectDelete(obj) {\
obj->onDelete(obj);\
free(obj);\
}
void ObjectOnDelete(void *obj){
printf("Object on delete\n");
}
Object* ObjectInit(Object *obj){
obj->onDelete = ObjectOnDelete;
return obj;
}
//Object end<<<<<<<<<<<<
typedef struct{
ObjectField
int age;
void(*sayHello)();
} People;
void PeopleSayHello(){
printf("Hello\n");
}
void PeopleOnDelete(void *p){
ObjectOnDelete(p);
printf("People on delete\n");
}
People* PeopleInit(People *p,int age){
ObjectInit((Object*)p);
p->age = age;
p->sayHello = PeopleSayHello;
p->onDelete = PeopleOnDelete;
return p;
}
int main(int argc, const char * argv[])
{
People *p = PeopleInit(ObjectCreate(People), 20);
p->sayHello();
ObjectDelete(p);
// printf("Hello, %d!\n",p->age);
return 0;
}

yii调试信息开启

Yii调试SQL主要有以下方法:

一、系统自带调试:

首先index.php开启调试模式

1
2
3
4
5
6
// remove the following lines when in production mode
defined('YII_DEBUG') or define('YII_DEBUG',true);
// specify how many levels of call stack should be shown in each log message
defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);
//app use time
//defined('YII_BEGIN_TIME') or define('YII_BEGIN_TIME',microtime(true));

main.php页面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
'errorHandler'=>array(
// use 'site/error' action to display errors
'errorAction'=>'site/error',
),
'log'=>array(
'class'=>'CLogRouter',
'routes'=>array(
array(
'class'=>'CFileLogRoute',
'levels'=>'error, warning',
),
// 下面显示页面日志
array(
'class'=>'CWebLogRoute',
'levels'=>'trace', //级别为trace
'categories'=>'system.db.*' //只显示关于数据库信息,包括数据库连接,数据库执行语句
),
),
),

YII_TRACE_LEVEL的数字越大,信息越清楚

二、使用调试工具调试:

yii-debug-toolbar把包解压后 放到extensions里边 然后在配置文件main.php中最后加上

1
2
3
4
5
6
7
8
9
'log'=>array(
'class'=>'CLogRouter',
'routes'=>array(
array(
'class'=>'ext.yii-debug-toolbar.YiiDebugToolbarRoute',
'ipFilters'=>array('127.0.0.1','192.168.1.215'),
),
),
),

没有出现的话加上在’components’下的db里加上两个属性,

1
2
'enableProfiling'=>true,
'enableParamLogging'=>true,

然后如果有其他调试工具的插件的话,可能会出现冲突导致sql语句不出来,把那段代码注掉即可。

AFNetworking官方例子

建筑

NSURLConnection的

  • AFURLConnectionOperation
  • AFHTTPRequestOperation
  • AFHTTPRequestOperationManager

NSURLSession(iOS的7 / Mac OS X的10.9)

  • AFURLSessionManager
  • AFHTTPSessionManager

序列化

AFURLRequestSerialization

  • AFHTTPRequestSerializer
  • AFJSONRequestSerializer
  • AFPropertyListRequestSerializer

AFURLResponseSerialization

  • AFHTTPResponseSerializer
  • AFJSONResponseSerializer
  • AFXMLParserResponseSerializer
  • AFXMLDocumentResponseSerializer (Mac OS X中)
  • AFPropertyListResponseSerializer
  • AFImageResponseSerializer
  • AFCompoundResponseSerializer

附加功能

  • AFSecurityPolicy
  • AFNetworkReachabilityManager

用法

HTTP请求营运经理

AFHTTPRequestOperationManager封装与Web应用程序进行通信通过HTTP,包括要求制作,响应序列化,网络可达性监控和安全性,以及要求经营管理的常见模式。

GET请求

1
2
3
4
5
6
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:@"http://example.com/resources.json" parameters:nil success:^(AFHTTPRequestOperation*operation, id responseObject) {
NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError*error) {
NSLog(@"Error: %@", error);
}];

POST的URL格式编码的请求

1
2
3
4
5
6
7
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = @{@"foo":@"bar"};
[manager POST:@"http://example.com/resources.json" parameters:parameters success:^(AFHTTPRequestOperation*operation, id responseObject) {
NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError*error) {
NSLog(@"Error: %@", error);
}];

POST多部分请求

1
2
3
4
5
6
7
8
9
10
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = @{@"foo":@"bar"};
NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
[manager POST:@"http://example.com/resources.json" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:filePath name:@"image" error:nil];
} success:^(AFHTTPRequestOperation *operation,id responseObject) {
NSLog(@"Success: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError*error) {
NSLog(@"Error: %@", error);
}];

AFURLSessionManager

AFURLSessionManager创建和管理一个NSURLSession根据指定的对象NSURLSessionConfiguration对象,这符合

创建下载任务

1
2
3
4
5
6
7
8
9
10
11
12
13
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://example.com/download.zip"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL*(NSURL *targetPath, NSURLResponse *response) {
NSURL *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES) firstObject]];
return [documentsDirectoryPath URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL*filePath, NSError *error) {
NSLog(@"File downloaded to: %@", filePath);
}];
[downloadTask resume];

创建上传任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse*response, id responseObject, NSError*error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"Success: %@ %@", response, responseObject);
}
}];
[uploadTask resume];

创建上传任务的多部分请求,与进展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:[NSURL fileURLWithPath:@"file://path/to/image.jpg"] name:@"file" fileName:@"filename.jpg" mimeType:@"image/jpeg" error:nil];
} error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSProgress *progress = nil;
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse*response, id responseObject, NSError*error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"%@ %@", response, responseObject);
}
}];
[uploadTask resume];

创建数据任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse*response, id responseObject, NSError*error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"%@ %@", response, responseObject);
}
}];
[dataTask resume];

请求序列化

请求序列化创建URL字符串,编码参数作为一个查询字符串或HTTP主体请求。

1
2
NSString *URLString = @"http://example.com";
NSDictionary *parameters = @{@"foo":@"bar", @"baz": @[@1,@2, @3]};

查询字符串参数编码

1
2
[[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:URLString parameters:parameters];
GET http://example.com?foo=bar&baz[]=1&baz[]=2&baz[]=3

URL,表单参数编码

1
2
3
4
5
6
[[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters];
POST http://example.com/
Content-Type: application/x-www-form-urlencoded
foo=bar&baz[]=1&baz[]=2&baz[]=3

JSON编码参数

1
2
3
4
5
[[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters];
POST http://example.com/
Content-Type: application/json
{"foo": "bar", "baz": [1,2,3]}

网络可达性管理

AFNetworkReachabilityManager监控领域的可达性,并为WWAN和WiFi网络接口的地址。

共享网络可达性

1
2
3
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));
}];

与基本URL的HTTP经理

当baseURL提供,网络可达性的作用范围是该基地URL的主机。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
NSURL *baseURL = [NSURL URLWithString:@"http://example.com/"];
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:baseURL];
NSOperationQueue *operationQueue = manager.operationQueue;
[manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusReachableViaWWAN:
case AFNetworkReachabilityStatusReachableViaWiFi:
[operationQueue setSuspended:NO];
break;
case AFNetworkReachabilityStatusNotReachable:
default:
[operationQueue setSuspended:YES];
break;
}
}];

安全策略

AFSecurityPolicy评估对固定X.509证书和通过安全连接的公共密钥服务器信任。
新增固定SSL证书到你的应用有助于防止人在这方面的中间人攻击和其他安全漏洞。 应用程序处理敏感的客户数据或财务信息我们强烈建议路线在使用SSL钉扎配置和启用HTTPS连接的所有通信。
使无效的SSL证书

1
2
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.securityPolicy.allowInvalidCertificates =YES; // 不建议在生产

AFHTTPRequestOperation

AFHTTPRequestOperation是的一个子类AFURLConnectionOperation使用HTTP或HTTPS协议请求。 它封装的接受状态代码和内容类型,这决定了请求的成功或失败的概念。

虽然AFHTTPRequestOperationManager通常是去提出要求的最佳途径, AFHTTPRequestOperation可以单独使用。

GET with AFHTTPRequestOperation

1
2
3
4
5
6
7
8
9
10
NSURL *URL = [NSURL URLWithString:@"http://example.com/resources/123.json"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer = [AFJSONResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation*operation, id responseObject) {
NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError*error) {
NSLog(@"Error: %@", error);
}];
[[NSOperationQueue mainQueue] addOperation:op];

操作的批处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
NSMutableArray *mutableOperations = [NSMutableArray array];
for (NSURL *fileURL in filesToUpload) {
NSURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:fileURL name:@"images[]" error:nil];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[mutableOperations addObject:operation];
}
NSArray *operations = [AFURLConnectionOperation batchOfRequestOperations:@[...] progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
NSLog(@"%lu of %lu complete", numberOfFinishedOperations, totalNumberOfOperations);
} completionBlock:^(NSArray *operations) {
NSLog(@"All operations in batch complete");
}];
[[NSOperationQueue mainQueue] addOperations:operations waitUntilFinished:NO];

单元测试

AFNetworking包括一套内部的测试子目录中的单元测试。 为了运行单元测试,你必须通过CocoaPods安装测试的依赖关系:

$ cd Tests

$ pod install

一旦测试的依赖安装,你可以通过在Xcode的’的iOS测试“和”OS X的测试“计划,执行测试套件。

使用xctool

测试也可以通过命令行或在一个持续集成环境中运行xctool ,它可以安装自制软件 :

$ brew update

$ brew install xctool —HEAD

一旦xctool安装,你可以通过执行该套件rake test 。