美女图片采集器 (源码+解析)[通俗易懂]

美女图片采集器 (源码+解析)[通俗易懂]前言:有一段时间没写博客了,”持之以恒”徽章都暗了,实在不该。前一段确实比较忙,…小小地给自己的懒找个借口吧。大二即将结束,学习iOS也有一段时间了。今天抽点时间,开源一个前几天刚上传的App里面的一个功能,RT,美女图片采集器。 美女..相信没有人不喜欢吧,基于此,这个小Demo应运而生。注: 本文正在参加博

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

前言:


有一段时间没写博客了, “持之以恒”徽章都暗了, 实在不该。 前一段确实比较忙, …小小地给自己的懒找个借口吧。 大二即将结束, 学习iOS也有一段时间了。今天抽点时间, 开源一个前几天刚上传的App里面的一个功能, RT, 美女图片采集器。   美女.. 相信没有人不喜欢吧, 基于此, 这个小Demo应运而生。

注: 

本文正在参加博客大赛。 如果觉得对你有所帮助, 还望帮忙投下票。 多谢。 

投票链接: http://vote.blog.csdn.net/Article/Details?articleid=37825177 (投票按钮在最下方)

效果演示:

美女图片采集器 (源码+解析)[通俗易懂]美女图片采集器 (源码+解析)[通俗易懂]美女图片采集器 (源码+解析)[通俗易懂]美女图片采集器 (源码+解析)[通俗易懂]美女图片采集器 (源码+解析)[通俗易懂]

看到这里, 如果还有兴趣学习的话, 可以先到我的git中下载源码, 然后配合着源码看我下面的解析。相信, 会让你有所收获的。

git下载链接: BeautyPickDemo.git

涉及内容:

  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
在CODE上查看代码片
派生到我的代码片

  1. @property (nonatomic,strongASIHTTPRequest *testRequest;  

[objc] 
view plain
copy
在CODE上查看代码片
派生到我的代码片

  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格式数据解析

一般的数据格式有
XML
JSON, 这里因为调用百度图片API返回的数据格式是JSON, 所以我们只要解析JSON即可。
调用API成功后, 它会自动执行这个函数

[objc] 
view plain
copy
在CODE上查看代码片
派生到我的代码片

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

我们只需要在这里解析数据, 使用数据即可。


这个方法返回的数据是二进制格式的NSData, 我们需要手动转为UTF8编码。可以这样获取:
[objc] 
view plain
copy
在CODE上查看代码片
派生到我的代码片

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

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

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

只需这样一条语句即可:
[objc] 
view plain
copy
在CODE上查看代码片
派生到我的代码片

  1. self.testDic = [responseString objectFromJSONString];  

打印解析后的数据如下:

美女图片采集器 (源码+解析)[通俗易懂]


至于需要哪些, 直接取就好了。比如. 我们这里需要获取到图片的标题. url, 宽度, 高度
[objc] 
view plain
copy
在CODE上查看代码片
派生到我的代码片

  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
在CODE上查看代码片
派生到我的代码片

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

这是SDWebImage给我们提供的一个函数. 通过调用它, 我们可以实现异步下载和离线缓存。


使用方法:
[objc] 
view plain
copy
在CODE上查看代码片
派生到我的代码片

  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];  
异步下载,离线缓存效果:(离线缓存可以到应用沙盒中查看)

美女图片采集器 (源码+解析)[通俗易懂]
美女图片采集器 (源码+解析)[通俗易懂]



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


这里涉及的主要是一些常规操作, 包括缩放, 删除, 添加, 保存到本地等。
至于删除, 一般是长按删除, 只要在图片上加上长按手势响应即可。然后弹出一个对话框, 提示用户是否删除。确定删除后, 从沙盒中清除缓存即可。
添加手势方法:
[objc] 
view plain
copy
在CODE上查看代码片
派生到我的代码片

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

从视图和沙盒中删除

