美女圖片採集器 (源代碼+解析)


前言:


有一段時間沒寫博客了, "持之以恆"徽章都暗了, 實在不該。 前一段確實比較忙, ...小小地給自己的懶找個借口吧。

大二即將結束, 學習iOS也有一段時間了。今天抽點時間, 開源一個前幾天剛上傳的App里面的一個功能, RT, 美女圖片採集器。   美女.. 相信沒有人不喜歡吧, 基於此, 這個小Demo應運而生。


注: 


本文正在參加博客大賽。 假設認為對你有所幫助, 還望幫忙投下票。 多謝。

 

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

效果演示:




看到這里, 假設還有興趣學習的話, 能夠先到我的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)
@property (nonatomic,strong) ASIHTTPRequest *testRequest;

NSString* urlString = [NSString stringWithFormat:@"http://image.baidu.com/channel/listjson?pn=%d&rn=10&tag1=美女&tag2=%@", nowPage, [chooseArr objectAtIndex:nowChoose]];

urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlString];
testRequest = [ASIHTTPRequest requestWithURL:url];
[testRequest setDelegate:self];
[testRequest startAsynchronous];

就可以正常調用API。

至於怎樣處理返回的數據, 以下再詳細講。


二。

JSON格式數據解析

一般的數據格式有 XMLJSON, 這里由於調用百度圖片API返回的數據格式是JSON, 所以我們僅僅要解析JSON就可以。
調用API成功后, 它會自己主動運行這個函數
#pragma mark - 載入數據完成
- (void)requestFinished:(ASIHTTPRequest *)request
我們僅僅須要在這里解析數據, 使用數據就可以。

這種方法返回的數據是二進制格式的NSData, 我們須要手動轉為UTF8編碼。能夠這樣獲取:
//當以二進制讀取返回內容時用這種方法
    NSData *responseData = [request responseData];
    NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];

接下去就是奇妙的時候了, 對於這種一個字符串, 假設直接打印, 你可能會看得雲里霧里的, json格式而且沒有又一次排列。
可是我們能夠使用JsonKit來直接解析。(文件在json解析目錄中)

僅僅需這樣一條語句就可以:
self.testDic = [responseString objectFromJSONString];

打印解析后的數據例如以下:



至於須要哪些, 直接取就好了。比方. 我們這里須要獲取到圖片的標題. url, 寬度, 高度
NSMutableDictionary *nowDic = [[NSMutableDictionary alloc]init];
[nowDic setObject:[[array objectAtIndex:i]objectForKey:@"image_url"] forKey:@"image_url"];
[nowDic setObject:[[array objectAtIndex:i]objectForKey:@"image_width"] forKey:@"image_width"];
[nowDic setObject:[[array objectAtIndex:i]objectForKey:@"image_height"] forKey:@"image_height"];
[nowDic setObject:[[array objectAtIndex:i]objectForKey:@"desc"] forKey:@"desc"];

[picArray addObject:nowDic];


三。圖片異步下載+離線緩存


這里提一下SDWebImage, 我們將會使用它來實現。

詳細使用參見:SDWebImage 筆記

在解析完json數據后, 我們會獲取到圖片相應的url。
我們能夠通過訪問url獲取圖片。 
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;
這是SDWebImage給我們提供的一個函數. 通過調用它, 我們能夠實現異步下載和離線緩存。


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


異步下載,離線緩存效果:(離線緩存能夠到應用沙盒中查看)




四。

圖片基本操作(縮放, 刪除, 加入, 保存到本地)


這里涉及的主要是一些常規操作, 包含縮放, 刪除, 加入, 保存到本地等。
至於刪除, 通常是長按刪除, 僅僅要在圖片上加上長按手勢響應就可以。然后彈出一個對話框, 提示用戶是否刪除。確定刪除后, 從沙盒中清除緩存就可以。
加入手勢方法:
//長按
UILongPressGestureRecognizer *longRecognizer;
longRecognizer = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(handleSingleLongFrom:)];
[self addGestureRecognizer:longRecognizer];

