iPhone团购信息客户端的开发

转自

http://blog.csdn.net/kangkangz4/article/details/7714140

http://blog.csdn.net/kangkangz4/article/details/7714722

http://blog.csdn.net/kangkangz4/article/details/7715376

http://blog.csdn.net/kangkangz4/article/details/7774098


因为工作的原因,已经很久没有更新博客了,这次我们就来完成一个稍显复杂的一个团购信息客户端,主要整合了ASIHTTPREQUEST,KISSXML,AQGridView,MBProgressHUD这几个主要流行的IOS开发库,我们先来看一下效果图

首先我们新建一个IOS工程,暂时就取名为Tuan1吧,如图下



好,工程新建完后我们就要加入框架了,首先加入ASIHTTPREQUEST库,首先我们从https://github.com/pokeb/asi-http-request/tree下载压缩包

点ZIP按钮就行了,会全部将文件下载下来,好,我们接着就将它加入我们的工程中,首先找到我们新建工程的那个Tuan1的文件夹,在底下新建一个ASIHttpRequest的文件夹


接着把我们下载的ASIHttpRequest中的几个文件夹拷入我们新建的文件夹内,我们主要拷的是下载包中class文件夹下的内容

将所有文件拷入我们自己新建的文件夹内,除了一个Test文件夹哦,这个是测试文件,我们用不到,所以不用拷了。

还有一个也需要我们拷到新建的文件夹内的,就是下载ASIHttpRequest下的External/Reachability文件夹,这个不能忘哦,不然运行的时候会报错。

接着就是加入我们的工程中了,在File下有一个Add File To 'Tuan1'这个选项


点击我们选择我们新建的ASIHttpRequest文件夹,将所有文件导入当前的工程中


接下来就是加Framework了,要运行ASIHttpRequest,我们需要以下几个Framework,CFNetwork.framework,SystemConfiguration.framework,MobileCoreServices.framework,libz.1.2.5.dylib,libxml2.dylib,最后如下图


接下来还有最重要的一件事哦,就是我们得告诉系统到哪找libxml2这个库

在Build Setting中Header Search Paths设置/usr/include/libxml2


因为ASIHttpRequest暂时不支持ARC模式,而我们的工程是使用ARC模式的,就需要将ASIHttpRequest下的所有文件不用ARC模式编绎


经过以上步骤,我们的ASIHttpRequest应该可以运行了,我们在工程中导入#import "ASIHttpRequest.h"试着运行一下,看有没有错误,没有错误的话,我们ASIHttpRequest就添加成功了,接下来第二篇,我们再介绍如何导入KissXML,MBProgressHUD和AGridView这几个库。



接上一篇,这篇我们对我们的客户端加入KissXML,MBProgressHUD,AQridView这几个库,首先我们先加入KissXML,这是XML解析库,支持Xpath,可以方便添加更改任何节点。先从官方网站上下载KissXML这个库

https://github.com/robbiehanson/KissXML

接下来,将KissXML库中的KissXML文件夹拷入我们的工程中,如图


然后跟上次一样,我们通过File/Add File to "Tuan1"这个选项加入到我们的工程中,我们以同样的方法分别加入MBProgressHUD和AGridView这两个库

在Framework中加入QuartzCore.framework,因为AGridView需要用到。

接着我们在代码中加入

#import"MBProgressHUD.h"

#import"DDXML.h"

这二行,运行一下,如果没有报错的话,那这几个库我们就加入成功了。

接着我们更改一下storybord,将FirstViewController这个视图加入NavigationController,选中FirstViewController在主菜单Editor/Embed In/Navigation Controller,系统自动为我们加入NavigationController。


下面,我们将FirstViewController中清空,所有内容都删除


好了,到这一步,我们的视图基本都完成了,接下来就是编码了,首先我们来解析美团网团购信息

FirstViewController.h

[plain]  view plain copy
  1. #import <UIKit/UIKit.h>  
  2. #import "ASIHTTPRequest.h"  
  3.   
  4.   
  5. @interface KKFirstViewController : UIViewController<ASIHTTPRequestDelegate>  
  6.   
  7.   
  8. @end  


FirstViewController.m

