1、常见的NSFileManager文件方法

-(NSData *)contentsAtPath:path  //从一个文件读取数据

-(BOOL)createFileAtPath: path contents:(NSData *)data attributes:attr  //向一个文件写入数据

-(BOOL)removeItemAtPath:path error:err  //删除一个文件

-(BOOL)moveItemAtPath:from toPath:to error:err  //重命名或者移动一个文件(to不能是已存在的)

-(BOOL)copyItemAtPath:from toPath:to error:err  //复制文件(to不能是已存在的)

-(BOOL)contentsEqualAtPath:path andPath:path2  //比较两个文件的内容

-(BOOL)fileExistAtPath:path  //测试文件是否存在

-(BOOL)isReadableFileAtPath:path  //测试文件是否存在,并且是否能执行读操作  

-(BOOL)isWriteableFileAtPath:path  //测试文件是否存在,并且是否能执行写操作  

-(NSDictionary *)attributesOfItemAtPath:path error:err  //获取文件的属性  

-(BOOL)setAttributesOfItemAtPath:attr error:err  //更改文件的属性

2.使用目录

-(NSString *)currentDirectoryPath  //获取当前目录

-(BOOL)changeCurrentDirectoryPath:path  //更改当前目录

-(BOOL)copyItemAtPath:from toPath:to error:err  //复制目录结构(to不能是已存在的)

-(BOOL)createDirectoryAtPath:path withIntermediateDirectories:(BOOL)flag attribute:attr  //创建一个新目录

-(BOOL)fileExistAtPath:path isDirectory:(BOOL*)flag  //测试文件是不是目录(flag中储存结果YES/NO)

-(NSArray *)contentsOfDirectoryAtPath:path error:err  //列出目录内容

-(NSDirectoryEnumerator *)enumeratorAtPath:path  //枚举目录的内容

-(BOOL)removeItemAtPath:path error:err  //删除空目录

-(BOOL)moveItemAtPath:from toPath:to error:err   //重命名或移动一个目录(to不能是已存在的)

3、常用路径工具方法

+(NSString *)pathWithComponens:components  //根据components中的元素构造有效路径

-(NSArray *)pathComponents  //析构路径,获得组成此路径的各个部分

-(NSString *)lastPathComponent  //提取路径的最后一个组成部分

-(NSString *)pathExtension  //从路径的最后一个组成部分中提取其扩展名

-(NSString *)stringByAppendingPathComponent:path  //将path添加到现有路径的末尾

-(NSString *)stringByAppendingPathExtension:ext  //将指定的扩展名添加到路径的最后一个组成部分

-(NSString *)stringByDeletingLastPathComponent  //删除路径的最后一个组成部分

-(NSString *)stringByDeletingPathExtension  //从文件的最后一部分删除扩展名

-(NSString *)stringByExpandingTileInPath   //将路径中代字符扩展成用户主目录(~)或指定用户的主目录(~user)

-(NSString *)stringByresolvingSymlinksInPath  //尝试解析路径中的符号链接

-(NSString *)stringByStandardizingPath  //通过尝试解析~、..(父目录符号)、.(当前目录符号)和符号链接来标准化路径

4、常用的路径工具函数

NSString* NSUserName(void)  //返回当前用户的登录名

NSString* NSFullUserName(void)  //返回当前用户的完整用户名

NSString* NSHomeDirectory(void)  //返回当前用户主目录的路径

NSString NSHomeDirectoryForUser(NSString user)  //返回用户user的主目录

NSString* NSTemporaryDirectory(void)  //返回可用于创建临时文件的路径目录

5、常用的IOS目录

Documents(NSDocumentDirectory)  //用于写入应用相关数据文件的目录,在ios中写入这里的文件能够与iTunes共享并访问,存储在这里的文件会自动备份到云端

Library/Caches(NSCachesDirectory)  //用于写入应用支持文件的目录,保存应用程序再次启动需要的信息。iTunes不会对这个目录的内容进行备份