[objc] 
view plain
copy
在CODE上查看代码片
派生到我的代码片

  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.         [picArray removeObjectAtIndex:i];  
  20.         break;  
  21.     }  
  22. }  
  23. [picArray writeToFile:namePath atomically:YES];  

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

像这样:
[objc] 
view plain
copy
在CODE上查看代码片
派生到我的代码片

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

本质就是调用presentViewController:viewController。

当然,我们可以给新视图的显示加上动画效果, 如下:
[objc] 
view plain
copy
在CODE上查看代码片
派生到我的代码片

  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
在CODE上查看代码片
派生到我的代码片

  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.         CGPoint center = [tapGestureRecognizer locationInView:self.scrollView];  
  20.         CGSize size = CGSizeMake(self.scrollView.bounds.size.width / self.scrollView.maximumZoomScale,  
  21.                                  self.scrollView.bounds.size.height / self.scrollView.maximumZoomScale);  
  22.         CGRect rect = CGRectMake(center.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中。
但是因为我之前专门写过一篇这样的博客。 就不再重复了。


六。幻灯片放映

顾名思义, 就是能够自动播放收藏过的美女图片..  
这里的原理是利用UIView的动画, 不断切换显示图片和显示效果。

切换效果如下:
[objc] 
view plain
copy
在CODE上查看代码片
派生到我的代码片

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

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

[objc] 
view plain
copy
在CODE上查看代码片
派生到我的代码片

  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.     NSInteger numberOfPhotos = [self.dataSource numberOfPhotosInPhotoStackView:self];  
  10.     NSInteger topPhotoIndex  = [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.borderWidthself.borderWidthself.borderWidthself.borderWidth)];  
  16.           
  17.         for (NSUInteger index = 0; index < numberOfPhotos; index++) {  
  18.   
  19.             UIImage *image = [self.dataSource photoStackView:self photoForIndex:index];  
  20.             CGSize imageSize = image.size;  
  21.             if([self.dataSource respondsToSelector:@selector(photoStackView:photoSizeForIndex:)]){  
  22.                 imageSize = [self.dataSource photoStackView:self photoSizeForIndex:index];  
  23.             }  
  24.             UIImageView *photoImageView     = [[UIImageView alloc] initWithFrame:(CGRect){CGPointZero, imageSize}];  
  25.             photoImageView.image            = image;  
  26.             UIView *view                    = [[UIView alloc] initWithFrame:photoImageView.frame];  
  27.             view.layer.rasterizationScale   = [[UIScreen mainScreen] scale];              
  28.             view.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.                     CGRect photoFrame                = photoImageView.frame;  
  37.                     photoFrame.origin                = CGPointMake(self.borderWidthself.borderWidth);  
  38.                     photoImageView.frame             = photoFrame;  
  39.   
  40.                     view.frame                       = CGRectMake(00, photoImageView.frame.size.width+(self.borderWidth*2), photoImageView.frame.size.height+(self.borderWidth*2));  
  41.                     UIImageView *backgroundImageView = [[UIImageView alloc] initWithFrame:view.frame];  
  42.                     backgroundImageView.image        = borderImage;  
  43.                       
  44.                     [view addSubview:backgroundImageView];  
  45.                 } else {  
  46.                     // if there is no boarder image draw one with the CALayer  
  47.                     view.layer.borderWidth        = self.borderWidth;  
  48.                     view.layer.borderColor        = [[UIColor whiteColor] CGColor];  
  49.                     view.layer.shadowOffset       = CGSizeMake(00);  
  50.                     view.layer.shadowOpacity      = 0.5;  
  51.                 }  
  52.             }  
  53.   
  54.             [view addSubview:photoImageView];  
  55.   
  56.             view.tag    = index;  
  57.             view.center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));  
  58.   
  59.             [photoViewsMutable 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. }  



七。自定义后台显示图片

这个功能就是演示效果里面, 当应用切换到后台后, 我们双击home键后显示后台程序时候, 该应用的显示效果。

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

这就涉及到了Background Fetch的应用。
之前也写过一篇博客专门介绍。 这里就不重复了。