[plain]  view plain copy
  1. #import "KKFirstViewController.h"  
  2. #import "MBProgressHUD.h"  
  3. #import "DDXML.h"  
  4. #import "DDXMLElementAdditions.h"  
  5.   
  6. @interface KKFirstViewController (){  
  7.       
  8.     MBProgressHUD *hud;  
  9.     NSMutableArray *arrays;  
  10.       
  11. }  
  12.   
  13. @end  
  14.   
  15. @implementation KKFirstViewController  
  16.   
  17. - (void)viewDidLoad  
  18. {  
  19.     [super viewDidLoad];  
  20.       
  21.     self.navigationItem.title = @"美团";  
  22.     //背景  
  23.     UIImage *bgImage = [UIImage imageNamed:@"bg-app.png"];  
  24.     self.view.backgroundColor = [UIColor colorWithPatternImage:bgImage];  
  25.     //HUD提示框  
  26.     hud = [[MBProgressHUD alloc] init];  
  27.     hud.labelText = @"载入数据...";  
  28.     //网址  
  29.     NSString *urlString = @"http://www.meituan.com/api/v2/beijing/deals";  
  30.       
  31.     [hud showWhileExecuting:@selector(startHttpRequest:) onTarget:self withObject:urlString animated:YES];  
  32.     //因为hud需要显示在最前面,所以我们在NavigationController中加入  
  33.     [self.navigationController.view addSubview:hud];  
  34.       
  35.     arrays = [NSMutableArray array];  
  36. }  
  37.   
  38. //请求URL  
  39. -(void)startHttpRequest:(NSString *)url{  
  40.       
  41.     ASIHTTPRequest *httpRequest = [[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:url]];  
  42.       
  43.     httpRequest.delegate = self;  
  44.       
  45.     [httpRequest startSynchronous];  
  46.       
  47. }  
  48.   
  49. - (void)viewDidUnload  
  50. {  
  51.     [super viewDidUnload];  
  52.     // Release any retained subviews of the main view.  
  53. }  
  54.   
  55. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation  
  56. {  
  57.     return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);  
  58. }  
  59.   
  60.   
  61. //请求结束  
  62. -(void)requestFinished:(ASIHTTPRequest *)request{  
  63.     //移除提示框  
  64.     [hud removeFromSuperview];  
  65.     //返回解析后的数据,每一个Array包括一个字典  
  66.     arrays = [self xmlParser:[request responseData]];  
  67.       
  68.     NSLog(@"%@", arrays);  
  69.       
  70. }  
  71.   
  72. //解析结点  
  73. static NSString *kXPath_Item = @"//data";  
  74. static NSString *kName_Deal = @"deal";  
  75. static NSString *kName_Title = @"deal_title";  
  76. static NSString *kName_Url = @"deal_url";  
  77. static NSString *kName_Img = @"deal_img";  
  78. static NSString *kName_Desc = @"deal_desc";  
  79. static NSString *kName_Tips = @"deal_tips";  
  80.   
  81. //XML解析  
  82. -(NSMutableArray *)xmlParser:(NSData *)data{  
  83.       
  84.     NSMutableArray *array = [NSMutableArray array];  
  85.     //文档开始  
  86.     DDXMLDocument *xmlDoc = [[DDXMLDocument alloc] initWithData:data options:0 error:nil];  
  87.     //返回<data>中的所有元素  
  88.     NSArray *items = [xmlDoc nodesForXPath:kXPath_Item error:nil];  
  89.     //遍历每个元素  
  90.     for (DDXMLElement *item in items) {  
  91.           
  92.         NSMutableDictionary *dict = [NSMutableDictionary dictionary];  
  93.         //返回<deal>中的所有元素  
  94.         NSArray *deals = [item elementsForName:kName_Deal];  
  95.           
  96.         for (DDXMLElement *deal in deals) {  
  97.             //<deal_title>  
  98.             DDXMLElement *title = [deal elementForName:kName_Title];  
  99.             if (title) {  
  100.                 [dict setObject:[title stringValue] forKey:kName_Title];  
  101.             }  
  102.             //<deal_url>  
  103.             DDXMLElement *url = [deal elementForName:kName_Url];  
  104.             if (url) {  
  105.                 [dict setObject:[url stringValue] forKey:kName_Url];  
  106.             }  
  107.             //<deal_img>  
  108.             DDXMLElement *img = [deal elementForName:kName_Img];  
  109.             if (img) {  
  110.                 [dict setObject:[img stringValue] forKey:kName_Img];  
  111.             }  
  112.             //<deal_desc>  
  113.             DDXMLElement *desc = [deal elementForName:kName_Desc];  
  114.             if (desc) {  
  115.                 [dict setObject:[desc stringValue] forKey:kName_Desc];  
  116.             }  
  117.             //<deal_tips>  
  118.             DDXMLElement *tips = [deal elementForName:kName_Tips];  
  119.             if (tips) {  
  120.                 [dict setObject:[tips stringValue] forKey:kName_Tips];  
  121.             }  
  122.               
  123.         }  
  124.         [array addObject:dict];  
  125.     }  
  126.       
  127.     return array;  
  128.       
  129. }  
  130.   
  131. //请求中止(出错)  
  132. -(void)requestFailed:(ASIHTTPRequest *)request{  
  133.       
  134.     [hud removeFromSuperview];  
  135.       
  136.     NSError *error = [request error];  
  137.       
  138.     NSLog(@"RequestError : %@", [error description]);  
  139.       
  140. }  
  141.   
  142. @end  