tmp(use NSTemporaryDirectory())  //这个目录用于存放临时文件,只程序终止时需要移除这些文件,当应用程序不再需要这些临时文件时,应该将其从这个目录中删除

Library/Preferences  //这个目录包含应用程序的偏好设置文件,使用 NSUserDefault类进行偏好设置文件的创建、读取和修改

在 UIView 中有一个autoresizingMask的属性,它对应的是一个枚举的值(如下),属性的意思就是自动调整子控件与父控件中间的位置,宽高。

1
2
3
4
5
6
7
8
9
enum {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};

UIViewAutoresizingNone就是不自动调整。
UIViewAutoresizingFlexibleLeftMargin 自动调整与superView左边的距离,保证与superView右边的距离不变。
UIViewAutoresizingFlexibleRightMargin 自动调整与superView的右边距离,保证与superView左边的距离不变。
UIViewAutoresizingFlexibleTopMargin 自动调整与superView顶部的距离,保证与superView底部的距离不变。
UIViewAutoresizingFlexibleBottomMargin 自动调整与superView底部的距离,也就是说,与superView顶部的距离不变。
UIViewAutoresizingFlexibleWidth 自动调整自己的宽度,保证与superView左边和右边的距离不变。
UIViewAutoresizingFlexibleHeight 自动调整自己的高度,保证与superView顶部和底部的距离不变。
UIViewAutoresizingFlexibleLeftMargin |UIViewAutoresizingFlexibleRightMargin 自动调整与superView左边的距离,保证与左边的距离和右边的距离和原来距左边和右边的距离的比例不变。

PendulemView

1
2
3
pendulum = [[PendulumView alloc] initWithFrame:self.view.bounds ballColor:ballColor ballDiameter:35];
pendulum.hidesWhenStopped = NO;
[self.view addSubview:pendulum];

SONFillAnimation是将一个UIView以指定网格动画显示的类。

用法

1
2
3
4
5
6
SONFillAnimation *animation = [[SONFillAnimation alloc] initWithNumberOfRows:3 columns:3 animationType:SONFillAnimationTypeDefault];
animation.direction = SONFillAnimationDirectionLeftToRightAndTopDown;
animation.duration = 0.3;
animation.xDelay = 0.1;
animation.yDelay = 0.2;
[animation animateView:view completion:^{}];

numberOfRows指行数,numberOfColumns指列数
xDelay指横向网格之间延迟的属性,yDelay指纵向网格之间延迟的属性
anchorPoint指定每个网格的锚点
direction指定顺序方向

您可以指定以下其中一个方向:

  • SONFillAnimationDirectionLeftToRightAndTopDown
  • SONFillAnimationDirectionLeftToRightAndBottomUp
  • SONFillAnimationDirectionRightToLeftAndTopDown
  • SONFillAnimationDirectionRightToLeftAndBottomUp
  • SONFillAnimationDirectionRandom

animationType是一个属性,表示一个类型的动画。

您可以指定在以下的animationType:

  • SONFillAnimationTypeDefault
  • SONFillAnimationTypeFoldOut
  • SONFillAnimationTypeFoldIn
  • SONFillAnimationTypeCustom

setRotationVector:::是定义为FoldIn/折页动画旋转向量的方法。如果动画类型是自定义的,就不需要设置这个值。默认值是(0,-1,0)。

在Podfile中添加

1
pod 'AVOSCloud'

使用UI相关的相关功能,就添加

1
pod 'AVOSCloundUI'

SNS组件的相关功能,就添加

1
pod 'AVOSCloundSNS'

AppDelegate.m文件,添加下列导入语句到头部

1
# import <AVOSClound/AVOSCloud.h>;

application:didFinishLaunchingWithOptions函数内添加

1
[AVOSClound setApplicationId:@"" clientKey:@""];

要跟踪应用的打开情况,添加下列代码

1
[AVAnalytics trackAppOpenedWithLaunchOptions:launchOptions];

对象

AVObject

在AVOS Cloud上,数据存储是围绕AVObject进行的。每个AVObject都包含了与JSON兼容的key-value对应的数据。数据是schema-free的,不需要在每个AVObject上提前制定存在哪些键,只要直接设定对应的key-value即可。
key必须是字母数字或下划线组成的字符串,自定义的键不能以__开头。值可以是字符串、数字、布尔值、甚至是数组和字典。
注意:在iOS SDK中,uuid是保留字段,不能作为key来使用。

保存对象

1
2
3
4
5
AVObject *gameScore = [AVObject objectWithClassName:@"GameScore"];
[gameScore setObject:[NSNumber numberWithInt:1337] forKey:@"score"];
[gameScore setObject:@"Steve" forKey:@"playerName"];
[gameScore setObject:[NSNumber numberWithBool:NO] forKey:@"cheatMode"];
[gameScore save];

setDesignResolutionSize(with,height,resolutionPolicy)
适配模式:

  • EXACT_FIT 游戏所有内容全部拉伸,内容铺满
  • NO_BORDER 一个方向上铺满屏幕
  • SHOW_ALL 保证设计区域全部显示,但是可能会有黑边
  • FIXED_WIDTH 保证设计分辨率的宽度不变,根据屏幕分辨率修正设计分辨率的高度
  • FIXED_HEIGHT 保证设计分辨率的高度不变,根据屏幕分辨率修正设计分辨率的宽度

NSUserDefaults类提供了一个与默认系统进行交互的编程接口。

使用

创建一个user defaults

1
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

添加数据

1
[userDefaults setObject:nameField.text forKey:UserDefayltNameKey];

也可以是基本数据类型int、float、bool等,有相应的方法

1
[userDefaults setBool:YES forKey:UserDefaultBoolKey];

读取数据

1
2
[userDefaults objectForKey:UserDefaultNameKey];
[userDefaults boolForKey:UserDefaultBoolKey];

注:NSUserDefaults非常好用,并不需要用户在程序中设置NSUserDefaults的全局变量,需要在哪里使用NSUserDefaults的数据,那么就在哪里创建一个NSUserDefaults对象,然后进行读或者写操作。
针对同一个关键字对应的对象或者数据,可以对它进行重写,重写之后关键字就对应新的对象或者数据,旧的对象或者数据会被自动清理。

Cocos2d-x坐标系和Open GL坐标系相同,都是起源于笛卡尔坐标系。

笛卡尔坐标系

笛卡尔坐标系中定义右手系原点在左下角,x向右,y向上,z向外

屏幕坐标系和Cocos2d坐标系

iOS、Android、Windows Phone在开发应用时使用的是标准屏幕坐标系,原点为屏幕左上角,x向右,y向下。

世界坐标系(World Coordinate)和本地坐标系(Node Local)

世界坐标系也叫绝对坐标系,是游戏开发中建立的概念,因此,“世界”指游戏世界。Cocos2d中的元素是由父子关系的层级结构,我们通过Node的setPosition设定元素的位置使用的就是相对与父类节点的本地坐标系而非世界坐标系。

本地坐标系也叫相对坐标系,是和节点相关联的坐标系。每个节点都有独立的坐标系,当节点移动或改变方向时,和该节点关联的坐标系将随之移动或改变方向。

锚点(Anchor Point)

  • Anchor Point的两个参数都在0~1之间。它们表示的并不是像素点,而是乘数因子。(0.5, 0.5)表示Anchor Point位于节点长度乘0.5和宽度乘0.5的地方,即节点的中心

  • 在Cocos2d-x中Layer的Anchor Point为默认值(0, 0),其他Node的默认值为(0.5, 0.5)。
    我们用以下代码为例,使用默认Anchor Point值,将红色层放在屏幕左下角,绿色层添加到红色层上:

    1
    2
    3
    4
    auto red = LayerColor::create(Color4B(255,100,100,128),visibleSize.width/2,visibleSize.height/2);
    auto green = LayerColor::create(Color4B(100,255,100,128),visibleSize.width/4,visibleSize.height/4);
    red->addChild(greeen);
    this->addChild(red,0);

我们用以下代码为例,将红色层的Anchor Point设为中点放在屏幕中央,绿色层添加到红色层上,绿色层锚点为右上角:

注:因为Layer比较特殊,它默认忽略锚点,所以要调用ignoreAnchorPointForPosition()接口来改变锚点,关于ignoreAnchorPointForPosition()接口的使用说明,我们将在后面详细讲解。

1
2
3
4
5
6
7
8
9
10
11
auto red = LayerColor::create(Color4B(255, 100, 100, 128), visibleSize.width/2, visibleSize.height/2);
red->ignoreAnchorPointForPosition(false);
red->setAnchorPoint(Point(0.5, 0.5));
red->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

auto green = LayerColor::create(Color4B(100, 255, 100, 128), visibleSize.width/4, visibleSize.height/4);
green->ignoreAnchorPointForPosition(false);
green->setAnchorPoint(Point(1, 1));
red->addChild(green);

this->addChild(red, 0);

忽略锚点(Ignore Anchor Point)

Ignore Anchor Point全称是ignoreAnchorPointForPosition,作用是将锚点固定在一个地方。

如果设置其值为true,则图片资源的Anchor Pont固定为左下角,否则即为所设置的位置。

我们用以下代码为例,将两个层的ignoreAnchorPointForPosition设为true,并将绿色的层添加到红色的层上:

1
2
3
4
5
6
7
8
9
10
auto red = LayerColor::create(Color4B(255, 100, 100, 128), visibleSize.width/2, visibleSize.height/2);
red->ignoreAnchorPointForPosition(true);
red->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

auto green = LayerColor::create(Color4B(100, 255, 100, 128), visibleSize.width/4, visibleSize.height/4);
green->ignoreAnchorPointForPosition(true);

red->addChild(green);

this->addChild(red, 0);

VertexZ,PositionZ和zOrder

  • VerextZ是OpenGL坐标系中的Z值
  • PositionZ是Cocos2d-x坐标系中Z值
  • zOrder是Cocos2d-x本地坐标系中Z值
    在实际开发中我们只需关注zOrder。

可以通过setPositionZ接口来设置PositionZ。

以下是setPositionZ接口的说明:

1
Sets the 'z' coordinate in the position. It is the OpenGL Z vertex value.

即PositionZ的值即为opengl的z值VertexZ。同样节点的PositionZ也是决定了该节点的渲染顺序,值越大,但是与zOrder不同的区别在于,PositionZ是全局渲染顺序即在根节点上的渲染顺序,而zOrder则是局部渲染顺序,即该节点在其父节点上的渲染顺序,与Node的层级有关。用以下事例来说明:

1
2
3
4
5
6
7
8
9
10
11
auto red = LayerColor::create(Color4B(255, 100, 100, 255), visibleSize.width/2, visibleSize.height/2);
red->ignoreAnchorPointForPosition(false);
red->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));

auto green = LayerColor::create(Color4B(100, 255, 100, 255), visibleSize.width/4, visibleSize.height/4);
green->ignoreAnchorPointForPosition(false);
green->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2 - 100));
red->setPositionZ(1);
green->setPositionZ(0);
this->addChild(red, 0);
this->addChild(green, 1);

触摸点(Touch position)

在处理触摸事件时需要重写以下四个函数:

1
2
3
4
virtual bool onTouchBegan(Touch *touch,Event *event);
virtual void onTouchEnded(Touch *touch,Event *event);
virtual void onTouchCancel(Touch *touch,Event *event);
virtual void onTouchMoved(Touch *touch,Event *event);

在函数中获取到touch,在设计游戏逻辑时需要用到触摸点在Cocos2d坐标系中的位置,就需要将touch的坐标转换成OpenGL坐标系中的点坐标。

Touch position是屏幕坐标系中的点,OpenGL postion是cocos2d-x用到OpenGL坐标系上的点坐标,通常我们在开发中会使用两个接口getLocation()和getLocationInView()来进行相应坐标转换工作。

在开发中一班使用getLocation()获取触摸点的GL坐标,而getLocationo()内部实现是通过Director::getInstance()->convertToGL(_point);返回GL坐标。

此外,关于世界坐标系和本地坐标系的互相转换,在Node中定义了以下四个常用的坐标转换的相关方法。

1
2
3
4
5
6
7
8
// 把基于当前节点的本地坐标系下的坐标转换到世界坐标系中
Point convertToNodeSpace(const Point& worldPoint) const;
// 把世界坐标转换到当前节点的本地坐标系中
Point convertToWorldSpace(const Point& nodePoint) const;
// 基于Anchor Point把基于当前节点的本地坐标系下的坐标转换到
Point convertToNodeSpaceAR(const Point& worldPoint) const;
// 基于Anchor Point把世界坐标转换到当前节点的本地坐标系中
Point convertToWorldSpaceAr(const Point& nodePoint) const;

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
auto *sprite1 = Sprite::create("HelloWorld.png");
sprite1->setPosistion(ccp(20,40));
sprite1->setAnchorPoint(ccp(0,0));
this->addChild(sprite1);// 此时添加到的是世界坐标系,也就是OpenGL坐标系

auto *sprite2 = Sprite::create("HelloWorld");
sprite2->setPosition(ccp(-5,-20));
sprite2->setAnchorPoint(ccp(1,1));
this->addChild(sprite2);// 此时添加到的是世界坐标系,也就是OpenGL坐标系

//将sprite2这个节点的坐标ccp(5,-20)转换成sprite1节点下的本地坐标系统的位置坐标
Point point1 = sprite1->convertToNodeSpace(sprite1->getPosition());
Point point2 = sprite->convertToWorldSpce(sprite2->getPosition());
// 将sprite2这个节点的坐标ccp(5,-20)转换成sprite1节点下的世界坐标系统的位置坐标
log("postion = (%f,%f)",point1.x,point1.y);
log("postion = (%f,%f)",point2.x,point2.y);


其中:Point point1 = sprite1->convertToNodeSpace(sprite2->getPosition());

相当于sprite2这个节点添加到(实际没有添加,只是这样理解)sprite1这个节点上,那么就需要使用sprite1这个节点的节点坐标系统,这个节点的节点坐标系统的原点在(20,40),而sprite1的坐标是(-5,-20),那么经过变换之后,sprite1的坐标就是(-25,-60)。

其中:Point point2 = sprite1->convertToWorldSpace(sprite2->getPosition());

此时的变换是将sprite2的坐标转换到sprite1的世界坐标系下,而其中世界坐标系是没有变化的,始终都是和OpenGL等同,只不过sprite2在变换的时候将sprite1作为了”参照“而已。所以变换之后sprite2的坐标为:(15,20)。


AFNetworking是一个非常流行的网络库,适用于iOS以及Mac OS X,具有良好的架构,丰富的api,以及模块化化构建方式,使得使用起来非常轻松。

使用CocoaPods安装

Podfile

1
2
platform :ios, '7.0'
pod "AFNetworking", "~> 2.0"

环境要求

Xcode 5、iOS 6.0及以上、Mac OS 10.8以上

用法

AFHTTPRequestOperationManager

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请求