好了。 到这里终于是介绍的差不多了。
当然。 我这里的解析都比较概括, 列举的都是几个关键代码段。
更加详细的还是需要自己去看代码。 注释也写了, 估计没什么问题。 如果有问题, 欢迎联系我。

一口气写了3个小时的博客…  累的够呛的。也希望, 能对你有所帮助。

本文正在参加博客大赛。 如果觉得对你有所帮助, 还望帮忙投下票。 多谢。 

投票链接: http://vote.blog.csdn.net/Article/Details?articleid=37825177 (投票按钮在最下方)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/194018.html原文链接:https://javaforall.net

(0)
上一篇 2025年11月14日 上午8:22
下一篇 2025年11月14日 上午9:01


相关推荐

  • 二叉树的基本性质及证明

    二叉树的基本性质及证明性质1:一棵非空二叉树的第i层上最多有2^(i-1)个结点,(i>=1)。性质2:一棵深度为k的二叉树中,最多具有2^k-1个结点,最少有k个结点。性质3:对于一棵非空的二叉树,度为0的结点(即叶子结点)总比度为1的结点多一个,即叶子结点数为n0,度为2的结点数为n2,则有n0=n2+1。证明:如果n0表示度为0(即叶子结点)的结点数,用n1表示度为1的结点数,n2表示度为2的结点数,

    2022年5月31日
    40
  • VC编程入门浅谈「建议收藏」

    VC编程入门浅谈「建议收藏」
    学VC并不是传说的那么难,可不下些功夫是学不成的。学编程急不得,没有编程的基础知识上来就学VC肯定碰一头灰,说VC难就难在这点上了。如果硬上,意志坚强的话还能挺过来,但最后还得回头来补习基础知识。意志不坚强的话,很有可能就此放弃,并留下一个VC难得不得了的印象。

      其实,只要踏踏实实一步一步来,学VC很简单。对于没有编程基础的人首先要学习编程的基础知识,如变量,语句,基本的算法等,然后写一些小的程序,实现些常用算法对自己的思维是很好的锻炼,对以后的学习大有好处。起码要能排

    2022年6月17日
    33
  • ActivityManager的作用

    ActivityManager的作用ActivityMana 在操作系统中有重要的作用 本文利用操作系统源码 逐步理清 ActivityMana 的框架 并从静态类结构图和动态序列图两个角度分别进行剖析 从而帮助开发人员加强对系统框架及进程通信机制的理解 ActivityMana 的作用参照 SDK 的说明 可见 ActivityMana 的功能是与系统中所有运行着的 Activity 交互提供了接口 主要的接口围绕着运

    2026年3月19日
    2
  • 写文章还在手动配图?这个Skill让AI从分析到排版全包,连预览都给你做好了!

    写文章还在手动配图?这个Skill让AI从分析到排版全包,连预览都给你做好了!

    2026年3月12日
    3
  • 2021年软件测试工具总结——单元测试工具

    2021年软件测试工具总结——单元测试工具在应用程序中 单元是具有一个或多个输入和单个输出的软件中最小可测试部分 单元测试是一种测试软件代码单元的方法 通常包括一个或两个输入 产生一个输出 单元测试主要关注独立模块的功能正确性 目的是确保每个单元都按照预期的方式运行 要进行单元测试 开发人员需要编写测试代码 单元测试有手动和自动化测试两种类型 自动化通常是首选的方法 可以为开发人员节省大量的时间和精力 单元测试是自动化测试金字塔模型中占比最大的测试类型 做好单元测试对于保证软件产品的质量非常重要 单元测试可以 及早发现软件中的缺陷并

    2026年3月20日
    1
  • transferto方法的应用_NIO的transferTo方法

    transferto方法的应用_NIO的transferTo方法大家好 我最近在做 NIO 为什么我使用 NIO 的 transferTo 方法貌似数据没有加载到管道求大神指点 packagecom etwin opps policy mvc importjava io RandomAccess importjava nio ByteBuffer importjava nio channels FileChannel importorg slf4j Lo

    2026年3月17日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号