iOS-raywenderlich翻译-AFNetworking速成教程

iOS-raywenderlich翻译-AFNetworking速成教程,第1张

概述注:本文由BeyondVincent(破船)翻译首发         转载请注明出处:http://blog.csdn.net/beyondvincent 腾讯微博:beyondvincent 新浪微博:beyondvincent 注:本文译自 http://www.raywenderlich.com/30445/afnetworking-crash-course 18 MARCH 2013 学习

注:本文由Beyondvincent(破船)翻译首发

        转载请注明出处:http://blog.csdn.net/beyondvincent

腾讯微博:beyondvincent

新浪微博:beyondvincent




注:本文译自 http://www.raywenderlich.com/30445/afnetworking-crash-course 18 marcH 2013


学习如何使用AFNetworking: iOS中使用起来非常方便的网络API!

本文是由 iOS Tutorial 小组成员 Scott Sherwood撰写,他是一个动态加载(Dynamically Loaded)(基于位置)软件公司(专业的混合定位)的共同创办人。 

网络 — 你的程序离开了它就不能生存下去!苹果Foundation framework中的NSURLConnection又非常难以理解,不过这里有一个可以使用的替代品:AFNetworking.

AFNetworking 非常受开发者欢迎 – 它赢得了我们读者的选择:2012年最佳的iOS library奖(2012 Best iOS Library Award.) 所以现在我就写这篇文章来向你介绍如何在程序中有效的使用它。

AFNetworking 包括了所有你需要与在线资源交互的内容,从web services到文件下载。当你的程序在下载一个大文件期间,AFNetworking还能确保你的UI是可以响应的。

本文将介绍AFNetworking框架主要的组成部分。一路上,你将使用World Weather Online提供的咨询(Feeds)来创建一个天气(Weather)程序。刚开始使用的天气数据是静态的,不过在学完本文内容之后,程序将连接到实时的天气咨询。

今日预计:一个很酷的开发者学习所有关于AFNetworking知识,并在他的程序中使用AFNetworking。我们开始忙活吧!

入门

首先来这里(here)下载本文的启动项目。这个工程提供了一个基本的UI — AFNetworking相关代码还没有添加。

打开MainStoryboard.storyboard文件,将看到3个vIEw controller:



从左到右,分别是:

顶级(top-level)的导航控制器; 用来显示天气的一个@R_301_5991@ vIEw controller,每天一行; 一个自定义的vIEw controller (WeatherAnimationVIEwController) 当用户点击某个@R_301_5991@ vIEw cell时,这个vIEw controller将显示某一天的天气咨询。

生成并运行项目,你将看到相关的UI出现,但是什么都没有实现!因为程序需要从网络中获取到所需要的数据,而相关代码还没有添加。这也是本文中你将要实现的!

首先,你需要将AFNetworking 框架包含到工程中。如果你还没有AFNetworking的话,在这里下载最新的版本:GitHub.

当你解压出下载的文件后,你将看到其中有一个AFNetworking子文件夹,里面全是.h 和 .m 文件,如下高亮显示的:



AFNetworking拖拽到Xcode工程中.



当出现了添加文件的选项时,确保勾选上copy items into destination group’s folder (if needed) 和 Create groups for any added folders.

要完成相关配置,请在工程的Supporting files群组中打开预编译头文件Weather-Prefix.pch. 然后在别的import后面添加如下一行代码:

#import "AFNetworking.h"

将AFNetworking添加到预编译头文件,意味着这个框架会被自动的添加到工程的所有源代码文件中。

很容易,不是吗?现在你已经准备好“天气”程序代码了!

*** 作JsON

AFNetworking通过网络来加载和处理结构化的数据是非常智能的,普通的http请求也一样。尤其是它支持JsON,XML 和 Property Lists (pLists).

你可以下载一些JsON数据,然后用自己的解析器来解析,但这何必呢?通过AFNetworking就可以完成这些 *** 作!Y

首先,你需要测试脚本(数据)所需的一个基本URL。将下面的这个静态Nsstring声明到WT@[email protected]顶部,也就是所有#import下面:

static NSString *const BaseURLString = @"http://www.raywenderlich.com/downloads/weather_sample/";