從視圖和沙盒中刪除
        //從當前視圖中刪除
        [testArr removeObject:data];
        //刷新數據
        __weak picVC *blockSelf = self;
        [blockSelf.waterView refreshView:testArr];
        [blockSelf.waterView.infiniteScrollingView stopAnimating];
        
        //從沙盒中刪除
        //打開沙盒
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
        NSString * namePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"savedPicInfo_%d.plist",nowChoose]];
        NSMutableArray *picArray = [[NSMutableArray alloc] initWithContentsOfFile:namePath];
        
        for (int i=0; i<[picArray count]; i++)
        {
            if ([[[picArray objectAtIndex:i]objectForKey:@"image_url"] isEqualToString:data.thumbURL])
            {
                [picArray removeObjectAtIndex:i];
                break;
            }
        }
        [picArray writeToFile:namePath atomically:YES];

至於縮放, 首先要彈出一個全屏顯示的視圖。
像這樣:
//單擊, 顯示大圖
-(void)showImage:(ImageInfo*)data
{
    NSURL *url = [NSURL URLWithString:data.thumbURL];
    [clickImage setImageWithURL:url placeholderImage:nil];
    TGRImageViewController *viewController = [[TGRImageViewController alloc] initWithImage:clickImage.image setImageInfo:data];
    viewController.transitioningDelegate = self;
    [self presentViewController:viewController animated:YES completion:nil];
}

本質就是調用presentViewController:viewController。
當然。我們能夠給新視圖的顯示加上動畫效果, 例如以下:
#pragma mark - UIViewControllerTransitioningDelegate methods
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
    if ([presented isKindOfClass:TGRImageViewController.class]) {
        return [[TGRImageZoomAnimationController alloc] initWithReferenceImageView:clickImage];
    }
    return nil;
}

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
    if ([dismissed isKindOfClass:TGRImageViewController.class]) {
        return [[TGRImageZoomAnimationController alloc] initWithReferenceImageView:clickImage];
    }
    return nil;
}


然后, 在新視圖中, 加入點擊移除, 長按彈出新操作, 雙指移動縮放手勢就可以。

詳細實現例如以下:
#pragma mark - Private methods

- (void)longPress:(UITapGestureRecognizer *)tapGestureRecognizer
{
    
    if(tapGestureRecognizer.state == UIGestureRecognizerStateBegan)
    {
        [self popupActionSheet];
    }
}

