ANF框架小结、网络概念步骤详情及开发源码

#import "MainViewController.h"

#import "AFNetworking.h"

#import "SSZipArchive.h"

 

@interfaceMainViewController () <NSXMLParserDelegate>

 

@property (strong, nonatomic) AFHTTPClient *httpClient;

 

// 操作队列

@property (strong, nonatomic) NSOperationQueue *queue;

 

// UIImageView

@property (weak, nonatomic) UIImageView *imageView;

// 进度条

@property (weak, nonatomic) UIProgressView *progress;

 

@end

 

@implementation MainViewController

/**

 ANF框架小结

 

 1. ANF是基于NSURLConnection的网络访问的封装;

 2. 使用方法

    1> NSURL

    2> NSURLRequest

    3> AFHttpRequestOperation

    4> 设置Operation的块代码

        上传进度

            setUploadProgressBlock

        下载进度

            setDownloadProgressBlock

        网络请求完成

            setCompletionBlockWithSuccess

        

        另外,如果是断点续传,需要用保存下载文件的路径设置NSOutputStream

 

    5> AFN框架,针对JSONXMLPListUIImageView都做了封装,使用起来相对简单

        而且将代码与出错处理部分分来,相对程序地逻辑更加清晰。

 

 3. 使用AFN框架的准备工作

    导入以下两个框架

 #import <SystemConfiguration/SystemConfiguration.h>

 #import <MobileCoreServices/MobileCoreServices.h>

 

    并且添加到pch文件中即可。

 

 . 网络概念

 

 1. Linux系统上,运行的Web服务器的名字叫做Apache

 2. 所有的http访问都是基于html或者相关的文件,例如:php,asp,jsp,asp.net

    这些文件最终都会转换成html供客户端使用,客户端就是我们写地程序或者浏览器

 3. form,在html页面中又称为表单,用来提交页面的,所有post请求的页面,至少会有一个表单

 

 4. get & postget是拿数据,post是将数据体放置在表中提交给服务器,然后再接收服务器的响应 

 

 

 . 解压缩,需要导入 libz.dylib

 

 第一个参数:要解压缩的文件

 第二个参数:要将zip文件解压缩到的位置

 [SSZipArchive unzipFileAtPath:downloadPath toDestination:docs[0]];

 

 . 删除zip文件,替用户节省空间

    使用文件管理器,可以查找文件、可以删除文件

 

 [[NSFileManager defaultManager]removeItemAtPath:downloadPath error:nil];

 */

 

- (void)viewDidLoad

{

    [superviewDidLoad];

    

    self.queue = [[NSOperationQueuealloc]init];

 

    // 1. 检测联网状态

    UIButton *button1 = [UIButtonbuttonWithType:UIButtonTypeRoundedRect];

    [button1 setFrame:CGRectMake(110, 200, 100, 40)];

    [button1 setTitle:@"连接状态" forState:UIControlStateNormal];

    [button1 addTarget:selfaction:@selector(reachability) forControlEvents:UIControlEventTouchUpInside];

    

    [self.view addSubview:button1];

    

    // 2. JSON

    UIButton *button2 = [UIButtonbuttonWithType:UIButtonTypeRoundedRect];

    [button2 setFrame:CGRectMake(110, 250, 100, 40)];

    [button2 setTitle:@"JSON"forState:UIControlStateNormal];

    [button2 addTarget:selfaction:@selector(loadJSON) forControlEvents:UIControlEventTouchUpInside];

    

    [self.view addSubview:button2];

    

    // 3. XML

    UIButton *button3 = [UIButtonbuttonWithType:UIButtonTypeRoundedRect];

    [button3 setFrame:CGRectMake(110, 300, 100, 40)];

    [button3 setTitle:@"XML"forState:UIControlStateNormal];

    [button3 addTarget:selfaction:@selector(loadXML) forControlEvents:UIControlEventTouchUpInside];

    

    [self.view addSubview:button3];

    

    // 4. UIImageView

    UIButton *button4 = [UIButtonbuttonWithType:UIButtonTypeRoundedRect];

    [button4 setFrame:CGRectMake(110, 350, 100, 40)];

    [button4 setTitle:@"UIImageView"forState:UIControlStateNormal];

    [button4 addTarget:selfaction:@selector(loadImageView) forControlEvents:UIControlEventTouchUpInside];

    

    [self.view addSubview:button4];

    

    UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(110, 50, 100, 100)];

    [self.view addSubview:imageView];

    self.imageView = imageView;

    

    // 5. 上传文件

    UIButton *button5 = [UIButtonbuttonWithType:UIButtonTypeRoundedRect];

    [button5 setFrame:CGRectMake(20, 400, 100, 40)];

    [button5 setTitle:@"上传图像" forState:UIControlStateNormal];

    [button5 addTarget:selfaction:@selector(uploadImage) forControlEvents:UIControlEventTouchUpInside];

    

    [self.view addSubview:button5];

    

    UIProgressView *progress = [[UIProgressView alloc]initWithFrame:CGRectMake(20, 20, 280, 20)];

    [self.view addSubview:progress];

    // 进度条的数值是以百分比的形式体现的

    self.progress = progress;

 

    // 6. 断点续传

    UIButton *button6 = [UIButtonbuttonWithType:UIButtonTypeRoundedRect];

    [button6 setFrame:CGRectMake(180, 400, 100, 40)];

    [button6 setTitle:@"下载zip"forState:UIControlStateNormal];

    [button6 addTarget:selfaction:@selector(download) forControlEvents:UIControlEventTouchUpInside];

    

    [self.view addSubview:button6];

}

 