这个URL是一个非常简单的“web service”,在本文中我特意为你创建的。如果你想知道它看起来是什么样,可以来这里下载代码:download the source.

这个web service以3种不同的格式(JsON,XML 和 PList)返回天气数据。你可以使用下面的这些URL来看看返回的数据:

http://www.raywenderlich.com/downloads/weather_sample/weather.php?format=json http://www.raywenderlich.com/downloads/weather_sample/weather.php?format=xml http://www.raywenderlich.com/downloads/weather_sample/weather.php?format=plist (might not show up right in your browser)

第一个数据格式使用的是JSON. JsON 是一种常见的JavaScript派生类对象格式。看起来如下:

{    "data": {        "current_condition": [            {                "cloudcover": "16","humIDity": "59","observation_time": "09:09 PM",}        ]    }}

注意: 如果你想要结更多关于JsON内容,请参考:Working with JSON in iOS 5 Tutorial.

当用户点击程序中的JsON按钮时,你希望对从服务中获得的JsON数据进行加载并处理。在WT@[email protected]中,找到JsonTapped: 方法 (现在应该是空的) ,并用下面的代码替换:

- (IBAction)JsonTapped:(ID)sender {    // 1    *weatherUrl = [NSString stringWithFormat:"%@weather.PHP?format=Json",BaseURLString];    NSURL *url [NSURL URLWithString:weatherUrl];    NSURLRequest *request [NSURLRequest requestWithURL:url]// 2    AFJsONRequestoperation *operation =    [AFJsONRequestoperation JsONRequestoperationWithRequest:request        // 3        success:^(*request,NSHTTPURLResponse *response,ID JsON) {            self.weather  (NSDictionary *)JsON;            self.Title "JsON RetrIEved";            [self.@R_301_5991@VIEw reloadData];        }        // 4        failure*error,0)">{            UIAlertVIEw *av [[UIAlertVIEw alloc] initWithTitle"Error RetrIEving Weather"                                                         message"%@",error]                                                        delegate:nil                                               cancelbuttonTitle"OK" otherbuttonTitlesnil];            [av show}// 5    [operation start];}

这是你的第一个AFNetworking代码!因此,这看起来是全新的,我将对这个方法中代码进行介绍。

根据基本的URL构造出完整的一个URL。然后通过这个完整的URL获得一个NSURL对象,然后根据这个url获得一个NSURLRequest. AFJsONRequestoperation 是一个功能完整的类(all-in-one)— 整合了从网络中获取数据并对JsON进行解析。 当请求成功,则运行成功块(success block)。在本示例中,把解析出来的天气数据从JsON变量转换为一个字典(dictionary),并将其存储在属性 weather 中. 如果运行出问题了,则运行失败块(failure block),比如网络不可用。如果failure block被调用了,将会通过提示框显示出错误信息。

如上所示,AFNetworking的使用非常简单。如果要用苹果提供的APIs(如NSURLConnection)来实现同样的功能(下载和解析JsON数据),则需要许多代码才能做到。

现在天气数据已经存在于self.weather中,你需要将其显示出来。找到@R_301_5991@VIEw:numberOfRowsInSection: 方法,并用下面的代码替换:

(NSInteger)@R_301_5991@VIEw(UI@R_301_5991@VIEw )@R_301_5991@VIEw numberOfRowsInSection)section// Return the number of rows in the section.     if(!self.weather)        return 0switch (section{        case 0{            1;        }        1{            NSArray *upcomingWeather [self.weather upcomingWeather];            return [upcomingWeather countdefault:            0;    }}

@R_301_5991@ vIEw有两个section:第一个用来显示当前天气,第二个用来显示未来的天气。

等一分钟,你可能正在思考。这里的 [self.weather upcomingWeather]是什么? 如果self.weather是一个普通的NSDictionary,它是怎么知道 “upcomingWeather” 是什么呢?

为了更容易的解析数据,在starter工程中,有一对NSDictionary categorIEs:

NSDictionary+weather.m NSDictionary+weather_package.m

这些categorIEs添加了一些方便的方法,通过这些方法可以很方便的对字典中的数据元素进行访问。这样你就可以专注于网络部分,而不是NSDictionary中数据的访问。对吧?

回到 WT@[email protected],找到 @R_301_5991@VIEw:cellForRowAtIndexPath: 方法,并用下面的实现替换:

(UI@R_301_5991@VIEwCell )@R_301_5991@VIEw cellForRowAtIndexPath(NSIndexPath )indexPath{    *CellIDentifIEr "WeatherCell";    UI@R_301_5991@VIEwCell *cell [@R_301_5991@VIEw dequeueReusableCellWithIDentifIEr:CellIDentifIEr forIndexPath:indexPath];    *daysWeather;     (indexPath.section{            daysWeather [self.weather currentConditionbreak;        ];            daysWeather [upcomingWeather objectAtIndex:indexPath.rowbreak;    }     cell.textLabel.text [daysWeather weatherDescription// maybe some code will be added here later...     return cell;}

跟tableView:numberOfRowsInSection: 方法一样,在这里使用了便利的NSDictionary categories来获得数据。当前天的天气是一个字典,而未来几日的天气则存储在一个数组中。

生成并运行工程,然后点击JSON按钮. 这将会动态的获得一个AFJSONOperation对象,并看到如下画面内容:



JsON *** 作成功!

*** 作Property Lists(pLists)

Property Lists (或简称为 pLists) 是以确定的格式(苹果定义的)构成的XML文件。苹果一般将pLists用在用户设置中。看起来如下:

 <dict>  <key>data</key>  <dict>    <key>current_condition</key>      <array>      <dict>        <key>cloudcover</key>        <string>16</string>        <key>humIDity</key>        <string>59</string>

上面的意思是:

一个字典中有一个名为“data”的key,这个key对应着另外一个字典。 这个字典有一个名为 “current_condition” 的key,这个key对应着一个array. 这个数组包含着一个字典,字典中有多个key和values。比如cloudcover=16和humIDity=59.

现在是时候加载pList版本的天气数据了!找到pListTapped: 方法,并用下面的实现替换:

 -)pListTapped)sender{    "%@weather.php?format=plist",0)">];     AFPropertyListRequestOperation [AFPropertyListRequestOperation propertyListRequestOperationWithRequest:request        successid propertyList)propertyList;            self.title "PLIST Retrieved";            }        failure"Error Retrieving Weather"                              message"OK"                                               otherButtonTitles];    ]}

注意到,上面的代码几乎与JSON版的一致,只不过将 *** 作(operation)的类型从AFJSONOperation 修改为 AFPropertyListOperation. 这非常的整齐:你才程序只需要修改一丁点代码就可以接收JSON或plist格式的数据了!

生成并运行工程,然后点击PLIST按钮。将看到如下内容:



如果你需要重置所有的内容,以重新开始 *** 作,导航栏顶部的Clear按钮可以清除掉Title和@R_301_5991@ vIEw中的数据。


*** 作XML

AFNetworking处理JsON和pList的解析使用的是类似的方法,并不需要花费太多功夫,而处理XML则要稍微复杂一点。下面,就根据XML咨询构造一个天气字典(NSDictionary)。

iOS提供了一个帮助类:NSXMLParse (如果你想了解更多内容,请看这里的链接:SAX parser).

还是在文件xmlTapped: 方法,并用下面的实现替换:

)xmlTapped"%@weather.PHP?format=xml",0)">];     AFXMLRequestoperation [AFXMLRequestoperation XMLParserRequestoperationWithRequest*XMLParser{            //self.xmlWeather = [NSMu@R_301_5991@Dictionary dictionary];            XMLParser.delegate = self;            [XMLParser setShouldProcessnamespacesYES[XMLParser parse}

到现在为止,这看起来跟之前处理JsON和pList很类似。最大的改动就是在成功块(success block)中,在这里不会传递给你一个预处理好的NSDictionary对象. 而是AFXMLRequestoperation实例化的NSXMLParse对象,这个对象将用来处理繁重的XML解析任务。

NSXMLParse对象有一组delegate方法是你需要实现的 — 用来获得XML数据。注意,在上面的代码中我将XMLParser的delegate设置为self,因此WT@R_301_5991@VIEwController将用来处理XML的解析任务。

首先,更新一下WT@[email protected] 并修改一下类声明,如下所示:

@interface WT@R_301_5991@VIEwController : UI@R_301_5991@VIEwController<NSXMLParserDelegate>

上面代码的意思是这个类将实现(遵循)NSXMLParserDelegate协议. 下一步将下面的delegate方法声明添加到@implementation后面:

voID)parser()parser didStartElement()elementName namespaceURI)namespaceURI qualifiedName)qName attributes)attributeDict;)parser foundCharacters)string;)parser didEndElement)qName;) parserDidEndDocument)parser;

为了支持咨询的解析,还需要一些属性来存储相关的数据。将下面的代码添加到@implementatio后面:

@property(strong) NSMutableDictionary *xmlWeather; //package containing the complete response*currentDictionary; //current section being parsed) *previousElementName;*elementName;) NSMutableString *outstring;

接着打开WT@[email protected],现在你需要一个一个的实现上面所说的几个delegate方法。将下面这个方法粘贴到实现文件中:

)attributeDict  {    self.prevIoUsElementname = self.elementname;     if (qname{        self.elementname = qname;    }     [qname isEqualToString"current_condition"]){        self.currentDictionary [NSMutableDictionary dictionary}    else "weather""request"}     self.outstring [NSMutableString string}

当NSXMLParser发现了新的元素开始标签时,会调用上面这个方法。在这个方法中,在构造一个新字典用来存储赋值给currentDictionary属性之前,首先保存住上一个元素名称。还要将outstring重置一下,这个字符串用来构造XML标签中的数据。

然后将下面这个方法粘贴到上一个方法的后面:

string !self.elementnamereturn;    }     [self.outstring appendFormat}

如名字一样,当NSXMLParser在一个XML标签中发现了字符数据,会调用这个方法。该方法将字符数据追加到outstring属性中,当XML标签结束的时候,这个outstring会被处理。

继续,将下面这个方法粘贴到上一个方法的后面:

)qname {     // 1    ] ||       {        [self.xmlWeather setobject[NSArray arrayWithObject:self.currentDictionary] forKey:qname];        self.currentDictionary = nil;    }    // 2    {         // Initalise the List of weather items if it dosnt exist        NSMutableArray *array [self.xmlWeather objectForKey];        !array)            array [NSMutableArray array][array addobject:array forKey];         self.currentDictionary // 3    "value"{        //Ignore value Tags they only appear in the two conditions below    // 4    "weatherDesc"] ||            "weatherIconUrl"[self.currentDictionary setobject[NSDictionary dictionaryWithObject:self.outstring forKey// 5    else } 	self.elementname nil;}

当检测到元素的结束标签时,会调用上面这个方法。在这个方法中,会查找一些标签:

urrent_condition 元素表示获得了一个今天的天气。会把今天的天气直接添加到xmlWeather字典中。 weather 元素表示获得了随后一天的天气。今天的天气只有一个,而后续的天气有多个,所以在此,将后续天气添加到一个数组中。 value 标签出现在别的标签中,所以这里可以忽略掉这个标签。 weatherDesc 和 weatherIconUrl 元素的值在存储之前,需要需要被放入一个数组中 — 这里的结构是为了与JsON和pList版本天气咨询格式相匹配。 所有其它元素都是按照原样(as-is)进行存储的。

下面是最有一个delegate方法!

)parser {    self.weather :self.xmlWeather forKey"data"];    self.Title "XML RetrIEved";    }

NSXMLParser解析到document的尾部时,会调用这个方法。在此,xmlWeather字典已经构造完毕,@R_301_5991@ vIEw可以重新加载了。

在上面代码中将xmlWeather添加到一个字典中,看起来是冗余的,不过这样可以确保与JsON和pList版本的格式完全匹配。这样所有的3种数据格式(JsON,pList和XML)都能够用相同的代码来显示!

@L_301_47@

现在所有的delegate方法和属性都搞定了,找到xmlTapped: 方法,并取消注释成功块(success block)中的一行代码:

{    ...    success// the line below used to be commented out        self.xmlWeather ];        XMLParser.delegate = self;    ...}

生成和运行工程,然后点击XML按钮,将看到如下内容:




未完待续 破船 2013-03-19 :]



一个小的天气程序

嗯,上面的这个程序看起来体验不太友好,有点像整周都是阴雨天。如何让@R_301_5991@ vIEw中的天气信息体验更好点呢?

再仔细看看之前的JsON格式数据:JSON format from before,你会看到每个天气项里面都有一个图片URLs。 将这些天气图片显示到每个@R_301_5991@ vIEw cell中,这样程序看起来会更有意思。

AFNetworking给UIImageVIEw添加了一个category,让图片能够异步加载,也就是说当图片在后台下载的时候,程序的UI界面仍然能够响应。为了使用这个功能,首先需要将这个category import到WT@[email protected]文件的顶部:

#import "UIImageVIEw+AFNetworking.h"

找到@R_301_5991@VIEw:cellForRowAtIndexPath: 方法,并将下面的代码粘贴到最后的return cell; 代码上上面(这里应该有一个注释标记)

 __weak UI@R_301_5991@VIEwCell *weakCell = cell; [cell.imageVIEw setimageWithURLRequestNSURLRequest alloc] initWithURL:daysWeather.weatherIconURL]                      placeholderImage[UIImage imagenamed"placeholder.png"]                               success*image{                                   weakCell.imageVIEw.image = image;                                    //only required if no placeholder is set to force the imagevIEw on the cell to be laID out to house the new image.                                   //if(weakCell.imageVIEw.frame.size.height==0 || weakCell.imageVIEw.frame.size.wIDth==0 ){                                   [weakCell setNeedsLayout];                                   //}                               }                               failure*error{                                ];

首先创建一个弱引用(weak)的cell,这样就可以在block中使用这个cell。如果你直接访问cell变量,Xcode会提示一个关于retain循环和内存泄露的警告。

UIImageVIEw+AFNetworking category定义了一个setimageWithURLRequest… 方法. 这个方法的参数包括:一个指向图片URL的请求,一个占位符图片,一个success block和一个failure block。

当cell首次被创建的时候,cell中的UIImageVIEw将显示一个占位符图片,直到真正的图片被下载完成。在这里你需要确保占位符的图片与实际图片尺寸大小相同。

如果尺寸不相同的话,你可以在success block中调用cell的setNeedsLayout方法. 上面代码中对两行代码进行了注释,这是因为这里的占位符图片尺寸正好合适,留着注释,可能在别的程序中需要用到。

现在生成并运行工程,然后点击之前添加的3个 *** 作中的任意一个,将看到如下内容:



很好! 异步加载图片从来没有这么简单过。

一个RESTful类

到现在你已经使用类似AFJsONRequestoperation这样的类创建了一次性的http请求。另外,较低级的AFhttpClIEnt类是用来访问单个的web service终端。 对这个AFhttpClIEnt一般是给它设置一个基本的URL,然后用AFhttpClIEnt进行多个请求(而不是像之前的那样,每次请求的时候,都创建一个AFhttpClIEnt

AFhttpClIEnt同样为编码参数、处理multipart表单请求body的构造、管理请求 *** 作和批次入队列 *** 作提供了很强的灵活性,它还处理了整套RESTful (GET,POST,PUT,和 DELETE),下面我们就来试试最常用的两个:GET 和 POST.

注意: 对REST,GET和POST不清楚?看看这里比较有趣的介绍 – 我如何给妻子解释REST(How I Explained REST to My Wife.)

WT@[email protected] 顶部将类声明按照如下修改:

: UI@R_301_5991@VIEwController<NSXMLParserDelegate,CLLocationManagerDelegate,UIActionSheetDelegate>

在 httpClIEntTapped: 方法,并用下面的实现替换:

)httpClIEntTapped{    UIActionSheet *actionSheet [UIActionSheet alloc"AFhttpClIEnt" delegate:self cancelbuttonTitle"Cancel" destructivebuttonTitlenil otherbuttonTitles"http POST","http GET",0)">[actionSheet showFrombarbuttonItem:sender animated}

上面的方法会d出一个action sheet,用以选择GET和POST请求。粘贴如下代码以实现action sheet中按钮对应的 *** 作:

)actionSheet(UIActionSheet )actionSheet clickedbuttonAtIndex)buttonIndex// 1    *baseURL :BaseURLString*parameters "json" forKey"format"// 2    AFHTTPClient *client [AFHTTPClient alloc] initWithBaseURL:baseURL[client registerHTTPOperationClass[AFJSONRequestOperation class[client setDefaultHeader"Accept" value"application/json"(buttonIndex==[client postPath"weather.php"              parameters:parameters                 success(AFHTTPRequestOperation *operation,144)">id responseObject{                     self.weather = responseObject;                     self.title "HTTP POST";                     ];                 }                 failure{                     UIAlertView "Error Retrieving Weather"                                                                  message]                                                                 delegatenil                                                        cancelButtonTitle];                     ]}         [client getPath"weather.php"             parameters:parameters                success{                    self.weather = responseObject;                    self.title "HTTP GET";                    ];                }                failure{                    UIAlertView "Error Retrieving Weather"                                                                 message]                                                                delegatenil                                                       cancelButtonTitle];                    ]}