- (IBAction)handleSingleTap:(UITapGestureRecognizer *)tapGestureRecognizer {
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (IBAction)handleDoubleTap:(UITapGestureRecognizer *)tapGestureRecognizer {
    if (self.scrollView.zoomScale == self.scrollView.minimumZoomScale) {
        // Zoom in
        CGPoint center = [tapGestureRecognizer locationInView:self.scrollView];
        CGSize size = CGSizeMake(self.scrollView.bounds.size.width / self.scrollView.maximumZoomScale,
                                 self.scrollView.bounds.size.height / self.scrollView.maximumZoomScale);
        CGRect rect = CGRectMake(center.x - (size.width / 2.0), center.y - (size.height / 2.0), size.width, size.height);
        [self.scrollView zoomToRect:rect animated:YES];
    }
    else {
        // Zoom out
        [self.scrollView zoomToRect:self.scrollView.bounds animated:YES];
    }
}



五。

下拉刷新, 上提載入

這個功能詳細在瀏覽圖片的時候使用。 代碼在picVC中。

可是由於我之前專門寫過一篇這種博客。 就不再反復了。


六。幻燈片放映

顧名思義, 就是能夠自己主動播放收藏過的美女圖片..  
這里的原理是利用UIView的動畫, 不斷切換顯示圖片和顯示效果。

切換效果例如以下:
    _transitionOptions= @[[NSNumber numberWithInteger:UIViewAnimationOptionTransitionFlipFromLeft],
                          [NSNumber numberWithInteger:UIViewAnimationOptionTransitionFlipFromRight],
                          [NSNumber numberWithInteger:UIViewAnimationOptionTransitionCurlUp],
                          [NSNumber numberWithInteger:UIViewAnimationOptionTransitionCurlDown],
                          [NSNumber numberWithInteger:UIViewAnimationOptionTransitionCrossDissolve],
                          [NSNumber numberWithInteger:UIViewAnimationOptionTransitionFlipFromTop],
                          [NSNumber numberWithInteger:UIViewAnimationCurveEaseIn],
                          [NSNumber numberWithInteger:UIViewAnimationCurveEaseOut],
                          [NSNumber numberWithInteger:UIViewAnimationCurveLinear],
                          [NSNumber numberWithInteger:UIViewAnimationOptionAllowAnimatedContent],
                          [NSNumber numberWithInteger:UIViewAnimationOptionOverrideInheritedCurve],
                          [NSNumber numberWithInteger:UIViewAnimationOptionTransitionFlipFromTop],
                          [NSNumber numberWithInteger:UIViewAnimationOptionTransitionFlipFromBottom]];

然后切換圖片的時候, 實現例如以下代碼就可以。

 (詳細參見PhotoStackView)

-(void)reloadData {
    
    if (!self.dataSource) {
        //exit if data source has not been set up yet
        self.photoViews = nil;
        return;
    }
    
    NSInteger numberOfPhotos = [self.dataSource numberOfPhotosInPhotoStackView:self];
    NSInteger topPhotoIndex  = [self indexOfTopPhoto]; // Keeping track of current photo's top index so that it remains on top if new photos are added
    
    if(numberOfPhotos > 0) {

        NSMutableArray *photoViewsMutable   = [[NSMutableArray alloc] initWithCapacity:numberOfPhotos];
        UIImage *borderImage                = [self.borderImage resizableImageWithCapInsets:UIEdgeInsetsMake(self.borderWidth, self.borderWidth, self.borderWidth, self.borderWidth)];
        
        for (NSUInteger index = 0; index < numberOfPhotos; index++) {

            UIImage *image = [self.dataSource photoStackView:self photoForIndex:index];
            CGSize imageSize = image.size;
            if([self.dataSource respondsToSelector:@selector(photoStackView:photoSizeForIndex:)]){
                imageSize = [self.dataSource photoStackView:self photoSizeForIndex:index];
            }
            UIImageView *photoImageView     = [[UIImageView alloc] initWithFrame:(CGRect){CGPointZero, imageSize}];
            photoImageView.image            = image;
            UIView *view                    = [[UIView alloc] initWithFrame:photoImageView.frame];
            view.layer.rasterizationScale   = [[UIScreen mainScreen] scale];            
            view.layer.shouldRasterize      = YES; // rasterize the view for faster drawing and smooth edges

            if (self.showBorder) {
                
                // Add the background image
                if (borderImage) {
                    // If there is a border image, we need to add a background image view, and add some padding around the photo for the border

                    CGRect photoFrame                = photoImageView.frame;
                    photoFrame.origin                = CGPointMake(self.borderWidth, self.borderWidth);
                    photoImageView.frame             = photoFrame;

                    view.frame                       = CGRectMake(0, 0, photoImageView.frame.size.width+(self.borderWidth*2), photoImageView.frame.size.height+(self.borderWidth*2));
                    UIImageView *backgroundImageView = [[UIImageView alloc] initWithFrame:view.frame];
                    backgroundImageView.image        = borderImage;
                    
                    [view addSubview:backgroundImageView];
                } else {
                    // if there is no boarder image draw one with the CALayer
                    view.layer.borderWidth        = self.borderWidth;
                    view.layer.borderColor        = [[UIColor whiteColor] CGColor];
                    view.layer.shadowOffset       = CGSizeMake(0, 0);
                    view.layer.shadowOpacity      = 0.5;
                }
            }

            [view addSubview:photoImageView];

            view.tag    = index;
            view.center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));

            [photoViewsMutable addObject:view];
            
        }

        // Photo views are added to subview in the photoView setter
        self.photoViews = photoViewsMutable; photoViewsMutable = nil;
        [self goToPhotoAtIndex:topPhotoIndex];
        
    }
    
}



七。自己定義后台顯示圖片

這個功能就是演示效果里面, 當應用切換到后台后, 我們雙擊home鍵后顯示后台程序時候, 該應用的顯示效果。
比方..  有時候我們瀏覽的圖片尺度比較大.. 然后切到后台的時候, 就希望把它隱藏起來..  

這就涉及到了Background Fetch的應用。
之前也寫過一篇博客專門介紹。 這里就不反復了。





好了。 到這里最終是介紹的幾乎相同了。
當然。 我這里的解析都比較概括, 列舉的都是幾個關鍵代碼段。
更加詳細的還是須要自己去看代碼。 凝視也寫了, 預計沒什么問題。 假設有問題, 歡迎聯系我。

一口氣寫了3個小時的博客...  累的夠嗆的。也希望, 能對你有所幫助。


本文正在參加博客大賽。

假設認為對你有所幫助, 還望幫忙投下票。

多謝。 

投票鏈接: http://vote.blog.csdn.net/Article/Details?

articleid=37825177 (投票button在最下方)



學習的路上, 與君共勉。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM