parserparser didStartElementelementName namespaceURInamespaceURI qualifiedNameqName attributesattributeDict { self.previousElementName = self.elementName; self.elementName = qName; } qName isEqualToStringself.currentDictionary dictionary]; qName isEqualToStringself.currentDictionary dictionary]; qName isEqualToStringself.currentDictionary dictionary]; } self.outstring ; }
当NSXMLParser发现了新的元素开始标签时,会调用上面这个方法。在这个方法中,在构造一个新字典用来存储赋值给currentDictionary属性之前,首先保存住上一个元素名称。还要将outstring重置一下,这个字符串用来构造XML标签中的数据。
然后将下面这个方法粘贴到上一个方法的后面:
parserparser foundCharactersself.elementName; } , string]; }
如名字一样,当NSXMLParser在一个XML标签中发现了字符数据,会调用这个方法。该方法将字符数据追加到outstring属性中,当XML标签结束的时候,这个outstring会被处理。
继续,将下面这个方法粘贴到上一个方法的后面:
parserparser didEndElementelementName namespaceURInamespaceURI qualifiedNameqName { qName isEqualToString|| self.xmlWeather setObjectarrayWithObject:self.currentDictionary] forKey:qName]; self.currentDictionary = nil; qName isEqualToString array ; array) array array]; [array addObject:self.currentDictionary]; ; self.currentDictionary = nil; qName isEqualToStringqName isEqualToString|| self.currentDictionary setObjectarrayWithObjectdictionaryWithObjectforKey:qName]; self.currentDictionary setObject:self.outstring forKey:qName]; } self.elementName = nil; }
当检测到元素的结束标签时,会调用上面这个方法。在这个方法中,会查找一些标签:
下面是最后一个delegate方法!将下面这个方法粘贴到上一个方法的后面:
parserDidEndDocumentparser { self.weather dictionaryWithObject; self.title ; [self.tableView reloadData]; }
当NSXMLParser解析到document的尾部时,会调用这个方法。在此,xmlWeather字典已经构造完毕,table view可以重新加载了。
在上面代码中将xmlWeather添加到一个字典中,看起来是冗余的, 不过这样可以确保与JSON和plist版本的格式完全匹配。这样所有的3种数据格式(JSON, plist和XML)都能够用相同的代码来显示!
sender{ ... successrequest, self.xmlWeather dictionary]; XMLParser.delegate = self; ... }
生成和运行工程,然后点击XML按钮,将看到如下内容:
一个小的天气程序
嗯, 上面的这个程序看起来体验不太友好,有点像整周都是阴雨天。如何让table view中的天气信息体验更好点呢?
再仔细看看之前的JSON格式数据:,你会看到每个天气项里面都有一个图片URLs。 将这些天气图片显示到每个table view cell中,这样程序看起来会更有意思。
AFNetworking给UIImageView添加了一个category,让图片能够异步加载,也就是说当图片在后台下载的时候,程序的UI界面仍然能够响应。为了使用这个功能,首先需要将这个category import到WTTableViewController.m文件的顶部:
#import "UIImageView+AFNetworking.h" 找到tableView:cellForRowAtIndexPath: 方法,并将下面的代码粘贴到最后的return cell; 代码上上面(这里应该有一个注释标记)
__weak UITableViewCell *weakCell = cell; allocURLWithString:daysWeather.weatherIconURL]] placeholderImagesuccessrequest, weakCell.imageView.image = image; weakCell setNeedsLayout]; //} } failurerequest, }];
首先创建一个弱引用(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类