上面的代码作用如下:

构建一个baseURL,以及一个参数字典,并将这两个变量传给AFHTTPClient. 将AFJSONRequestOperation注册为HTTP的 *** 作,这样就可以跟之前的示例一样,可以获得解析好的JSON数据。 做了一个GET请求,这个请求有一对block:success和failure。 POST请求跟GET一样。

在这里,将请求一个JSON回应,当然也可以使用之前讨论过的另外两种格式来代替JSON。

生成并运行工程,点击HTTPClient按钮,然后选择GET 或 POST按钮来初始化一个相关的请求。之后会看到如下内容:



至此,你已经知道AFhttpClIEnt最基本的使用方法。不过,这里还有更好的一种使用方法,它可以让代码更加干净整齐,下面我们就来学习一下吧。

连接到live Service

到现在为止,你已经在@R_301_5991@ vIEw controller中直接调用了AFRequestoperations 和 AFhttpClIEnt. 实际上,大多数时候不是这样的,你的网络请求会跟某个web service或API相关。

AFhttpClIEnt已经具备与web API通讯的所有内容。AFhttpClIEnt在代码中已经把网络通讯部分做了解耦处理,让网络通讯的代码在整个工程中都可以重用。

下面是两个关于AFhttpClIEnt最佳实践的指导:

为每个web service创建一个子类。例如,如果你在写一个社交网络聚合器,那么可能就会有Twitter的一个子类,Facebook的一个子类,Instragram的一个子类等等。 在AFhttpClIEnt子类中,创建一个类方法,用来返回一个共享的单例,这将会节约资源并省去必要的对象创建。

当前,你的工程中还没有一个AFhttpClIEnt的子类,下面就来创建一个吧。我们来处理一下,让代码清洁起来。

首先,在工程中创建一个新的文件:iOS\Cocoa touch\Objective-C Class. 命名为WeatherhttpClIEnt 并让其继承自AFhttpClIEnt.

你希望这个类做3件事情:

A:执行http请求 

B:当有新的可用天气数据时,调用delegate

C:使用用户当前地理位置来获得准确的天气。

用下面的代码替换WeatherhttpClIEnt.h:

#import "AFhttpClIEnt.h" @protocol WeatherhttpClIEntDelegate; @interface WeatherhttpClIEnt : AFhttpClIEnt (weak) ID<WeatherhttpClIEntDelegate> delegate; + (WeatherhttpClIEnt )shareDWeatherhttpClIEnt;)initWithBaseURL()url;)updateWeatherAtLocation(CLLocation )location forNumberOfDaysint)number; @end @protocol WeatherHttpClientDelegate <NSObject>)weatherHTTPClient)client didUpdateWithWeather)weather;)client didFailWithError()error;@end