这里面最重要的就是解析返回的XML数据,代码里面的注释也写得比较详细了,我想大家也应该能看得懂,取得数据后我们就可以显示在AQGridView中去了。这个内容我们放到第三篇中做详细介绍。


接上二篇的内容,今天我们就来介绍一下如何将解析出来的数据放入AQGridView中显示出来,因为我们的工程中已经将AQGridView导入了,所以我们在KKFirstViewController中直接可以引用

[plain]  view plain copy
  1. #import <UIKit/UIKit.h>  
  2. #import "ASIHTTPRequest.h"  
  3. #import "AQGridView.h"  
  4.   
  5.   
  6. @interface KKFirstViewController : UIViewController<ASIHTTPRequestDelegate, AQGridViewDelegate, AQGridViewDataSource>  
  7.   
  8. @property(nonatomic, retain)AQGridView *gridView;  
  9.   
  10. @end  
这里加入了AQGridViewDelegate和AQGridViewDataSource这两个委托,简单一点我们可以把AQGridView看成UITableView,同样的道理,一个是数据源的方法,一个就是选中的方法

然后就是
在-(void)viewDidLoad这个方法中,我们加入了

[plain]  view plain copy
  1. self.gridView = [[AQGridView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];  
  2. self.gridView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;  
  3. self.gridView.autoresizesSubviews = YES;  
  4. self.gridView.delegate = self;  
  5. self.gridView.dataSource = self;  
  6.   
  7. [self.view addSubview:gridView];  
将当前的gridView加入主视图中

接着还有两个方法一定需要实现的

[plain]  view plain copy
  1. #pragma mark AQGridViewDataSource  
  2. //总共有的Item  
  3. -(NSUInteger)numberOfItemsInGridView:(AQGridView *)gridView{  
  4.       
  5.     return [arrays count];  
  6. }  
  7. //每个Item  
  8. -(AQGridViewCell *)gridView:(AQGridView *)aGridView cellForItemAtIndex:(NSUInteger)index{  
  9.       
  10.     static NSString *identifier = @"PlainCell";  
  11.       
  12.     GridViewCell *cell = (GridViewCell *)[aGridView dequeueReusableCellWithIdentifier:identifier];  
  13.       
  14.     if(cell == nil){  
  15.           
  16.         cell = [[GridViewCell alloc] initWithFrame:CGRectMake(0, 0, 160, 123) reuseIdentifier:identifier];  
  17.     }  
  18.       
  19.     //取得每一个字典  
  20.     NSDictionary *dict = [arrays objectAtIndex:index];  
  21.       
  22.     [cell.captionLabel setText:[dict objectForKey:kName_Title]];  
  23.       
  24.     return cell;  
  25.       
  26. }  
  27.   
  28. //每个显示框大小  
  29. -(CGSize)portraitGridCellSizeForGridView:(AQGridView *)gridView{  
  30.       
  31.     return CGSizeMake(160, 123);  
  32. }  
这里还少一个类,就是GridView,这个类继承了AQGridViewCell,里面就是我们单独要显示的一个Item

[plain]  view plain copy
  1. #import "AQGridViewCell.h"  
  2.   
  3. @interface GridViewCell : AQGridViewCell  
  4.   
  5. @property(nonatomic, retain)UIImageView *imageView;  
  6. @property(nonatomic, retain)UILabel *captionLabel;  
  7.   
  8. @end  
图片显示的是团购信息中的图片,还有一个是文本

[plain]  view plain copy
  1. #import "GridViewCell.h"  
  2.   
  3. @implementation GridViewCell  
  4.   
  5. @synthesize imageView,captionLabel;  
  6.   
  7.   
  8. - (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier  
  9. {  
  10.     self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier];  
  11.     if (self) {  
  12.           
  13.         UIView *mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 160, 123)];  
  14.         [mainView setBackgroundColor:[UIColor clearColor]];  
  15.           
  16.         UIImageView *frameImageView = [[UIImageView alloc] initWithFrame:CGRectMake(9, 4, 142, 117)];  
  17.         [frameImageView setImage:[UIImage imageNamed:@"tab-mask.png"]];  
  18.           
  19.         self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(13, 8, 135, 84)];  
  20.           
  21.         self.captionLabel = [[UILabel alloc] initWithFrame:CGRectMake(13, 92, 127, 21)];  
  22.         [captionLabel setFont:[UIFont systemFontOfSize:14]];  
  23.           
  24.         [mainView addSubview:imageView];  
  25.         [mainView addSubview:frameImageView];  
  26.         [mainView addSubview:captionLabel];  
  27.           
  28.         [self.contentView addSubview:mainView];  
  29.           
  30.     }  
  31.     return self;  
  32. }  
  33.   
  34. @end  