#pragma mark 断点续传

// AFN的文件下载,本身就是断点续传,不需要指定什么参数

- (void)download

{

    // 1. NSURL

    NSString *urlStr = @"http://localhost/~apple/itcast/download/10-iOS高级28-数据存取05-CoreData.mp4";

    // 如果有中文或者空格,需要加百分号

    

    NSURL *url = [NSURLURLWithString:[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

    

    // 2. NSURLRequest

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    

    // 3. 定义Operation

    AFHTTPRequestOperation *op = [[AFHTTPRequestOperationalloc]initWithRequest:request];

    

    // 下载文件》要告诉op下载到哪里?

    // 输出流(数据在网络上都是以流的方式传输的)

    // 所谓输出流,就是让数据流流到哪里-》保存到沙箱

    NSArray *docs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    // 指定下载路径

    NSString *downloadPath = [docs[0]stringByAppendingPathComponent:@"download.zip"];

    

    [op setOutputStream:[NSOutputStreamoutputStreamToFileAtPath:downloadPath append:NO]];

    

    // 设置下载进度代码

    /**

     bytesRead      此次下载的字节数(5k)

     totalBytesRead 已经下载完成的字节数(80k)

     totalBytesExpectedToRead 文件总字节数(100k)

     */

    [op setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {

        

        float percent = (float)totalBytesRead / totalBytesExpectedToRead;

        NSLog(@"%f", percent);

        

        [self.progress setProgress:percent animated:YES];

    }];

    

    // 设置下载完成块代码

    [op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

        

        NSLog(@"下载完成");

        // 1. 进入沙箱检查下载文件

        

        // 2. 解压缩文件

        /*

         第一个参数:要解压缩的文件

         第二个参数:要将zip文件解压缩到的位置

         */

        [SSZipArchive unzipFileAtPath:downloadPath toDestination:docs[0]];

        

        // 3. 删除zip文件,替用户节省空间

        // 使用文件管理器,可以查找文件、可以删除文件

        [[NSFileManagerdefaultManager]removeItemAtPath:downloadPath error:nil];

        

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        NSLog(@"下载失败");

    }];

    

    [op start];

 

}

 

#pragma mark 上传图像

- (void)uploadImage

{

    // 1. 定义httpClient

    // 所谓baseURL就是此后所有的请求都基于此地址

    NSURL *url = [NSURLURLWithString:@"http://localhost"];

    AFHTTPClient *httpClient = [AFHTTPClient clientWithBaseURL:url];

    

    // 2. 根据httpClient生成post请求

    NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:@"POST"path:@"/~apple/itcast/upload.php"parameters:nilconstructingBodyWithBlock:^(id<AFMultipartFormData> formData) {

        

        // 提示:UIImage不能为空

        NSData *data = UIImagePNGRepresentation(self.imageView.image);

        

        /**

         参数说明:

         

         1. fileData:   要上传文件的数据

         2. name:       负责上传文件的远程服务中接收文件使用的字段名称

         3. fileName   要上传文件的文件名

         4. mimeType   要上传文件的文件类型

         

         提示,在日常开发中,如果要上传图片到服务器,一定记住不要出现文件重名的问题!

         这个问题,通常涉及到前端程序员和后端程序员的沟通。

         

         通常解决此问题,可以使用系统时间作为文件名!

         */

        // 1) 取当前系统时间

        NSDate *date = [NSDate date];

        // 2) 使用日期格式化工具

        NSDateFormatter *formatter = [[NSDateFormatteralloc]init];

        // 3) 指定日期格式

        [formatter setDateFormat:@"yyyyMMddHHmmss"];

        NSString *dateStr = [formatter stringFromDate:date];

        // 4) 使用系统时间生成一个文件名

        NSString *fileName = [NSString stringWithFormat:@"%@.png", dateStr];

        

        [formData appendPartWithFileData:data name:@"file"fileName:fileName mimeType:@"image/png"];

    }];

    

    // 准备做上传的工作!

    // 3. operation

    AFHTTPRequestOperation *op = [[AFHTTPRequestOperationalloc]initWithRequest:request];

 

    // 显示上传进度

    /*

     bytesWritten   本次上传的字节数(本次上传了5k)

     totalBytesWritten  已经上传的字节数(已经上传了80k)

     totalBytesExpectedToWrite  文件总字节数(100k

     */

    [op setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {

        

        [self.progress setProgress:(float)(totalBytesWritten / totalBytesExpectedToWrite)];

        

        NSLog(@"上传 %f", (float)(totalBytesWritten / totalBytesExpectedToWrite));

    }];

    

    [op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

       

        NSLog(@"上传文件成功");

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        NSLog(@"上传文件失败 %@", error);

    }];

    

    // 4. operation start

    [op start];

}

 