在实现文件中,你将了解头文件中定义的更多相关内容。打开WeatherHTTPClient.m 并将下面的代码添加到@implementation下面:

)sharedWeatherHTTPClient*urlStr "http://free.worldweatheronline.com/feed/"static dispatch_once_t pred;    static WeatherHTTPClient *_sharedWeatherHTTPClient nil;     dispatch_once&pred,^{ _sharedWeatherHTTPClient [self alloc:urlStr]; );    return _sharedWeatherHTTPClient;} )url{    self [super initWithBaseURL];    !selfreturn [self registerHTTPOperationClass[self setDefaultHeader]return self;}

sharedWeatherHTTPClient 方法使用Grand Central Dispatch(GCD)来确保这个共享的单例对象只被初始化分配一次。这里用一个base URL来初始化对象,并将其设置为期望web service响应为JSON。

将下面的方法粘贴到上一个方法的下面:

)number{    [parameters setObject"%d",number"num_of_days""%f,%f",location.coordinate.latitude,location.coordinate.longitude"q""7f3a3480fc162445131401" forKey"key"[self getPath"weather.ashx"       parameters:parameters          success[self.delegate respondsToSelector@selector(weatherHTTPClient:didUpdateWithWeather)                [self.delegate weatherHTTPClient:self didUpdateWithWeather:responseObject:didFailWithError:self didFailWithError:error}

这个方法调用World Weather Online接口,以获得具体位置的天气信息。

非常重要!本实例中的API key仅仅是为本文创建的。如果你创建了一个程序,请在World Weather Online创建一个账号,并获得你自己的API key!

一旦对象获得了天气数据,它需要一些方法来通知对此感兴趣的对象:数据回来了。这里要感谢WeatherhttpClIEntDelegate 协议和它的delegate方法,在上面代码中的success 和 failure blocks可以通知一个controller:指定位置的天气已经更新了。这样,controller就可以对天气做更新显示。

现在,我们需要把这些代码片段整合到一起!WeatherhttpClIEnt希望接收一个位置信息,并且WeatherhttpClIEnt定义了一个delegate协议,现在对WT@R_301_5991@VIEwControlle类做一下更新,以使用WeatherhttpClIEnt.

打开WT@[email protected] 添加一个import,并用下面的代码替换@interface声明:

#import "WeatherhttpClIEnt.h" : UI@R_301_5991@VIEwController <NSXMLParserDelegate,UIActionSheetDelegate,WeatherhttpClIEntDelegate>

另外添加一个新的Core Location manager 属性:

) CLLocationManager *manager;

在 WT@[email protected]中,将下面的代码添加到vIEwDIDLoad:的底部:

    self.manager [CLLocationManager alloc] init];    self.manager.delegate = self;

上面这两行代码初始化了Core Location manager,这样当vIEw加载的时候,用来确定用户的当前位置。Core Location然后会通过delegate回调以传回位置信息。将下面的方法添加到实现文件中:

)locationManager(CLLocationManager )manager dIDUpdatetoLocation)newLocation fromLocation)oldLocation//if the location is more than 5 minutes old ignore    [newLocation.timestamp timeIntervalSinceNow]< 300[self.manager stopUpdatingLocation];         WeatherhttpClIEnt [WeatherhttpClIEnt shareDWeatherhttpClIEnt];        clIEnt.delegate = self;        [clIEnt updateWeatherAtLocation:newLocation forNumberOfDays:5];      }

现在,当用户的位置有了变化时,你就可以使用WeatherhttpClIEnt单例来请求当前位置的天气信息。

记住,WeatherhttpClIEnt有两个delegate方法需要实现。将下面两个方法添加到实现文件中:

)aWeather= aWeather;    self.Title "API Updated";    )error{    UIAlertVIEw "Error RetrIEving Weather"                                                 message]                                                delegatenil                                       cancelbuttonTitle}

上面的两个方法,当WeatherhttpClIEnt请求成功,你就可以更新天气数据并重新加载@R_301_5991@ vIEw。如果网络错误,则显示一个错误信息。

找到APITapped: 方法,并用下面的方法替换:

)APITapped{    [self.manager startUpdatingLocation}

生成并运行程序,点击AP按钮以初始化一个WeatherhttpClIEnt 请求,然后会看到如下画面:



希望在这里你未来的天气跟我的一样:晴天!

我还没有死!

你可能注意到了,这里调用的外部web service需要花费一些时间才能返回数据。当在进行网络 *** 作时,给用户提供一个信息反馈是非常重要的,这样用户才知道程序是在运行中或已奔溃了。

很幸运的是,AFNetworking有一个简便的方法来提供信息反馈:AFNetworkActivityIndicatorManager.

在 WTAppDelegate.m中,找到application:dIDFinishLaunchingWithOptions: 方法,并用下面的方法替换:

BOol)application(UIApplication )application dIDFinishLaunchingWithOptions)launchOptions[AFNetworkActivityIndicatorManager sharedManager].enabled YES;    YES;}