1
2
3
4
5
6
7
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = @{@"foo":@"bar"};
[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多部分请求

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:parametes construtingBodyWithBlock:^(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根据指定的NSURLSessionConfiguration对象创建、管理NSURLSession,实现了<NSURLSessionTaskDelegate><NSURLSessionDataDelegate><NSURLSessionDownloadDelegate><NSURLSessionDelegate>委托。

创建下载任务

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
NSMutableURLRequest *requst = [[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] initWithSessionConfigguration:[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
15
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];
[ dataTask 简历];

请求序列化

创建序列化URL字符串

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

查询参数列表

1
[[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
[[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters];
  POST http://example.com/
Content-Type: application/json

{"foo": "bar", "baz": [1,2,3]}

网络可达性管理

AFNetworkReachabilityManager监控网络的可达性。

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

可达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;
}
}];


这个类只有三个类方法+ (void) resetCache+ (void) setObject:(NSData *)data forKey:(NSString *)key+ (id) objectForKey:(NSString *)key
resetCache:清空当前的缓存
setObject:(NSData *)data forKey:(NSString *)key:根据Key保存data到缓存中
objectForKey:(NSString *)key:根据Key从缓存中获取data

方法实现

首先我们需要实现一个方法,该方法用于返回缓存的完整目录
核心的代码为NSArray* paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);用于获取沙盒内的缓存目录

1
2
3
4
5
6
7
+ (NSString *) cacheDirectory {
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString* cacheDirectory = [paths objectAtIndex:0];
// 添加目录后缀
cacheDirectory = [cacheDirectory stringByAppendingPathComponent:@"ZTCaches"];
return cacheDirectory;
}

清空缓存也相对容易,只要把该目录的文件删除即可

1
2
3
+ (void) resetCache {
[[NSFileManager defaultManager] removeItemAtPath:[ZTCache cacheDirectory] error:nil];
}

根据Key将data存入缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+ (void) setObject:(NSData *)data forKey:(NSString *)key{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *filename = [self.cacheDirectory stringByAppendingPathComponent:key];
BOOL isDir = YES;
// 如果缓存目录不存在需要创建缓存目录
if (![fileManager fileExistsAtPath:self.cacheDirectory isDirectory:&isDir]) {
// 创建目录
[fileManager createDirectoryAtPath:self.cacheDirectory withIntermediateDirectories:NO attributes:nil error:nil];
}
NSError *error;
@try {
[data writeToFile:filename options:NSDataWritingAtomic error:&error];
}
@catch (NSException *exception) {
//
}
}

根据Key从缓存中获取data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
+ (NSData *) objectForKey:(NSString *)key{
NSFileManager* fileManager = [NSFileManager defaultManager];
// 根据目录和Key创建一个完整的fileName
NSString* filename = [self.cacheDirectory stringByAppendingPathComponent:key];
// 判断文件是否存在
if ([fileManager fileExistsAtPath:filename]) {
// 获取文件属性Dic,并取其中的最后修改时间属性
NSDate *modificationDate = [[fileManager attributesOfItemAtPath:filename error:nil] objectForKey:NSFileModificationDate];
// 如果最后修改时间与现在时间大于7天,删除文件
if ([modificationDate timeIntervalSinceNow] > cacheTime) {
[fileManager removeItemAtPath:filename error:nil];
}else{
// 从文件中读取data
NSData *data = [NSData dataWithContentsOfFile:filename];
return data;
}
}
return nil;
}

使用缓存类

根据实际需要,调用获取缓存,URL用MD5进行加工变为短连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- (void) loadImageFromURL:(NSString*)URL {
NSURL *imageURL = [NSURL URLWithString:URL];
NSString *key = [URL MD5Hash];
NSData *data = [ZTCache objectForKey:key];
// 如果存在将data传入imageView,否则添加一个异步任务
if (data) {
UIImage *image = [UIImage imageWithData:data];
_imageView.image = image;
} else {
_imageView.image = [UIImage imageNamed:@"img_def"];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSData *data = [NSData dataWithContentsOfURL:imageURL];
[ZTCache setObject:data forKey:key];
UIImage *image = [UIImage imageWithData:data];
dispatch_sync(dispatch_get_main_queue(), ^{
_imageView.image = image;
});
});
}
}

String+MD5实现如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- (NSString *) MD5Hash {

CC_MD5_CTX md5;
CC_MD5_Init (&md5);
CC_MD5_Update (&md5, [self UTF8String], (CC_LONG)[self length]);

unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5_Final (digest, &md5);
NSString *s = [NSString stringWithFormat: @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
digest[0], digest[1],
digest[2], digest[3],
digest[4], digest[5],
digest[6], digest[7],
digest[8], digest[9],
digest[10], digest[11],
digest[12], digest[13],
digest[14], digest[15]];

return s;

}

示例