这里面定义了三个控件,两个控件是我们要传入的数据,一个图片,一个文本,还有一个就是我们单独Item的背景

做完这一些,运行一下,我们就可以看到有文字信息的效果了,但还没有加入图片显示功能,从这里我们就要考虑了,图片是我们划动的时候再加载呢还是一次性加载呢,考虑到效果和数据流量,我们还是用异步来加载数据,这就需要加入缓存的功能了,我们用一个NSMutableArray来实现缓存。

看一下代码呢,这代码也是参考了别人写的

[plain]  view plain copy
  1. //缓存图片  
  2. -(UIImage *)cachedImageForUrl:(NSURL *)url{  
  3.       
  4.     id cacheObject = [self.cachedImage objectForKey:url];  
  5.       
  6.     if (cacheObject == nil) {  
  7.         //添加占位符  
  8.         [self.cachedImage setObject:@"Loading..." forKey:url];  
  9.           
  10.         ASIHTTPRequest *picRequest = [ASIHTTPRequest requestWithURL:url];  
  11.         picRequest.delegate = self;  
  12.         picRequest.didFinishSelector = @selector(didFinishRequestImage:);  
  13.         picRequest.didFailSelector = @selector(didFailRequestImage:);  
  14.         //加入队列  
  15.         [self.queue addOperation:picRequest];  
  16.           
  17.         [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;  
  18.           
  19.     }else if(![cacheObject isKindOfClass:[UIImage class]]){  
  20.         cacheObject = nil;  
  21.     }  
  22.       
  23.     return cacheObject;  
  24.       
  25. }  
  26.   
  27. //完成图片下载,并加入缓存  
  28. -(void)didFinishRequestImage:(ASIHTTPRequest *)request{  
  29.       
  30.     NSData *imageData = [request responseData];  
  31.     UIImage *image = [UIImage imageWithData:imageData];  
  32.     if (image != nil) {  
  33.         [self.cachedImage setObject:image forKey:request.url];  
  34.           
  35.         [self.gridView reloadData];  
  36.     }  
  37.       
  38.     [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;  
  39. }  
  40.   
  41. //下载失败  
  42. -(void)didFailRequestImage:(ASIHTTPRequest *)request{  
  43.       
  44.     NSLog(@"Error download Image %@", [request error]);  
  45.     //从当前缓存中移除  
  46.     [self.cachedImage removeObjectForKey:request.url];  
  47.     [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;  
  48.       
  49. }  

最后我们在Cell中加入显示图片的代码就可以了,就实现了异步加载图片

[plain]  view plain copy
  1. //利用缓存保存图片  
  2.     [cell.imageView setImage:[self cachedImageForUrl:[NSURL URLWithString:[dict objectForKey:kName_Img]]]];  
好了,这个程序中主要介绍了AQGridView库,MBProgressHUD,KissXML,ASIHttpRequest这几个库,综合利用各个类库将可以使我们的程序美观,也可以缩短我们的开发周期。好了,谢谢大家有耐心看完。这里提供了源码下载

程序源码

我们对团购客户端进行了重构,来看一下效果图呢




这里因为美团提供了地图坐标,所以我们也加入了MapKit来显示店铺所在位置,但只有美团有,其他几个网站都没有提供。

我们把源码放出:谢谢大家一如既往的支持


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值