让sharedManager可以自动的显示出网络活动指示器( network activity indicator)— 无论射门时候,只要有一个新的网络请求在后台运行着。 这样你就不需要每次请求的时候,都要单独进行管理。

生成并运行工程,无论什么时候,只要有网络请求,都可以在状态栏中看到一个小的网络风火轮:



现在,即使你的程序在等待一个很慢的web service,用户都知道程序还在运行着。

下载图片

如果你在@R_301_5991@ vIEw cell上点击,程序会切换到天气的详细画面,并且以动画的方式显示出相应的天气情况。

这非常不错,但目前动画只有一个背景图片。除了通过网络来更新背景图片,还有更好的方法吗!

下面是本文关于介绍AFNetworking的最后内容了:AFImageRequestoperation. 跟AFJsONRequestoperation一样,AFImageRequestoperation封装了http请求:获取图片。

WeatherAnimationVIEwController.m 中有两个方法需要实现. 找到updateBackgroundImage: 方法,并用下面的代码替换:

)updateBackgroundImage//Store this image on the same server as the weather canned files    "http://www.scott-sherwood.com/wp-content/uploads/2013/01/scene.png"];    AFImageRequestOperation [AFImageRequestOperation imageRequestOperationWithRequest:request        imageProcessingBlocknil        success{            self.backgroundImageView.image = image;            [self saveImage:image withFilename"background.png"{            NSLog("Error %@",0)">);    }

这个方法初始化并下载一个新的背景图片。在结束时,它将返回请求到的完整图片。

在WeatherAnimationViewController.m中,你将看到两个辅助方法:imageWithFilename: 和 saveImage:withFilename:,通过这两个辅助方法,可以对下载下来的图片进行存储和加载。updateBackgroundImage: 将通过辅助方法把下载的图片存储到磁盘中。

接下来找到deleteBackgroundImage: 方法,并用下面的代码替换:

)deleteBackgroundImage*path;	*paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,0)">);	path [paths objectAtIndex] stringByAppendingPathComponent"WeatherHTTPClientImages/"];     *error;    [NSFileManager defaultManager] removeItemAtPath:path error:&error];     *desc [self.weatherDictionary weatherDescription[self start:desc}

这个方法将删除已经下载的图片,这样在测试程序的时候,你可以再次下载图片。

最后一次:生成并运行工程,下载天气数据,并点击某个cell,以打开详细天气画面。在详细天气画面中,点击Update Background 按钮. 如果你点击的是晴天cell,将会看到如下画面:



何去何从?

你可以在这里下载到完整的工程:here.

你所想到的所有方法,都可以通过使用AFNetworking来与外界通讯:

AFJsOnoperation,AFPropertyListOperation 和 AFXMLOperation用来解析结构化数据。 UIImageVIEw+AFNetworking用来快捷的填充image vIEw。 AFhttpClIEnt用来进行更底层的请求。 用自定义的AFhttpClIEnt子类来访问一个web service。 AFNetworkActivityIndicatorManager用来给用户做出网络访问的提示。 AFImageRequestoperation用来加载图片。

AFNetworking的威力可以帮助你进行网络开发!

如果你有任何相关问题,请访问我们的网站以获得帮助。我也很乐意看到你的回复!

本文是由 iOS Tutorial 小组成员 Scott Sherwood撰写,他是一个动态加载(Dynamically Loaded)(基于位置)软件公司(专业的混合定位)的共同创办人。

Tweet

iPhonecategory:

Tags: iOS, ios6, iPhone, networked, sample code, tutorial

发表评论(Leave a Comment)

很想听听你的想法(I'd love to hear your thoughts)!

      添加评论(Add a comment)!   添加评论(Add a comment)!   本文翻译完毕!2013-03-20 破船 :] 总结

以上是内存溢出为你收集整理的iOS-raywenderlich翻译-AFNetworking速成教程全部内容,希望文章能够帮你解决iOS-raywenderlich翻译-AFNetworking速成教程所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1089118.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存