#pragma mark 加载UIImageView

// 提示:如果是异步加载表格图像,不建议使用此方法

// 还是需要使用图像的内存缓存或者磁盘缓存的方式处理

// 此方法,仅适用于单张独立的图像,而不要在表格中使用

- (void)loadImageView

{

    UIImage *image = [UIImage imageNamed:@"头像1.png"];

    

    NSURL *url = [NSURLURLWithString:@"http://localhost/~apple/itcast/images/head2.png"];

    

    [self.imageViewsetImageWithURL:url placeholderImage:image];

}

 

#pragma mark 加载XML

// 使用AFN加载XMLXML解析器的方法一个都不能少,还需要自己进行解析!

- (void)loadXML

{

    // 1. URL

    NSURL *url = [NSURLURLWithString:@"http://localhost/~apple/itcast/videos.php?format=xml"];

    

    // 2. Request

    NSURLRequest *request = [NSURLRequestrequestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicytimeoutInterval:1.0f];

    

    // 3. 加载XML

    [self.queuesetMaxConcurrentOperationCount:4];

    

    AFXMLRequestOperation *op = [AFXMLRequestOperation XMLParserRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLParser *XMLParser) {

        

        // 1. 实例化解析器,并传入数据 AFN已经做了 XMLParser

        // 2. 设置代理

        [XMLParser setDelegate:self];

        // 3. 解析器解析

        [XMLParser parse];

        

    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSXMLParser *XMLParser) {

        

        NSLog(@"%@", error.localizedDescription);

    }];

    

    // 启动操作

    // 提示,因为都是后台的数据处理,这些任务是可以放在后台线程中实现的

    [self.queue addOperation:op];

}

 

#pragma mark - XML解析器代理方法

// 1. 开始

- (void)parserDidStartDocument:(NSXMLParser *)parser

{

    NSLog(@"解析文档开始 %@", [NSThread currentThread]);

}

 

// 2. 开始节点

// 3. 发现节点元素

// 4. 结束节点

// 5. 结束

// 6. 出错

 

#pragma mark 加载JSON

- (void)loadJSON

{

    // 1. URL

    NSURL *url = [NSURLURLWithString:@"http://10.0.0.1/~apple/itcast/videos.php?format=json"];

    

    // 2. Request

    NSURLRequest *request = [NSURLRequestrequestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicytimeoutInterval:1.0f];

    

    // 原生的方法

//    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * response, NSData *data, NSError *error) {

//        

//        // 1) 出错判断

//        

//        // 2) 反序列化

//        NSArray *array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];

//    }];

    

    // 3. Connection

    // 实例化操作对象

    AFJSONRequestOperation *op = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {

        

        NSLog(@"%@", JSON);

        NSArray *array = JSON;

        

        // 将加载的数组写入plist

        [array writeToFile:@"/users/apple/Desktop/123.plist"atomically:YES];

        

    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {

        

        NSLog(@"%@ %@", error.localizedDescription, JSON);

    }];

    

    // 启动操作

    [op start];

}

 

#pragma mark 检测联网状态

- (void)reachability

{

    // BaseURL在检测网络连接状态时,可以使用一些门户网站,例如:www.baidu.com

    NSURL *url = [NSURLURLWithString:@"http://www.baidu.com"];

    AFHTTPClient *httpClient = [AFHTTPClient clientWithBaseURL:url];

    self.httpClient = httpClient;

    

    [httpClient setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {

        

        switch (status) {

            caseAFNetworkReachabilityStatusNotReachable:

                NSLog(@"无连接");

                break;

            caseAFNetworkReachabilityStatusReachableViaWiFi:

                NSLog(@"WIFI连接");

                break;

            caseAFNetworkReachabilityStatusReachableViaWWAN:

                NSLog(@"3G连接");

                break;

            caseAFNetworkReachabilityStatusUnknown:

                NSLog(@"连接状态未知");

                break;

        }

    }];

}

 

@end

 

posted on 2013-12-21 23:08  林源  阅读(730)  评论(0编辑  收藏  举报

导航