涉及内容:

  1. 百度图片API的使用
  2. JSON格式数据解析
  3. 图片异步下载 + 离线缓存
  4. 图片基本操作(缩放, 删除, 添加, 保存到本地)
  5. 下拉刷新, 上提加载
  6. 幻灯片放映
  7. 自定义后台显示图片


源码解析:




一。百度图片API的使用


首先, 我们知道百度是没有对外开放图片API的, 但是我们可以通过谷歌浏览器来捕捉到访问过程中它调用的API。有兴趣的, 可以了解下谷歌浏览器Network选项的使用, 也可以参考下这篇文章:  ​​百度图片api​​


这里, 我们主要介绍如何使用即可。



1.百度图片通用API:


​​ http://image.baidu.com/i?tn=resultjsonavstar&ie=utf-8&word=刘德华&pn=0&rn=60 ​​ 说明:
返回格式为json
word为查询的内容
pn为第几页
rn为一页返回的图片数量
用法:大家在浏览器地址栏输入上述地址,回车即可看到返回的图片地址



2.百度图片分类API (我们使用的就是这个)


​​ http://image.baidu.com/channel/listjson?pn=0&rn=30&tag1=美女&tag2=全部&ie=utf8 ​​​ http://image.baidu.com/channel/listjson?pn=0&rn=30&tag1=美女&tag2=全部&ftags=校花&ie=utf8 ​



至于其他的, 依照这个方法都能获取到. 就不重复说明了。



至于如何调用API, 涉及到网络编程。


开源的ASI类库做的比较好(虽然挺老的一个东西了, 也有一段时间没更新了, 但是能满足我们需求)。


从源码中, 可以找到 网络请求ASI文件夹,里面有需要的文件



1。导入这里的文件


2。导入必须的框架, 包括:


SystemConfiguration.framework
MobileCoreServices.framework
CFNetwork.framework
libz.dylib


3。调用API (参见 主界面-->picVC)


[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. @property (nonatomic,strong) ASIHTTPRequest *testRequest;  



[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. NSString* urlString = [NSString stringWithFormat:@"http://image.baidu.com/channel/listjson?pn=%d&rn=10&tag1=美女&tag2=%@", nowPage, [chooseArr objectAtIndex:nowChoose]];  
  2.   
  3. urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];  
  4. NSURL *url = [NSURL URLWithString:urlString];  
  5. testRequest = [ASIHTTPRequest requestWithURL:url];  
  6. [testRequest setDelegate:self];  
  7. [testRequest startAsynchronous];  



即可正常调用API。至于如何处理返回的数据, 下面再详细讲。



二。JSON格式数据解析


XMLJSON, 这里因为调用百度图片API返回的数据格式是JSON, 所以我们只要解析JSON即可。


[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. #pragma mark - 加载数据完毕  
  2. - (void)requestFinished:(ASIHTTPRequest *)request  



这个方法返回的数据是二进制格式的NSData, 我们需要手动转为UTF8编码。可以这样获取:


[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. //当以二进制读取返回内容时用这个方法  
  2. NSData *responseData = [request responseData];  
  3. NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];  


接下去就是神奇的时候了, 对于这样的一个字符串, 如果直接打印, 你可能会看得云里雾里的, json格式并且没有重新排列。


但是我们可以使用JsonKit来直接解析。(文件在json解析文件夹中)



只需这样一条语句即可:


[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. self.testDic = [responseString objectFromJSONString];  



打印解析后的数据如下:




美女图片采集器 (源码+解析)_JSON




至于需要哪些, 直接取就好了。比如. 我们这里需要获取到图片的标题. url, 宽度, 高度


[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. NSMutableDictionary *nowDic = [[NSMutableDictionary alloc]init];  
  2. [nowDic setObject:[[array objectAtIndex:i]objectForKey:@"image_url"] forKey:@"image_url"];  
  3. [nowDic setObject:[[array objectAtIndex:i]objectForKey:@"image_width"] forKey:@"image_width"];  
  4. [nowDic setObject:[[array objectAtIndex:i]objectForKey:@"image_height"] forKey:@"image_height"];  
  5. [nowDic setObject:[[array objectAtIndex:i]objectForKey:@"desc"] forKey:@"desc"];  
  6.   
  7. [picArray addObject:nowDic];  




三。图片异步下载+离线缓存



这里提一下SDWebImage, 我们将会使用它来实现。 具体使用参见: ​​SDWebImage 笔记​​


在解析完json数据后, 我们会获取到图片对应的url。


我们可以通过访问url获取图片。 


[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. - (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;  



使用方法:


[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(SPACE / 2 , SPACE / 2 , width, height)];  
  2. NSURL *url = [NSURL URLWithString:imageInfo.thumbURL];  
  3. [imageView setImageWithURL:url placeholderImage:nil];  
  4. imageView.backgroundColor = [UIColor palePurpleColor];  
  5. [self addSubview:imageView];  




异步下载,离线缓存效果:(离线缓存可以到应用沙盒中查看)



美女图片采集器 (源码+解析)_API_02





四。图片基本操作(缩放, 删除, 添加, 保存到本地)



这里涉及的主要是一些常规操作, 包括缩放, 删除, 添加, 保存到本地等。


至于删除, 一般是长按删除, 只要在图片上加上长按手势响应即可。然后弹出一个对话框, 提示用户是否删除。确定删除后, 从沙盒中清除缓存即可。


添加手势方法:


[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. //长按  
  2. UILongPressGestureRecognizer *longRecognizer;  
  3. longRecognizer = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(handleSingleLongFrom:)];  
  4. [self addGestureRecognizer:longRecognizer];  


从视图和沙盒中删除


[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. //从当前视图中删除  
  2. [testArr removeObject:data];  
  3. //刷新数据  
  4. __weak picVC *blockSelf = self;  
  5. [blockSelf.waterView refreshView:testArr];  
  6. [blockSelf.waterView.infiniteScrollingView stopAnimating];  
  7.   
  8. //从沙盒中删除  
  9. //打开沙盒  
  10. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  
  11. NSString *documentsDirectory = [paths objectAtIndex:0];  
  12. NSString * namePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"savedPicInfo_%d.plist",nowChoose]];  
  13. NSMutableArray *picArray = [[NSMutableArray alloc] initWithContentsOfFile:namePath];  
  14.   
  15. for (int i=0; i<[picArray count]; i++)  
  16. {  
  17. if ([[[picArray objectAtIndex:i]objectForKey:@"image_url"] isEqualToString:data.thumbURL])  
  18.     {  
  19.  removeObjectAtIndex:i];  
  20. break;  
  21.     }  
  22. }  
  23. [picArray writeToFile:namePath atomically:YES];  


至于缩放, 首先要弹出一个全屏显示的视图。


像这样:


[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. //单击, 显示大图  
  2. -(void)showImage:(ImageInfo*)data  
  3. {  
  4. NSURL *url = [NSURL URLWithString:data.thumbURL];  
  5.  setImageWithURL:url placeholderImage:nil];  
  6. TGRImageViewController *viewController = [[TGRImageViewController alloc] initWithImage:clickImage.image setImageInfo:data];  
  7. .transitioningDelegate = self;  
  8. self presentViewController:viewController animated:YES completion:nil];  
  9. }  


本质就是调用presentViewController:viewController。


当然,我们可以给新视图的显示加上动画效果, 如下:


[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. #pragma mark - UIViewControllerTransitioningDelegate methods  
  2. - (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source  
  3. {  
  4. if ([presented isKindOfClass:TGRImageViewController.class]) {  
  5. return [[TGRImageZoomAnimationController alloc] initWithReferenceImageView:clickImage];  
  6.     }  
  7. return nil;  
  8. }  
  9.   
  10. - (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {  
  11. if ([dismissed isKindOfClass:TGRImageViewController.class]) {  
  12. return [[TGRImageZoomAnimationController alloc] initWithReferenceImageView:clickImage];  
  13.     }  
  14. return nil;  
  15. }  




然后, 在新视图中, 添加点击移除, 长按弹出新操作, 双指移动缩放手势即可。


具体实现如下:


[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. #pragma mark - Private methods  
  2.   
  3. - (void)longPress:(UITapGestureRecognizer *)tapGestureRecognizer  
  4. {  
  5.       
  6. if(tapGestureRecognizer.state == UIGestureRecognizerStateBegan)  
  7.     {  
  8. self popupActionSheet];  
  9.     }  
  10. }  
  11.   
  12. - (IBAction)handleSingleTap:(UITapGestureRecognizer *)tapGestureRecognizer {  
  13. self dismissViewControllerAnimated:YES completion:nil];  
  14. }  
  15.   
  16. - (IBAction)handleDoubleTap:(UITapGestureRecognizer *)tapGestureRecognizer {  
  17. if (self.scrollView.zoomScale == self.scrollView.minimumZoomScale) {  
  18. // Zoom in  
  19.  locationInView:self.scrollView];  
  20. self.scrollView.bounds.size.width / self.scrollView.maximumZoomScale,  
  21. self.scrollView.bounds.size.height / self.scrollView.maximumZoomScale);  
  22. .x - (size.width / 2.0), center.y - (size.height / 2.0), size.width, size.height);  
  23. self.scrollView zoomToRect:rect animated:YES];  
  24.     }  
  25. else {  
  26. // Zoom out  
  27. self.scrollView zoomToRect:self.scrollView.bounds animated:YES];  
  28.     }  
  29. }  





五。下拉刷新, 上提加载


这个功能具体在浏览图片的时候使用。 代码在picVC中。


但是因为我之前专门写过一篇这样的博客。 就不再重复了。


详细可以看这里: ​​ iOS开发-ios7下拉刷新,上提加载快速集成​​




六。幻灯片放映


顾名思义, 就是能够自动播放收藏过的美女图片..  


这里的原理是利用UIView的动画, 不断切换显示图片和显示效果。



切换效果如下:


[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. _transitionOptions= @[[NSNumber numberWithInteger:UIViewAnimationOptionTransitionFlipFromLeft],  
  2.  numberWithInteger:UIViewAnimationOptionTransitionFlipFromRight],  
  3.  numberWithInteger:UIViewAnimationOptionTransitionCurlUp],  
  4.  numberWithInteger:UIViewAnimationOptionTransitionCurlDown],  
  5.  numberWithInteger:UIViewAnimationOptionTransitionCrossDissolve],  
  6.  numberWithInteger:UIViewAnimationOptionTransitionFlipFromTop],  
  7.  numberWithInteger:UIViewAnimationCurveEaseIn],  
  8.  numberWithInteger:UIViewAnimationCurveEaseOut],  
  9.  numberWithInteger:UIViewAnimationCurveLinear],  
  10.  numberWithInteger:UIViewAnimationOptionAllowAnimatedContent],  
  11.  numberWithInteger:UIViewAnimationOptionOverrideInheritedCurve],  
  12.  numberWithInteger:UIViewAnimationOptionTransitionFlipFromTop],  
  13.  numberWithInteger:UIViewAnimationOptionTransitionFlipFromBottom]];  


然后切换图片的时候, 实现如下代码即可。  (具体参见PhotoStackView)


[objc]  ​​view plain​​ ​​copy​​ ​​​ ​​​



  1. -(void)reloadData {  
  2.       
  3. if (!self.dataSource) {  
  4. //exit if data source has not been set up yet  
  5. self.photoViews = nil;  
  6. return;  
  7.     }  
  8.       
  9. self.dataSource numberOfPhotosInPhotoStackView:self];  
  10. self indexOfTopPhoto]; // Keeping track of current photo's top index so that it remains on top if new photos are added  
  11.       
  12. if(numberOfPhotos > 0) {  
  13.   
  14. NSMutableArray *photoViewsMutable   = [[NSMutableArray alloc] initWithCapacity:numberOfPhotos];  
  15. UIImage *borderImage                = [self.borderImage resizableImageWithCapInsets:UIEdgeInsetsMake(self.borderWidth, self.borderWidth, self.borderWidth, self.borderWidth)];  
  16.           
  17. for (NSUInteger index = 0; index < numberOfPhotos; index++) {  
  18.   
  19. UIImage *image = [self.dataSource photoStackView:self photoForIndex:index];  
  20. .size;  
  21. if([self.dataSource respondsToSelector:@selector(photoStackView:photoSizeForIndex:)]){  
  22. self.dataSource photoStackView:self photoSizeForIndex:index];  
  23.             }  
  24. UIImageView *photoImageView     = [[UIImageView alloc] initWithFrame:(CGRect){CGPointZero, imageSize}];  
  25. .image            = image;  
  26. UIView *view                    = [[UIView alloc] initWithFrame:photoImageView.frame];  
  27. .layer.rasterizationScale   = [[UIScreen mainScreen] scale];              
  28. .layer.shouldRasterize      = YES; // rasterize the view for faster drawing and smooth edges  
  29.   
  30. if (self.showBorder) {  
  31.                   
  32. // Add the background image  
  33. if (borderImage) {  
  34. // If there is a border image, we need to add a background image view, and add some padding around the photo for the border  
  35.   
  36. .frame;  
  37. .origin                = CGPointMake(self.borderWidth, self.borderWidth);  
  38. .frame             = photoFrame;  
  39.   
  40. .frame                       = CGRectMake(0, 0, photoImageView.frame.size.width+(self.borderWidth*2), photoImageView.frame.size.height+(self.borderWidth*2));  
  41. UIImageView *backgroundImageView = [[UIImageView alloc] initWithFrame:view.frame];  
  42. .image        = borderImage;  
  43.                       
  44.  addSubview:backgroundImageView];  
  45. else {  
  46. // if there is no boarder image draw one with the CALayer  
  47. .layer.borderWidth        = self.borderWidth;  
  48. .layer.borderColor        = [[UIColor whiteColor] CGColor];  
  49. .layer.shadowOffset       = CGSizeMake(0, 0);  
  50. .layer.shadowOpacity      = 0.5;  
  51.                 }  
  52.             }  
  53.   
  54.  addSubview:photoImageView];  
  55.   
  56. .tag    = index;  
  57. .center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));  
  58.   
  59.  addObject:view];  
  60.               
  61.         }  
  62.   
  63. // Photo views are added to subview in the photoView setter  
  64. self.photoViews = photoViewsMutable; photoViewsMutable = nil;  
  65. self goToPhotoAtIndex:topPhotoIndex];  
  66.           
  67.     }  
  68.       
  69. }  





七。自定义后台显示图片


比如..  有时候我们浏览的图片尺度比较大.. 然后切到后台的时候, 就希望把它隐藏起来..  



这就涉及到了Background Fetch的应用。


之前也写过一篇博客专门介绍。 这里就不重复了。


具体参见: ​​ iOS开发-自定义后台显示图片(iOS7-Background Fetch的应用)​​